tttls1.3 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +16 -0
  5. data/.travis.yml +8 -0
  6. data/Gemfile +13 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +52 -0
  9. data/Rakefile +133 -0
  10. data/example/helper.rb +17 -0
  11. data/example/https_client.rb +32 -0
  12. data/example/https_client_using_0rtt.rb +64 -0
  13. data/example/https_client_using_hrr.rb +35 -0
  14. data/example/https_client_using_ticket.rb +56 -0
  15. data/lib/tttls1.3/cipher_suites.rb +102 -0
  16. data/lib/tttls1.3/client.rb +745 -0
  17. data/lib/tttls1.3/connection.rb +380 -0
  18. data/lib/tttls1.3/cryptograph/aead.rb +118 -0
  19. data/lib/tttls1.3/cryptograph/passer.rb +22 -0
  20. data/lib/tttls1.3/cryptograph.rb +3 -0
  21. data/lib/tttls1.3/error.rb +22 -0
  22. data/lib/tttls1.3/key_schedule.rb +242 -0
  23. data/lib/tttls1.3/message/alert.rb +86 -0
  24. data/lib/tttls1.3/message/application_data.rb +27 -0
  25. data/lib/tttls1.3/message/certificate.rb +121 -0
  26. data/lib/tttls1.3/message/certificate_verify.rb +59 -0
  27. data/lib/tttls1.3/message/change_cipher_spec.rb +26 -0
  28. data/lib/tttls1.3/message/client_hello.rb +100 -0
  29. data/lib/tttls1.3/message/encrypted_extensions.rb +65 -0
  30. data/lib/tttls1.3/message/end_of_early_data.rb +29 -0
  31. data/lib/tttls1.3/message/extension/alpn.rb +70 -0
  32. data/lib/tttls1.3/message/extension/cookie.rb +47 -0
  33. data/lib/tttls1.3/message/extension/early_data_indication.rb +58 -0
  34. data/lib/tttls1.3/message/extension/key_share.rb +236 -0
  35. data/lib/tttls1.3/message/extension/pre_shared_key.rb +205 -0
  36. data/lib/tttls1.3/message/extension/psk_key_exchange_modes.rb +54 -0
  37. data/lib/tttls1.3/message/extension/record_size_limit.rb +46 -0
  38. data/lib/tttls1.3/message/extension/server_name.rb +91 -0
  39. data/lib/tttls1.3/message/extension/signature_algorithms.rb +69 -0
  40. data/lib/tttls1.3/message/extension/signature_algorithms_cert.rb +25 -0
  41. data/lib/tttls1.3/message/extension/status_request.rb +106 -0
  42. data/lib/tttls1.3/message/extension/supported_groups.rb +145 -0
  43. data/lib/tttls1.3/message/extension/supported_versions.rb +98 -0
  44. data/lib/tttls1.3/message/extension/unknown_extension.rb +38 -0
  45. data/lib/tttls1.3/message/extensions.rb +173 -0
  46. data/lib/tttls1.3/message/finished.rb +44 -0
  47. data/lib/tttls1.3/message/new_session_ticket.rb +89 -0
  48. data/lib/tttls1.3/message/record.rb +232 -0
  49. data/lib/tttls1.3/message/server_hello.rb +116 -0
  50. data/lib/tttls1.3/message.rb +48 -0
  51. data/lib/tttls1.3/sequence_number.rb +31 -0
  52. data/lib/tttls1.3/signature_scheme.rb +31 -0
  53. data/lib/tttls1.3/transcript.rb +69 -0
  54. data/lib/tttls1.3/utils.rb +91 -0
  55. data/lib/tttls1.3/version.rb +5 -0
  56. data/lib/tttls1.3.rb +16 -0
  57. data/spec/aead_spec.rb +95 -0
  58. data/spec/alert_spec.rb +54 -0
  59. data/spec/alpn_spec.rb +55 -0
  60. data/spec/application_data_spec.rb +26 -0
  61. data/spec/certificate_spec.rb +55 -0
  62. data/spec/certificate_verify_spec.rb +51 -0
  63. data/spec/change_cipher_spec_spec.rb +26 -0
  64. data/spec/cipher_suites_spec.rb +39 -0
  65. data/spec/client_hello_spec.rb +83 -0
  66. data/spec/client_spec.rb +319 -0
  67. data/spec/connection_spec.rb +114 -0
  68. data/spec/cookie_spec.rb +98 -0
  69. data/spec/early_data_indication_spec.rb +64 -0
  70. data/spec/encrypted_extensions_spec.rb +94 -0
  71. data/spec/error_spec.rb +18 -0
  72. data/spec/extensions_spec.rb +170 -0
  73. data/spec/finished_spec.rb +55 -0
  74. data/spec/key_schedule_spec.rb +198 -0
  75. data/spec/key_share_spec.rb +199 -0
  76. data/spec/new_session_ticket_spec.rb +80 -0
  77. data/spec/pre_shared_key_spec.rb +167 -0
  78. data/spec/psk_key_exchange_modes_spec.rb +45 -0
  79. data/spec/record_size_limit_spec.rb +61 -0
  80. data/spec/record_spec.rb +105 -0
  81. data/spec/server_hello_spec.rb +101 -0
  82. data/spec/server_name_spec.rb +110 -0
  83. data/spec/signature_algorithms_cert_spec.rb +73 -0
  84. data/spec/signature_algorithms_spec.rb +100 -0
  85. data/spec/spec_helper.rb +872 -0
  86. data/spec/status_request_spec.rb +73 -0
  87. data/spec/supported_groups_spec.rb +79 -0
  88. data/spec/supported_versions_spec.rb +136 -0
  89. data/spec/transcript_spec.rb +69 -0
  90. data/spec/unknown_extension_spec.rb +90 -0
  91. data/spec/utils_spec.rb +215 -0
  92. data/tttls1.3.gemspec +25 -0
  93. metadata +197 -0
