tttls1.3 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,319 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe Client do
8
+ context 'client' do
9
+ let(:record) do
10
+ mock_socket = SimpleStream.new
11
+ client = Client.new(mock_socket, 'localhost')
12
+ client.send(:send_client_hello)
13
+ Record.deserialize(mock_socket.read, Cryptograph::Passer.new)
14
+ end
15
+
16
+ it 'should send default ClientHello' do
17
+ expect(record.type).to eq ContentType::HANDSHAKE
18
+
19
+ message = record.messages.first
20
+ expect(message.msg_type).to eq HandshakeType::CLIENT_HELLO
21
+ expect(message.legacy_version).to eq ProtocolVersion::TLS_1_2
22
+ expect(message.cipher_suites).to eq DEFAULT_CH_CIPHER_SUITES
23
+ expect(message.legacy_compression_methods).to eq ["\x00"]
24
+ end
25
+ end
26
+
27
+ context 'client' do
28
+ let(:message) do
29
+ msg_len = TESTBINARY_SERVER_HELLO.length
30
+ mock_socket = SimpleStream.new
31
+ mock_socket.write(ContentType::HANDSHAKE \
32
+ + ProtocolVersion::TLS_1_2 \
33
+ + msg_len.to_uint16 \
34
+ + TESTBINARY_SERVER_HELLO)
35
+ client = Client.new(mock_socket, 'localhost')
36
+ client.send(:recv_server_hello)
37
+ end
38
+
39
+ it 'should receive ServerHello' do
40
+ expect(message.msg_type).to eq HandshakeType::SERVER_HELLO
41
+ expect(message.legacy_version).to eq ProtocolVersion::TLS_1_2
42
+ expect(message.cipher_suite).to eq CipherSuite::TLS_AES_128_GCM_SHA256
43
+ expect(message.legacy_compression_method).to eq "\x00"
44
+ end
45
+ end
46
+
47
+ context 'client' do
48
+ let(:client) do
49
+ mock_socket = SimpleStream.new
50
+ mock_socket.write(TESTBINARY_SERVER_PARAMETERS_RECORD)
51
+ client = Client.new(mock_socket, 'localhost')
52
+ client.instance_variable_set(:@cipher_suite,
53
+ CipherSuite::TLS_AES_128_GCM_SHA256)
54
+ read_seq_num = SequenceNumber.new
55
+ cipher = Cryptograph::Aead.new(
56
+ cipher_suite: CipherSuite::TLS_AES_128_GCM_SHA256,
57
+ write_key: TESTBINARY_SERVER_PARAMETERS_WRITE_KEY,
58
+ write_iv: TESTBINARY_SERVER_PARAMETERS_WRITE_IV,
59
+ sequence_number: read_seq_num
60
+ )
61
+ client.instance_variable_set(:@read_cipher, cipher)
62
+ client.instance_variable_set(:@read_seq_num, read_seq_num)
63
+ client
64
+ end
65
+
66
+ it 'should receive EncryptedExtensions' do
67
+ message = client.send(:recv_encrypted_extensions)
68
+ expect(message.msg_type).to eq HandshakeType::ENCRYPTED_EXTENSIONS
69
+ end
70
+
71
+ it 'should receive Certificate' do
72
+ client.send(:recv_encrypted_extensions) # to skip
73
+ message = client.send(:recv_certificate)
74
+ expect(message.msg_type).to eq HandshakeType::CERTIFICATE
75
+ end
76
+
77
+ it 'should receive CertificateVerify' do
78
+ client.send(:recv_encrypted_extensions) # to skip
79
+ client.send(:recv_certificate) # to skip
80
+ message = client.send(:recv_certificate_verify)
81
+ expect(message.msg_type).to eq HandshakeType::CERTIFICATE_VERIFY
82
+ end
83
+
84
+ it 'should receive Finished' do
85
+ client.send(:recv_encrypted_extensions) # to skip
86
+ client.send(:recv_certificate) # to skip
87
+ client.send(:recv_certificate_verify) # to skip
88
+ message = client.send(:recv_finished)
89
+ expect(message.msg_type).to eq HandshakeType::FINISHED
90
+ end
91
+ end
92
+
93
+ context 'client' do
94
+ let(:record) do
95
+ mock_socket = SimpleStream.new
96
+ client = Client.new(mock_socket, 'localhost')
97
+ transcript = Transcript.new
98
+ transcript.merge!(
99
+ CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
100
+ SH => ServerHello.deserialize(TESTBINARY_SERVER_HELLO),
101
+ EE => EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS),
102
+ CT => Certificate.deserialize(TESTBINARY_CERTIFICATE),
103
+ CV => CertificateVerify.deserialize(TESTBINARY_CERTIFICATE_VERIFY),
104
+ SF => Finished.deserialize(TESTBINARY_SERVER_FINISHED)
105
+ )
106
+ client.instance_variable_set(:@transcript, transcript)
107
+ ks = KeySchedule.new(shared_secret: TESTBINARY_SHARED_SECRET,
108
+ cipher_suite: CipherSuite::TLS_AES_128_GCM_SHA256,
109
+ transcript: transcript)
110
+ client.instance_variable_set(:@key_schedule, ks)
111
+ client.instance_variable_set(:@cipher_suite,
112
+ CipherSuite::TLS_AES_128_GCM_SHA256)
113
+ write_seq_num = SequenceNumber.new
114
+ write_cipher = Cryptograph::Aead.new(
115
+ cipher_suite: CipherSuite::TLS_AES_128_GCM_SHA256,
116
+ write_key: TESTBINARY_CLIENT_FINISHED_WRITE_KEY,
117
+ write_iv: TESTBINARY_CLIENT_FINISHED_WRITE_IV,
118
+ sequence_number: write_seq_num
119
+ )
120
+ client.instance_variable_set(:@write_cipher, write_cipher)
121
+ client.instance_variable_set(:@write_seq_num, write_seq_num)
122
+ client.send(:send_finished)
123
+ read_cipher = Cryptograph::Aead.new(
124
+ cipher_suite: CipherSuite::TLS_AES_128_GCM_SHA256,
125
+ write_key: TESTBINARY_CLIENT_FINISHED_WRITE_KEY,
126
+ write_iv: TESTBINARY_CLIENT_FINISHED_WRITE_IV,
127
+ sequence_number: SequenceNumber.new
128
+ )
129
+ Record.deserialize(mock_socket.read, read_cipher)
130
+ end
131
+
132
+ it 'should send Finished' do
133
+ expect(record.type).to eq ContentType::APPLICATION_DATA
134
+
135
+ message = record.messages.first
136
+ expect(message.msg_type).to eq HandshakeType::FINISHED
137
+ expect(message.serialize).to eq TESTBINARY_CLIENT_FINISHED
138
+ end
139
+ end
140
+
141
+ context 'client' do
142
+ let(:client) do
143
+ client = Client.new(nil, 'localhost')
144
+ transcript = Transcript.new
145
+ transcript.merge!(
146
+ CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
147
+ SH => ServerHello.deserialize(TESTBINARY_SERVER_HELLO),
148
+ EE => EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS),
149
+ CT => Certificate.deserialize(TESTBINARY_CERTIFICATE),
150
+ CV => CertificateVerify.deserialize(TESTBINARY_CERTIFICATE_VERIFY),
151
+ SF => Finished.deserialize(TESTBINARY_SERVER_FINISHED)
152
+ )
153
+ client.instance_variable_set(:@transcript, transcript)
154
+ ks = KeySchedule.new(shared_secret: TESTBINARY_SHARED_SECRET,
155
+ cipher_suite: CipherSuite::TLS_AES_128_GCM_SHA256,
156
+ transcript: transcript)
157
+ client.instance_variable_set(:@key_schedule, ks)
158
+ client.instance_variable_set(:@cipher_suite,
159
+ CipherSuite::TLS_AES_128_GCM_SHA256)
160
+ client
161
+ end
162
+
163
+ let(:client_finished) do
164
+ Finished.deserialize(TESTBINARY_CLIENT_FINISHED)
165
+ end
166
+
167
+ it 'should verify server CertificateVerify' do
168
+ expect(client.send(:verify_certificate_verify)).to be true
169
+ end
170
+
171
+ it 'should verify server Finished' do
172
+ expect(client.send(:verify_finished)).to be true
173
+ end
174
+
175
+ it 'should sign client Finished' do
176
+ expect(client.send(:sign_finished)).to eq client_finished.verify_data
177
+ end
178
+ end
179
+
180
+ context 'client' do
181
+ let(:client) do
182
+ client = Client.new(nil, 'localhost')
183
+ transcript = {
184
+ CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
185
+ SH => ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
186
+ }
187
+ client.instance_variable_set(:@transcript, transcript)
188
+ client
189
+ end
190
+
191
+ it 'should check that ServerHello.legacy_version matches ' \
192
+ 'ClientHello.legacy_version' do
193
+ expect(client.send(:valid_sh_legacy_version?)).to be true
194
+ end
195
+
196
+ it 'should check that ServerHello.legacy_session_id_echo matches ' \
197
+ 'ClientHello.legacy_session_id' do
198
+ expect(client.send(:valid_sh_legacy_session_id_echo?)).to be true
199
+ end
200
+
201
+ it 'should check that ServerHello.cipher_suite is included in' \
202
+ 'ClientHello.cipher_suites' do
203
+ expect(client.send(:valid_sh_cipher_suite?)).to be true
204
+ end
205
+
206
+ it 'should check that ServerHello.compression_method is valid value' do
207
+ expect(client.send(:valid_sh_compression_method?)).to be true
208
+ end
209
+
210
+ it 'should check that negotiated protocol_version is TLS 1.3' do
211
+ expect(client.send(:negotiated_tls_1_3?)).to be true
212
+ end
213
+ end
214
+
215
+ context 'client, received ServerHello with random[-8..] == ' \
216
+ 'downgrade protection value(TLS 1.2),' do
217
+ let(:client) do
218
+ mock_socket = SimpleStream.new
219
+ client = Client.new(mock_socket, 'localhost')
220
+ sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
221
+ random = OpenSSL::Random.random_bytes(24) + \
222
+ Client::DOWNGRADE_PROTECTION_TLS_1_2
223
+ sh.instance_variable_set(:@random, random)
224
+ transcript = {
225
+ CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
226
+ SH => sh
227
+ }
228
+ client.instance_variable_set(:@transcript, transcript)
229
+ client
230
+ end
231
+
232
+ it 'should check downgrade protection value' do
233
+ expect { client.send(:negotiated_tls_1_3?) }.to raise_error(ErrorAlerts)
234
+ end
235
+ end
236
+
237
+ context 'client, received ServerHello with random[-8..] == ' \
238
+ 'downgrade protection value(prior to TLS 1.2),' do
239
+ let(:client) do
240
+ mock_socket = SimpleStream.new
241
+ client = Client.new(mock_socket, 'localhost')
242
+ sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
243
+ random = OpenSSL::Random.random_bytes(24) + \
244
+ Client::DOWNGRADE_PROTECTION_TLS_1_1
245
+ sh.instance_variable_set(:@random, random)
246
+ transcript = {
247
+ CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
248
+ SH => sh
249
+ }
250
+ client.instance_variable_set(:@transcript, transcript)
251
+ client
252
+ end
253
+
254
+ it 'should check downgrade protection value' do
255
+ expect { client.send(:negotiated_tls_1_3?) }.to raise_error(ErrorAlerts)
256
+ end
257
+ end
258
+
259
+ context 'client, received ServerHello with supported_versions not ' \
260
+ 'including "\x03\x04",' do
261
+ let(:client) do
262
+ mock_socket = SimpleStream.new
263
+ client = Client.new(mock_socket, 'localhost')
264
+ sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
265
+ extensions = sh.instance_variable_get(:@extensions)
266
+ extensions[ExtensionType::SUPPORTED_VERSIONS] = nil
267
+ sh.instance_variable_set(:@extensions, extensions)
268
+ transcript = {
269
+ CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
270
+ SH => sh
271
+ }
272
+ client.instance_variable_set(:@transcript, transcript)
273
+ client
274
+ end
275
+
276
+ it 'should check negotiated protocol_version' do
277
+ expect(client.send(:negotiated_tls_1_3?)).to be false
278
+ end
279
+ end
280
+
281
+ context 'client, received Certificate signed by private CA,' do
282
+ let(:certificate) do
283
+ server_crt = OpenSSL::X509::Certificate.new(
284
+ File.read(__dir__ + '/../tmp/server.crt')
285
+ )
286
+ Certificate.new(certificate_list: [CertificateEntry.new(server_crt)])
287
+ end
288
+
289
+ let(:client) do
290
+ Client.new(nil, 'localhost')
291
+ end
292
+
293
+ it 'should not certify certificate' do
294
+ expect(client.send(:certified_certificate?, certificate.certificate_list))
295
+ .to be false
296
+ end
297
+
298
+ it 'should certify certificate, received path to private ca.crt' do
299
+ expect(client.send(:certified_certificate?, certificate.certificate_list,
300
+ __dir__ + '/../tmp/ca.crt')).to be true
301
+ end
302
+ end
303
+
304
+ context 'client using PSK' do
305
+ let(:client) do
306
+ Client.new(nil, 'localhost')
307
+ end
308
+
309
+ let(:ticket_nonce) do
310
+ nst = NewSessionTicket.deserialize(TESTBINARY_NEW_SESSION_TICKET)
311
+ nst.ticket_nonce
312
+ end
313
+
314
+ it 'should generate PSK from NewSessionTicket of previous handshake' do
315
+ expect(client.send(:gen_psk_from_nst, TESTBINARY_RES_MASTER, ticket_nonce,
316
+ 'SHA256')).to eq TESTBINARY_0_RTT_PSK
317
+ end
318
+ end
319
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+
6
+ RSpec.describe Connection do
7
+ context 'connection, Simple 1-RTT Handshake,' do
8
+ let(:ct) do
9
+ Certificate.deserialize(TESTBINARY_CERTIFICATE)
10
+ end
11
+
12
+ let(:cv) do
13
+ CertificateVerify.deserialize(TESTBINARY_CERTIFICATE_VERIFY)
14
+ end
15
+
16
+ let(:cf) do
17
+ Finished.deserialize(TESTBINARY_CLIENT_FINISHED)
18
+ end
19
+
20
+ let(:sf) do
21
+ Finished.deserialize(TESTBINARY_SERVER_FINISHED)
22
+ end
23
+
24
+ let(:connection) do
25
+ connection = Connection.new(nil)
26
+ transcript = Transcript.new
27
+ transcript.merge!(
28
+ CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
29
+ SH => ServerHello.deserialize(TESTBINARY_SERVER_HELLO),
30
+ EE => EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS),
31
+ CT => ct,
32
+ CV => cv,
33
+ CF => cf,
34
+ SF => sf
35
+ )
36
+ connection.instance_variable_set(:@transcript, transcript)
37
+ connection.instance_variable_set(:@cipher_suite,
38
+ CipherSuite::TLS_AES_128_GCM_SHA256)
39
+ connection
40
+ end
41
+
42
+ it 'should verify server CertificateVerify.signature' do
43
+ certificate_pem = ct.certificate_list.first.cert_data.to_pem
44
+ signature_scheme = cv.signature_scheme
45
+ signature = cv.signature
46
+ expect(connection.send(:do_verify_certificate_verify,
47
+ certificate_pem: certificate_pem,
48
+ signature_scheme: signature_scheme,
49
+ signature: signature,
50
+ context: 'TLS 1.3, server CertificateVerify',
51
+ handshake_context_end: CT))
52
+ .to be true
53
+ end
54
+
55
+ it 'should verify server Finished.verify_data' do
56
+ expect(connection.send(:do_verify_finished,
57
+ digest: 'SHA256',
58
+ finished_key: TESTBINARY_SERVER_FINISHED_KEY,
59
+ handshake_context_end: CV,
60
+ signature: sf.verify_data))
61
+ .to be true
62
+ end
63
+
64
+ it 'should sign client Finished.verify_data' do
65
+ expect(connection.send(:do_sign_finished,
66
+ digest: 'SHA256',
67
+ finished_key: TESTBINARY_CLIENT_FINISHED_KEY,
68
+ handshake_context_end: EOED))
69
+ .to eq cf.verify_data
70
+ end
71
+ end
72
+
73
+ context 'connection, HelloRetryRequest,' do
74
+ let(:ct) do
75
+ Certificate.deserialize(TESTBINARY_HRR_CERTIFICATE)
76
+ end
77
+
78
+ let(:cv) do
79
+ CertificateVerify.deserialize(TESTBINARY_HRR_CERTIFICATE_VERIFY)
80
+ end
81
+
82
+ let(:connection) do
83
+ connection = Connection.new(nil)
84
+ transcript = Transcript.new
85
+ transcript.merge!(
86
+ CH1 => ClientHello.deserialize(TESTBINARY_HRR_CLIENT_HELLO1),
87
+ HRR => ServerHello.deserialize(TESTBINARY_HRR_HELLO_RETRY_REQUEST),
88
+ CH => ClientHello.deserialize(TESTBINARY_HRR_CLIENT_HELLO),
89
+ SH => ServerHello.deserialize(TESTBINARY_HRR_SERVER_HELLO),
90
+ EE =>
91
+ EncryptedExtensions.deserialize(TESTBINARY_HRR_ENCRYPTED_EXTENSIONS),
92
+ CT => ct,
93
+ CV => cv
94
+ )
95
+ connection.instance_variable_set(:@transcript, transcript)
96
+ connection.instance_variable_set(:@cipher_suite,
97
+ CipherSuite::TLS_AES_128_GCM_SHA256)
98
+ connection
99
+ end
100
+
101
+ it 'should verify server CertificateVerify.signature' do
102
+ certificate_pem = ct.certificate_list.first.cert_data.to_pem
103
+ signature_scheme = cv.signature_scheme
104
+ signature = cv.signature
105
+ expect(connection.send(:do_verify_certificate_verify,
106
+ certificate_pem: certificate_pem,
107
+ signature_scheme: signature_scheme,
108
+ signature: signature,
109
+ context: 'TLS 1.3, server CertificateVerify',
110
+ handshake_context_end: CT))
111
+ .to be true
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,98 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe Cookie do
8
+ context 'valid cookie' do
9
+ let(:cookie) do
10
+ OpenSSL::Random.random_bytes(2**16 - 3)
11
+ end
12
+
13
+ let(:extension) do
14
+ Cookie.new(cookie)
15
+ end
16
+
17
+ it 'should be generated' do
18
+ expect(extension.extension_type).to eq ExtensionType::COOKIE
19
+ expect(extension.cookie).to eq cookie
20
+ end
21
+
22
+ it 'should be serialized' do
23
+ expect(extension.serialize).to eq ExtensionType::COOKIE \
24
+ + (2**16 - 1).to_uint16 \
25
+ + (2**16 - 3).to_uint16 \
26
+ + cookie
27
+ end
28
+ end
29
+
30
+ context 'ignored cookie, empty,' do
31
+ let(:extension) do
32
+ Cookie.new('')
33
+ end
34
+
35
+ it 'should be generated' do
36
+ expect(extension.extension_type).to eq ExtensionType::COOKIE
37
+ expect(extension.cookie).to eq ''
38
+ end
39
+ end
40
+
41
+ context 'ignored cookie, nil,' do
42
+ let(:extension) do
43
+ Cookie.new(nil)
44
+ end
45
+
46
+ it 'should not be generated' do
47
+ expect(extension.extension_type).to eq ExtensionType::COOKIE
48
+ expect(extension.cookie).to eq ''
49
+ end
50
+ end
51
+
52
+ context 'invalid cookie, too long,' do
53
+ let(:extension) do
54
+ Cookie.new('a' * (2**16 - 2))
55
+ end
56
+
57
+ it 'should not be generated' do
58
+ expect { extension }.to raise_error(ErrorAlerts)
59
+ end
60
+ end
61
+
62
+ context 'valid cookie binary' do
63
+ let(:extension) do
64
+ Cookie.deserialize(TESTBINARY_COOKIE)
65
+ end
66
+
67
+ it 'should generate object' do
68
+ expect(extension.extension_type).to eq ExtensionType::COOKIE
69
+ expect(extension.cookie).to eq TESTBINARY_COOKIE[2..]
70
+ end
71
+
72
+ it 'should generate serializable object' do
73
+ expect(extension.serialize).to eq ExtensionType::COOKIE \
74
+ + TESTBINARY_COOKIE.prefix_uint16_length
75
+ end
76
+ end
77
+
78
+ context 'cookie binary, empty,' do
79
+ let(:extension) do
80
+ Cookie.deserialize("\x00\x00")
81
+ end
82
+
83
+ it 'should generat object' do
84
+ expect(extension.extension_type).to eq ExtensionType::COOKIE
85
+ expect(extension.cookie).to eq ''
86
+ end
87
+ end
88
+
89
+ context 'invalid cookie binary, malformed binary,' do
90
+ let(:extension) do
91
+ Cookie.deserialize(TESTBINARY_COOKIE[0...-1])
92
+ end
93
+
94
+ it 'should return nil' do
95
+ expect(extension).to be nil
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe EarlyDataIndication do
8
+ context 'valid early_data_indication, NewSessionTicket,' do
9
+ let(:extension) do
10
+ EarlyDataIndication.new(2**32 - 1)
11
+ end
12
+
13
+ it 'should be generated' do
14
+ expect(extension.extension_type).to eq ExtensionType::EARLY_DATA
15
+ expect(extension.max_early_data_size).to eq 2**32 - 1
16
+ end
17
+
18
+ it 'should be serialized' do
19
+ expect(extension.serialize).to eq ExtensionType::EARLY_DATA \
20
+ + 4.to_uint16 \
21
+ + (2**32 - 1).to_uint32
22
+ end
23
+ end
24
+
25
+ context 'valid early_data_indication, ClientHello or EncryptedExtensions,' do
26
+ let(:extension) do
27
+ EarlyDataIndication.new(nil)
28
+ end
29
+
30
+ it 'should be generated' do
31
+ expect(extension.extension_type).to eq ExtensionType::EARLY_DATA
32
+ expect(extension.max_early_data_size).to be nil
33
+ end
34
+
35
+ it 'should be serialized' do
36
+ expect(extension.serialize).to eq ExtensionType::EARLY_DATA \
37
+ + 0.to_uint16
38
+ end
39
+ end
40
+
41
+ context 'valid early_data_indication binary, NewSessionTicket,' do
42
+ let(:extension) do
43
+ EarlyDataIndication.deserialize(TESTBINARY_EARLY_DATA_INDICATION_NST,
44
+ HandshakeType::NEW_SESSION_TICKET)
45
+ end
46
+
47
+ it 'should generate valid object' do
48
+ expect(extension.extension_type).to eq ExtensionType::EARLY_DATA
49
+ expect(extension.max_early_data_size).to eq 1024
50
+ end
51
+ end
52
+
53
+ context 'valid early_data_indication binary, ClientHello,' do
54
+ let(:extension) do
55
+ EarlyDataIndication.deserialize(TESTBINARY_EARLY_DATA_INDICATION_CH,
56
+ HandshakeType::CLIENT_HELLO)
57
+ end
58
+
59
+ it 'should generate valid object' do
60
+ expect(extension.extension_type).to eq ExtensionType::EARLY_DATA
61
+ expect(extension.max_early_data_size).to be nil
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,94 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe EncryptedExtensions do
8
+ context 'valid encrypted_extensions' do
9
+ let(:server_name) do
10
+ ServerName.new('')
11
+ end
12
+
13
+ let(:supported_groups) do
14
+ SupportedGroups.new(
15
+ [
16
+ NamedGroup::SECP256R1,
17
+ NamedGroup::SECP384R1,
18
+ NamedGroup::SECP521R1
19
+ ]
20
+ )
21
+ end
22
+
23
+ let(:extensions) do
24
+ Extensions.new([server_name, supported_groups])
25
+ end
26
+
27
+ let(:message) do
28
+ EncryptedExtensions.new(extensions)
29
+ end
30
+
31
+ it 'should be generated' do
32
+ expect(message.msg_type).to eq HandshakeType::ENCRYPTED_EXTENSIONS
33
+ expect(message.extensions).to eq extensions
34
+ expect(message.any_forbidden_extensions?).to be false
35
+ end
36
+
37
+ it 'should be serialized' do
38
+ expect(message.serialize)
39
+ .to eq HandshakeType::ENCRYPTED_EXTENSIONS \
40
+ + extensions.serialize.prefix_uint24_length
41
+ end
42
+ end
43
+
44
+ context 'invalid encrypted_extensions, including forbidden extension type,' do
45
+ let(:extensions) do
46
+ signature_algorithms \
47
+ = SignatureAlgorithms.new([SignatureScheme::ECDSA_SECP256R1_SHA256])
48
+ Extensions.new([signature_algorithms])
49
+ end
50
+
51
+ let(:message) do
52
+ EncryptedExtensions.new(extensions)
53
+ end
54
+
55
+ it 'should be generated' do
56
+ expect(message.msg_type).to eq HandshakeType::ENCRYPTED_EXTENSIONS
57
+ expect(message.extensions).to eq extensions
58
+ expect(message.any_forbidden_extensions?).to be true
59
+ end
60
+ end
61
+
62
+ context 'valid encrypted_extensions, nil argument,' do
63
+ let(:message) do
64
+ EncryptedExtensions.new(nil)
65
+ end
66
+
67
+ it 'should be generated' do
68
+ expect(message.msg_type).to eq HandshakeType::ENCRYPTED_EXTENSIONS
69
+ expect(message.extensions).to eq Extensions.new
70
+ expect(message.any_forbidden_extensions?).to be false
71
+ end
72
+
73
+ it 'should be serialized' do
74
+ expect(message.serialize)
75
+ .to eq HandshakeType::ENCRYPTED_EXTENSIONS \
76
+ + Extensions.new.serialize.prefix_uint24_length
77
+ end
78
+ end
79
+
80
+ context 'valid encrypted_extensions binary' do
81
+ let(:message) do
82
+ EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS)
83
+ end
84
+
85
+ it 'should generate valid object' do
86
+ expect(message.msg_type).to eq HandshakeType::ENCRYPTED_EXTENSIONS
87
+ expect(message.any_forbidden_extensions?).to be false
88
+ end
89
+
90
+ it 'should generate valid serializable object' do
91
+ expect(message.serialize).to eq TESTBINARY_ENCRYPTED_EXTENSIONS
92
+ end
93
+ end
94
+ end