@@ -0,0 +1,80 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe NewSessionTicket do
8
+ context 'new_session_ticket' do
9
+ let(:ticket_lifetime) do
10
+ 7200 # two_hours
11
+ end
12
+
13
+ let(:ticket_age_add) do
14
+ OpenSSL::Random.random_bytes(4)
15
+ end
16
+
17
+ let(:ticket_nonce) do
18
+ "\x00" * 255
19
+ end
20
+
21
+ let(:ticket) do
22
+ OpenSSL::Random.random_bytes(255)
23
+ end
24
+
25
+ let(:message) do
26
+ NewSessionTicket.new(ticket_lifetime: ticket_lifetime,
27
+ ticket_age_add: ticket_age_add,
28
+ ticket_nonce: ticket_nonce,
29
+ ticket: ticket)
30
+ end
31
+
32
+ it 'should be generated' do
33
+ expect(message.msg_type).to eq HandshakeType::NEW_SESSION_TICKET
34
+ expect(message.ticket_lifetime).to eq ticket_lifetime
35
+ expect(message.ticket_age_add).to eq ticket_age_add
36
+ expect(message.ticket_nonce).to eq ticket_nonce
37
+ expect(message.ticket).to eq ticket
38
+ expect(message.extensions).to be_empty
39
+ end
40
+
41
+ it 'should be serialized' do
42
+ expect(message.serialize).to eq HandshakeType::NEW_SESSION_TICKET \
43
+ + 523.to_uint24 \
44
+ + ticket_lifetime.to_uint32 \
45
+ + ticket_age_add \
46
+ + ticket_nonce.prefix_uint8_length \
47
+ + ticket.prefix_uint16_length \
48
+ + Extensions.new.serialize
49
+ end
50
+ end
51
+
52
+ context 'new_session_ticket, invalid ticket_age_add,' do
53
+ let(:message) do
54
+ NewSessionTicket.new(ticket_lifetime: 60 * 60 * 2, # 2 hours
55
+ ticket_age_add: OpenSSL::Random.random_bytes(32),
56
+ ticket_nonce: "\x00" * 255,
57
+ ticket: OpenSSL::Random.random_bytes(255))
58
+ end
59
+
60
+ it 'should not be generated' do
61
+ expect { message }.to raise_error(ErrorAlerts)
62
+ end
63
+ end
64
+
65
+ context 'valid new_session_ticket binary' do
66
+ let(:message) do
67
+ NewSessionTicket.deserialize(TESTBINARY_NEW_SESSION_TICKET)
68
+ end
69
+
70
+ it 'should generate object' do
71
+ expect(message.msg_type).to eq HandshakeType::NEW_SESSION_TICKET
72
+ expect(message.ticket_lifetime).to eq 30
73
+ expect(message.ticket_nonce).to eq "\x00\x00"
74
+ end
75
+
76
+ it 'should generate serializable object' do
77
+ expect(message.serialize).to eq TESTBINARY_NEW_SESSION_TICKET
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,167 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe PreSharedKey do
8
+ context 'valid pre_shared_key of ClientHello' do
9
+ let(:identity) do
10
+ OpenSSL::Random.random_bytes(32)
11
+ end
12
+
13
+ let(:obfuscated_ticket_age) do
14
+ OpenSSL::BN.rand_range(1 << 32).to_i
15
+ end
16
+
17
+ let(:binders) do
18
+ [
19
+ OpenSSL::Random.random_bytes(32)
20
+ ]
21
+ end
22
+
23
+ let(:identities) do
24
+ [
25
+ PskIdentity.new(
26
+ identity: identity,
27
+ obfuscated_ticket_age: obfuscated_ticket_age
28
+ )
29
+ ]
30
+ end
31
+
32
+ let(:offered_psks) do
33
+ OfferedPsks.new(
34
+ identities: identities,
35
+ binders: binders
36
+ )
37
+ end
38
+
39
+ let(:extension) do
40
+ PreSharedKey.new(msg_type: HandshakeType::CLIENT_HELLO,
41
+ offered_psks: offered_psks)
42
+ end
43
+
44
+ it 'should be generated' do
45
+ expect(extension.msg_type).to eq HandshakeType::CLIENT_HELLO
46
+ expect(extension.extension_type).to eq ExtensionType::PRE_SHARED_KEY
47
+ expect(extension.offered_psks).to eq offered_psks
48
+ expect(extension.selected_identity).to be_nil
49
+ end
50
+
51
+ it 'should be serialized' do
52
+ expect(extension.serialize).to eq ExtensionType::PRE_SHARED_KEY \
53
+ + 75.to_uint16 \
54
+ + 38.to_uint16 \
55
+ + 32.to_uint16 \
56
+ + identity \
57
+ + obfuscated_ticket_age.to_uint32 \
58
+ + 33.to_uint16 \
59
+ + "\x20" \
60
+ + binders.join
61
+ end
62
+ end
63
+
64
+ context 'valid pre_shared_key, ClientHello,' do
65
+ let(:identity_1) do
66
+ OpenSSL::Random.random_bytes(32)
67
+ end
68
+ let(:identity_2) do
69
+ OpenSSL::Random.random_bytes(32)
70
+ end
71
+
72
+ let(:obfuscated_ticket_age_1) do
73
+ OpenSSL::BN.rand_range(1 << 32).to_i
74
+ end
75
+ let(:obfuscated_ticket_age_2) do
76
+ OpenSSL::BN.rand_range(1 << 32).to_i
77
+ end
78
+
79
+ let(:binders) do
80
+ [
81
+ OpenSSL::Random.random_bytes(32),
82
+ OpenSSL::Random.random_bytes(32)
83
+ ]
84
+ end
85
+
86
+ let(:identities) do
87
+ [
88
+ PskIdentity.new(
89
+ identity: identity_1,
90
+ obfuscated_ticket_age: obfuscated_ticket_age_1
91
+ ),
92
+ PskIdentity.new(
93
+ identity: identity_2,
94
+ obfuscated_ticket_age: obfuscated_ticket_age_2
95
+ )
96
+ ]
97
+ end
98
+
99
+ let(:offered_psks) do
100
+ OfferedPsks.new(
101
+ identities: identities,
102
+ binders: binders
103
+ )
104
+ end
105
+
106
+ let(:extension) do
107
+ PreSharedKey.new(msg_type: HandshakeType::CLIENT_HELLO,
108
+ offered_psks: offered_psks)
109
+ end
110
+
111
+ it 'should be generated' do
112
+ expect(extension.msg_type).to eq HandshakeType::CLIENT_HELLO
113
+ expect(extension.extension_type).to eq ExtensionType::PRE_SHARED_KEY
114
+ expect(extension.offered_psks).to eq offered_psks
115
+ expect(extension.selected_identity).to be_nil
116
+ end
117
+
118
+ it 'should be serialized' do
119
+ expect(extension.serialize).to eq ExtensionType::PRE_SHARED_KEY \
120
+ + 146.to_uint16 \
121
+ + 76.to_uint16 \
122
+ + identity_1.prefix_uint16_length \
123
+ + obfuscated_ticket_age_1.to_uint32 \
124
+ + identity_2.prefix_uint16_length \
125
+ + obfuscated_ticket_age_2.to_uint32 \
126
+ + 66.to_uint16 \
127
+ + binders[0].prefix_uint8_length \
128
+ + binders[1].prefix_uint8_length
129
+ end
130
+ end
131
+
132
+ context 'valid pre_shared_key binary, ClientHello,' do
133
+ let(:extension) do
134
+ PreSharedKey.deserialize(TESTBINARY_PRE_SHARED_KEY_CH,
135
+ HandshakeType::CLIENT_HELLO)
136
+ end
137
+
138
+ it 'should generate valid object' do
139
+ expect(extension.msg_type).to eq HandshakeType::CLIENT_HELLO
140
+ expect(extension.extension_type).to eq ExtensionType::PRE_SHARED_KEY
141
+ end
142
+
143
+ it 'should generate valid serializable object' do
144
+ expect(extension.serialize)
145
+ .to eq ExtensionType::PRE_SHARED_KEY \
146
+ + TESTBINARY_PRE_SHARED_KEY_CH.prefix_uint16_length
147
+ end
148
+ end
149
+
150
+ context 'valid pre_shared_key binary, ServerHello,' do
151
+ let(:extension) do
152
+ PreSharedKey.deserialize(TESTBINARY_PRE_SHARED_KEY_SH,
153
+ HandshakeType::SERVER_HELLO)
154
+ end
155
+
156
+ it 'should generate valid object' do
157
+ expect(extension.msg_type).to eq HandshakeType::SERVER_HELLO
158
+ expect(extension.extension_type).to eq ExtensionType::PRE_SHARED_KEY
159
+ end
160
+
161
+ it 'should generate valid serializable object' do
162
+ expect(extension.serialize)
163
+ .to eq ExtensionType::PRE_SHARED_KEY \
164
+ + TESTBINARY_PRE_SHARED_KEY_SH.prefix_uint16_length
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe PskKeyExchangeModes do
8
+ context 'valid psk_key_exchange_modes' do
9
+ let(:extension) do
10
+ PskKeyExchangeModes.new([PskKeyExchangeMode::PSK_KE,
11
+ PskKeyExchangeMode::PSK_DHE_KE])
12
+ end
13
+
14
+ it 'should generate valid psk_key_exchange_modes' do
15
+ expect(extension.extension_type)
16
+ .to eq ExtensionType::PSK_KEY_EXCHANGE_MODES
17
+ expect(extension.ke_modes).to eq [PskKeyExchangeMode::PSK_KE,
18
+ PskKeyExchangeMode::PSK_DHE_KE]
19
+ expect(extension.serialize)
20
+ .to eq ExtensionType::PSK_KEY_EXCHANGE_MODES \
21
+ + 3.to_uint16 \
22
+ + [PskKeyExchangeMode::PSK_KE,
23
+ PskKeyExchangeMode::PSK_DHE_KE].join.prefix_uint8_length
24
+ end
25
+ end
26
+
27
+ context 'valid psk_key_exchange_modes binary' do
28
+ let(:extension) do
29
+ PskKeyExchangeModes.deserialize(TESTBINARY_PSK_KEY_EXCHANGE_MODES)
30
+ end
31
+
32
+ it 'should generate valid object' do
33
+ expect(extension.extension_type)
34
+ .to eq ExtensionType::PSK_KEY_EXCHANGE_MODES
35
+ expect(extension.ke_modes).to eq [PskKeyExchangeMode::PSK_KE,
36
+ PskKeyExchangeMode::PSK_DHE_KE]
37
+ end
38
+
39
+ it 'should generate serializable object' do
40
+ expect(extension.serialize)
41
+ .to eq ExtensionType::PSK_KEY_EXCHANGE_MODES \
42
+ + TESTBINARY_PSK_KEY_EXCHANGE_MODES.prefix_uint16_length
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe RecordSizeLimit do
8
+ context 'vailid record_size_limit' do
9
+ let(:extension) do
10
+ RecordSizeLimit.new(2**14)
11
+ end
12
+
13
+ it 'should be generated' do
14
+ expect(extension.extension_type).to eq ExtensionType::RECORD_SIZE_LIMIT
15
+ expect(extension.record_size_limit).to eq 2**14
16
+ end
17
+
18
+ it 'should be serialized' do
19
+ expect(extension.serialize).to eq ExtensionType::RECORD_SIZE_LIMIT \
20
+ + 2.to_uint16 \
21
+ + (2**14).to_uint16
22
+ end
23
+ end
24
+
25
+ context 'invalid record_size_limit' do
26
+ let(:extension) do
27
+ RecordSizeLimit.new(63)
28
+ end
29
+
30
+ it 'should not generated' do
31
+ expect { extension }.to raise_error(ErrorAlerts)
32
+ end
33
+ end
34
+
35
+ context 'valid record_size_limit binary' do
36
+ let(:extension) do
37
+ RecordSizeLimit.deserialize(TESTBINARY_RECORD_SIZE_LIMIT)
38
+ end
39
+
40
+ it 'should generate valid object' do
41
+ expect(extension.extension_type).to eq ExtensionType::RECORD_SIZE_LIMIT
42
+ expect(extension.record_size_limit).to eq 2**14
43
+ end
44
+
45
+ it 'should generate serializable object' do
46
+ expect(extension.serialize)
47
+ .to eq ExtensionType::RECORD_SIZE_LIMIT \
48
+ + TESTBINARY_RECORD_SIZE_LIMIT.prefix_uint16_length
49
+ end
50
+ end
51
+
52
+ context 'invalid record_size_limit binary, too short record_size_limit,' do
53
+ let(:extension) do
54
+ RecordSizeLimit.deserialize(63.to_uint16)
55
+ end
56
+
57
+ it 'should not generate object' do
58
+ expect { extension }.to raise_error(ErrorAlerts)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,105 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe Record do
8
+ context 'valid record' do
9
+ let(:record) do
10
+ Record.new(
11
+ type: ContentType::CCS,
12
+ legacy_record_version: ProtocolVersion::TLS_1_2,
13
+ messages: [ChangeCipherSpec.new],
14
+ cipher: Passer.new
15
+ )
16
+ end
17
+
18
+ it 'should be generated' do
19
+ expect(record.type).to eq ContentType::CCS
20
+ expect(record.legacy_record_version).to eq ProtocolVersion::TLS_1_2
21
+ end
22
+
23
+ it 'should be serialized' do
24
+ expect(record.serialize).to eq ContentType::CCS \
25
+ + ProtocolVersion::TLS_1_2 \
26
+ + 1.to_uint16 \
27
+ + ChangeCipherSpec.new.serialize
28
+ end
29
+ end
30
+
31
+ context 'valid record binary' do
32
+ let(:record) do
33
+ Record.deserialize(TESTBINARY_RECORD_CCS, Passer.new)
34
+ end
35
+
36
+ it 'should generate valid record header and ChangeCipherSpec' do
37
+ expect(record.type).to eq ContentType::CCS
38
+ expect(record.legacy_record_version).to eq ProtocolVersion::TLS_1_2
39
+ end
40
+
41
+ it 'should generate valid serializable object' do
42
+ expect(record.serialize).to eq ContentType::CCS \
43
+ + ProtocolVersion::TLS_1_2 \
44
+ + 1.to_uint16 \
45
+ + ChangeCipherSpec.new.serialize
46
+ end
47
+ end
48
+
49
+ context 'invalid record binary, too short,' do
50
+ let(:record) do
51
+ Record.deserialize(TESTBINARY_RECORD_CCS[0...-1],
52
+ Passer.new)
53
+ end
54
+
55
+ it 'should not generate object' do
56
+ expect { record }.to raise_error(ErrorAlerts)
57
+ end
58
+ end
59
+
60
+ context 'invalid record binary, nil,' do
61
+ let(:record) do
62
+ Record.deserialize(nil, Passer.new)
63
+ end
64
+
65
+ it 'should not generate object' do
66
+ expect { record }.to raise_error(ErrorAlerts)
67
+ end
68
+ end
69
+
70
+ context 'server parameters record binary' do
71
+ let(:record) do
72
+ cipher = Cryptograph::Aead.new(
73
+ cipher_suite: CipherSuite::TLS_AES_128_GCM_SHA256,
74
+ write_key: TESTBINARY_SERVER_PARAMETERS_WRITE_KEY,
75
+ write_iv: TESTBINARY_SERVER_PARAMETERS_WRITE_IV,
76
+ sequence_number: SequenceNumber.new
77
+ )
78
+ Record.deserialize(TESTBINARY_SERVER_PARAMETERS_RECORD, cipher)
79
+ end
80
+
81
+ it 'should generate valid record header' do
82
+ expect(record.type).to eq ContentType::APPLICATION_DATA
83
+ expect(record.legacy_record_version).to eq ProtocolVersion::TLS_1_2
84
+ end
85
+
86
+ it 'should generate valid server parameters' do
87
+ expect(record.messages[0].msg_type)
88
+ .to eq HandshakeType::ENCRYPTED_EXTENSIONS
89
+ expect(record.messages[0].serialize)
90
+ .to eq TESTBINARY_ENCRYPTED_EXTENSIONS
91
+ expect(record.messages[1].msg_type)
92
+ .to eq HandshakeType::CERTIFICATE
93
+ expect(record.messages[1].serialize)
94
+ .to eq TESTBINARY_CERTIFICATE
95
+ expect(record.messages[2].msg_type)
96
+ .to eq HandshakeType::CERTIFICATE_VERIFY
97
+ expect(record.messages[2].serialize)
98
+ .to eq TESTBINARY_CERTIFICATE_VERIFY
99
+ expect(record.messages[3].msg_type)
100
+ .to eq HandshakeType::FINISHED
101
+ expect(record.messages[3].serialize)
102
+ .to eq TESTBINARY_SERVER_FINISHED
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,101 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe ServerHello do
8
+ context 'default server_hello' do
9
+ let(:random) do
10
+ OpenSSL::Random.random_bytes(32)
11
+ end
12
+
13
+ let(:legacy_session_id_echo) do
14
+ Array.new(32, 0).map(&:chr).join
15
+ end
16
+
17
+ let(:cipher_suite) do
18
+ CipherSuite::TLS_AES_256_GCM_SHA384
19
+ end
20
+
21
+ let(:message) do
22
+ ServerHello.new(random: random,
23
+ legacy_session_id_echo: legacy_session_id_echo,
24
+ cipher_suite: cipher_suite)
25
+ end
26
+
27
+ it 'should be generated' do
28
+ expect(message.msg_type).to eq HandshakeType::SERVER_HELLO
29
+ expect(message.legacy_version).to eq ProtocolVersion::TLS_1_2
30
+ expect(message.random).to eq random
31
+ expect(message.legacy_session_id_echo).to eq legacy_session_id_echo
32
+ expect(message.cipher_suite).to eq CipherSuite::TLS_AES_256_GCM_SHA384
33
+ expect(message.legacy_compression_method).to eq "\x00"
34
+ expect(message.extensions).to be_empty
35
+ end
36
+
37
+ it 'should be serialized' do
38
+ expect(message.serialize).to eq HandshakeType::SERVER_HELLO \
39
+ + 72.to_uint24 \
40
+ + ProtocolVersion::TLS_1_2 \
41
+ + random \
42
+ + legacy_session_id_echo.length.to_uint8 \
43
+ + legacy_session_id_echo \
44
+ + cipher_suite \
45
+ + "\x00" \
46
+ + Extensions.new.serialize
47
+ end
48
+ end
49
+
50
+ context 'valid server_hello binary' do
51
+ let(:message) do
52
+ ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
53
+ end
54
+
55
+ it 'should generate valid object' do
56
+ expect(message.msg_type).to eq HandshakeType::SERVER_HELLO
57
+ expect(message.legacy_version).to eq ProtocolVersion::TLS_1_2
58
+ expect(message.cipher_suite).to eq CipherSuite::TLS_AES_128_GCM_SHA256
59
+ expect(message.legacy_compression_method).to eq "\x00"
60
+ end
61
+
62
+ it 'should generate valid serializable object' do
63
+ expect(message.serialize).to eq TESTBINARY_SERVER_HELLO
64
+ end
65
+ end
66
+
67
+ context 'hello_retry_request binary' do
68
+ let(:message) do
69
+ ServerHello.deserialize(TESTBINARY_HRR_HELLO_RETRY_REQUEST)
70
+ end
71
+
72
+ it 'should generate valid object' do
73
+ expect(message.msg_type).to eq HandshakeType::SERVER_HELLO
74
+ expect(message.legacy_version).to eq ProtocolVersion::TLS_1_2
75
+ expect(message.cipher_suite).to eq CipherSuite::TLS_AES_128_GCM_SHA256
76
+ expect(message.legacy_compression_method).to eq "\x00"
77
+ expect(message.hrr?).to be true
78
+ end
79
+
80
+ it 'should generate valid serializable object' do
81
+ expect(message.serialize).to eq TESTBINARY_HRR_HELLO_RETRY_REQUEST
82
+ end
83
+ end
84
+
85
+ context 'valid server_hello binary, 0-RTT,' do
86
+ let(:message) do
87
+ ServerHello.deserialize(TESTBINARY_0_RTT_SERVER_HELLO)
88
+ end
89
+
90
+ it 'should generate valid object' do
91
+ expect(message.msg_type).to eq HandshakeType::SERVER_HELLO
92
+ expect(message.legacy_version).to eq ProtocolVersion::TLS_1_2
93
+ expect(message.cipher_suite).to eq CipherSuite::TLS_AES_128_GCM_SHA256
94
+ expect(message.legacy_compression_method).to eq "\x00"
95
+ end
96
+
97
+ it 'should generate valid serializable object' do
98
+ expect(message.serialize).to eq TESTBINARY_0_RTT_SERVER_HELLO
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,110 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe ServerName do
8
+ context 'valid server_name, example.com,' do
9
+ let(:extension) do
10
+ ServerName.new('example.com')
11
+ end
12
+
13
+ it 'should be generated' do
14
+ expect(extension.extension_type).to eq ExtensionType::SERVER_NAME
15
+ expect(extension.server_name).to eq 'example.com'
16
+ end
17
+
18
+ it 'should be serialized' do
19
+ expect(extension.serialize).to eq ExtensionType::SERVER_NAME \
20
+ + 16.to_uint16 \
21
+ + 14.to_uint16 \
22
+ + NameType::HOST_NAME \
23
+ + 11.to_uint16 \
24
+ + 'example.com'
25
+ end
26
+ end
27
+
28
+ context 'valid server_name, empty HostName,' do
29
+ let(:extension) do
30
+ ServerName.new('')
31
+ end
32
+
33
+ it 'should be generated' do
34
+ expect(extension.extension_type).to eq ExtensionType::SERVER_NAME
35
+ end
36
+
37
+ it 'should be serialized' do
38
+ expect(extension.serialize).to eq ExtensionType::SERVER_NAME \
39
+ + 0.to_uint16
40
+ end
41
+ end
42
+
43
+ context 'invalid server_name, too long HostName,' do
44
+ let(:extension) do
45
+ ServerName.new('a' * (2**16 - 4))
46
+ end
47
+
48
+ it 'should not be generated' do
49
+ expect { extension }.to raise_error(ErrorAlerts)
50
+ end
51
+ end
52
+
53
+ context 'valid server_name binary' do
54
+ let(:extension) do
55
+ ServerName.deserialize(TESTBINARY_SERVER_NAME)
56
+ end
57
+
58
+ it 'should generate valid object' do
59
+ expect(extension.extension_type).to eq ExtensionType::SERVER_NAME
60
+ expect(extension.server_name).to eq 'github.com'
61
+ end
62
+
63
+ it 'should generate serializable object' do
64
+ expect(extension.serialize)
65
+ .to eq ExtensionType::SERVER_NAME \
66
+ + TESTBINARY_SERVER_NAME.prefix_uint16_length
67
+ end
68
+ end
69
+
70
+ context 'invalid server_name binary, malformed binary,' do
71
+ let(:extension) do
72
+ ServerName.deserialize(TESTBINARY_SERVER_NAME[0...-1])
73
+ end
74
+
75
+ it 'should return nil' do
76
+ expect(extension).to be nil
77
+ end
78
+ end
79
+
80
+ context 'invalid server_name binary, unknown NameType,' do
81
+ let(:testbinary) do
82
+ name_type = "\xff"
83
+ binary = name_type + 'example.com'.prefix_uint16_length
84
+ binary.prefix_uint16_length.prefix_uint16_length
85
+ end
86
+
87
+ let(:extension) do
88
+ ServerName.deserialize(testbinary)
89
+ end
90
+
91
+ it 'should return nil' do
92
+ expect(extension).to be nil
93
+ end
94
+ end
95
+
96
+ context 'invalid server_name binary, empty HostName,' do
97
+ let(:testbinary) do
98
+ binary = NameType::HOST_NAME + ''.prefix_uint16_length
99
+ binary.prefix_uint16_length.prefix_uint16_length
100
+ end
101
+
102
+ let(:extension) do
103
+ ServerName.deserialize(testbinary)
104
+ end
105
+
106
+ it 'should return nil' do
107
+ expect(extension).to be nil
108
+ end
109
+ end
110
+ end