tttls1.3 0.2.15 → 0.2.18

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.
@@ -44,6 +44,11 @@ module TTTLS13
44
44
  ].freeze
45
45
  private_constant :DEFAULT_SP_NAMED_GROUP_LIST
46
46
 
47
+ DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS = [
48
+ Message::Extension::CertificateCompressionAlgorithm::ZLIB
49
+ ].freeze
50
+ private_constant :DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS
51
+
47
52
  DEFAULT_SERVER_SETTINGS = {
48
53
  crt_file: nil,
49
54
  chain_files: nil,
@@ -53,7 +58,9 @@ module TTTLS13
53
58
  supported_groups: DEFAULT_SP_NAMED_GROUP_LIST,
54
59
  alpn: nil,
55
60
  process_ocsp_response: nil,
61
+ compress_certificate_algorithms: DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS,
56
62
  compatibility_mode: true,
63
+ sslkeylogfile: nil,
57
64
  loglevel: Logger::WARN
58
65
  }.freeze
59
66
  private_constant :DEFAULT_SERVER_SETTINGS
@@ -140,9 +147,17 @@ module TTTLS13
140
147
  transcript = Transcript.new
141
148
  key_schedule = nil # TTTLS13::KeySchedule
142
149
  priv_key = nil # OpenSSL::PKey::$Object
143
-
144
150
  hs_wcipher = nil # TTTLS13::Cryptograph::$Object
145
151
  hs_rcipher = nil # TTTLS13::Cryptograph::$Object
152
+ sslkeylogfile = nil # TTTLS13::SslKeyLogFile::Writer
153
+ unless @settings[:sslkeylogfile].nil?
154
+ begin
155
+ sslkeylogfile = SslKeyLogFile::Writer.new(@settings[:sslkeylogfile])
156
+ rescue SystemCallError => e
157
+ msg = "\"#{@settings[:sslkeylogfile]}\" file can NOT open: #{e}"
158
+ logger.warn(msg)
159
+ end
160
+ end
146
161
 
147
162
  @state = ServerState::START
148
163
  loop do
@@ -151,7 +166,7 @@ module TTTLS13
151
166
  logger.debug('ServerState::START')
152
167
 
153
168
  receivable_ccs = transcript.include?(CH1)
154
- ch = transcript[CH] = recv_client_hello(receivable_ccs)
169
+ ch, = transcript[CH] = recv_client_hello(receivable_ccs)
155
170
 
156
171
  # support only TLS 1.3
157
172
  terminate(:protocol_version) unless ch.negotiated_tls_1_3?
@@ -183,7 +198,7 @@ module TTTLS13
183
198
  logger.debug('ServerState::RECVD_CH')
184
199
 
185
200
  # select parameters
186
- ch = transcript[CH]
201
+ ch, = transcript[CH]
187
202
  @cipher_suite = select_cipher_suite(ch)
188
203
  @named_group = select_named_group(ch)
189
204
  @signature_scheme = select_signature_scheme(ch, @crt)
@@ -192,8 +207,9 @@ module TTTLS13
192
207
 
193
208
  # send HRR
194
209
  if @named_group.nil?
195
- ch1 = transcript[CH1] = transcript.delete(CH)
196
- transcript[HRR] = send_hello_retry_request(ch1, @cipher_suite)
210
+ ch1, = transcript[CH1] = transcript.delete(CH)
211
+ hrr = send_hello_retry_request(ch1, @cipher_suite)
212
+ transcript[HRR] = [hrr, hrr.serialize]
197
213
  @state = ServerState::START
198
214
  next
199
215
  end
@@ -201,16 +217,20 @@ module TTTLS13
201
217
  when ServerState::NEGOTIATED
202
218
  logger.debug('ServerState::NEGOTIATED')
203
219
 
204
- ch = transcript[CH]
220
+ ch, = transcript[CH]
205
221
  extensions, priv_key = gen_sh_extensions(@named_group)
206
- transcript[SH] = send_server_hello(extensions, @cipher_suite,
207
- ch.legacy_session_id)
222
+ sh = send_server_hello(
223
+ extensions,
224
+ @cipher_suite,
225
+ ch.legacy_session_id
226
+ )
227
+ transcript[SH] = [sh, sh.serialize]
208
228
  send_ccs if @settings[:compatibility_mode]
209
229
 
210
230
  # generate shared secret
211
231
  ke = ch.extensions[Message::ExtensionType::KEY_SHARE]
212
232
  &.key_share_entry
213
- &.find { |e| e.group == @named_group }
233
+ &.find { |kse| kse.group == @named_group }
214
234
  &.key_exchange
215
235
  shared_secret = gen_shared_secret(ke, priv_key, @named_group)
216
236
  key_schedule = KeySchedule.new(
@@ -224,40 +244,49 @@ module TTTLS13
224
244
  key_schedule.server_handshake_write_key,
225
245
  key_schedule.server_handshake_write_iv
226
246
  )
247
+ sslkeylogfile&.write_server_handshake_traffic_secret(
248
+ transcript[CH].first.random,
249
+ key_schedule.server_handshake_traffic_secret
250
+ )
227
251
  hs_rcipher = gen_cipher(
228
252
  @cipher_suite,
229
253
  key_schedule.client_handshake_write_key,
230
254
  key_schedule.client_handshake_write_iv
231
255
  )
256
+ sslkeylogfile&.write_client_handshake_traffic_secret(
257
+ transcript[CH].first.random,
258
+ key_schedule.client_handshake_traffic_secret
259
+ )
232
260
  @state = ServerState::WAIT_FLIGHT2
233
261
  when ServerState::WAIT_EOED
234
262
  logger.debug('ServerState::WAIT_EOED')
235
263
  when ServerState::WAIT_FLIGHT2
236
264
  logger.debug('ServerState::WAIT_FLIGHT2')
237
265
 
238
- ch = transcript[CH]
266
+ ch, = transcript[CH]
239
267
  rsl = @send_record_size \
240
268
  if ch.extensions.include?(Message::ExtensionType::RECORD_SIZE_LIMIT)
241
- ee = transcript[EE] = gen_encrypted_extensions(ch, @alpn, rsl)
269
+ ee = gen_encrypted_extensions(ch, @alpn, rsl)
270
+ transcript[EE] = [ee, ee.serialize]
242
271
  # TODO: [Send CertificateRequest]
243
272
 
244
273
  # status_request
245
274
  ocsp_response = fetch_ocsp_response \
246
275
  if ch.extensions.include?(Message::ExtensionType::STATUS_REQUEST)
247
- ct = transcript[CT] = gen_certificate(@crt, @chain, ocsp_response)
276
+ ct = gen_certificate(@crt, ch, @chain, ocsp_response)
277
+ transcript[CT] = [ct, ct.serialize]
248
278
  digest = CipherSuite.digest(@cipher_suite)
249
- cv = transcript[CV] = gen_certificate_verify(
250
- @key,
251
- @signature_scheme,
252
- transcript.hash(digest, CT)
253
- )
279
+ hash = transcript.hash(digest, CT)
280
+ cv = gen_certificate_verify(@key, @signature_scheme, hash)
281
+ transcript[CV] = [cv, cv.serialize]
254
282
  finished_key = key_schedule.server_finished_key
255
283
  signature = sign_finished(
256
284
  digest: digest,
257
285
  finished_key: finished_key,
258
286
  hash: transcript.hash(digest, CV)
259
287
  )
260
- sf = transcript[SF] = Message::Finished.new(signature)
288
+ sf = Message::Finished.new(signature)
289
+ transcript[SF] = [sf, sf.serialize]
261
290
  send_server_parameters([ee, ct, cv, sf], hs_wcipher)
262
291
  @state = ServerState::WAIT_FINISHED
263
292
  when ServerState::WAIT_CERT
@@ -267,7 +296,7 @@ module TTTLS13
267
296
  when ServerState::WAIT_FINISHED
268
297
  logger.debug('ServerState::WAIT_FINISHED')
269
298
 
270
- cf = transcript[CF] = recv_finished(hs_rcipher)
299
+ cf, = transcript[CF] = recv_finished(hs_rcipher)
271
300
  digest = CipherSuite.digest(@cipher_suite)
272
301
  verified = verified_finished?(
273
302
  finished: cf,
@@ -281,11 +310,19 @@ module TTTLS13
281
310
  key_schedule.server_application_write_key,
282
311
  key_schedule.server_application_write_iv
283
312
  )
313
+ sslkeylogfile&.write_server_traffic_secret_0(
314
+ transcript[CH].first.random,
315
+ key_schedule.server_application_traffic_secret
316
+ )
284
317
  @ap_rcipher = gen_cipher(
285
318
  @cipher_suite,
286
319
  key_schedule.client_application_write_key,
287
320
  key_schedule.client_application_write_iv
288
321
  )
322
+ sslkeylogfile&.write_client_traffic_secret_0(
323
+ transcript[CH].first.random,
324
+ key_schedule.client_application_traffic_secret
325
+ )
289
326
  @exporter_master_secret = key_schedule.exporter_master_secret
290
327
  @state = ServerState::CONNECTED
291
328
  when ServerState::CONNECTED
@@ -294,6 +331,7 @@ module TTTLS13
294
331
  break
295
332
  end
296
333
  end
334
+ sslkeylogfile&.close
297
335
  end
298
336
  # rubocop: enable Metrics/AbcSize
299
337
  # rubocop: enable Metrics/BlockLength
@@ -325,12 +363,15 @@ module TTTLS13
325
363
  # @raise [TTTLS13::Error::ErrorAlerts]
326
364
  #
327
365
  # @return [TTTLS13::Message::ClientHello]
366
+ # @return [String]
328
367
  def recv_client_hello(receivable_ccs)
329
- ch = recv_message(receivable_ccs: receivable_ccs,
330
- cipher: Cryptograph::Passer.new)
368
+ ch, orig_msg = recv_message(
369
+ receivable_ccs: receivable_ccs,
370
+ cipher: Cryptograph::Passer.new
371
+ )
331
372
  terminate(:unexpected_message) unless ch.is_a?(Message::ClientHello)
332
373
 
333
- ch
374
+ [ch, orig_msg]
334
375
  end
335
376
 
336
377
  # @param extensions [TTTLS13::Message::Extensions]
@@ -408,19 +449,39 @@ module TTTLS13
408
449
  end
409
450
 
410
451
  # @param crt [OpenSSL::X509::Certificate]
452
+ # @param ch [TTTLS13::Message::ClientHell]
411
453
  # @param chain [Array of OpenSSL::X509::Certificate]
412
454
  # @param ocsp_response [OpenSSL::OCSP::Response]
413
455
  #
414
- # @return [TTTLS13::Message::Certificate, nil]
415
- def gen_certificate(crt, chain = [], ocsp_response = nil)
456
+ # @return [TTTLS13::Message::Certificate, CompressedCertificate, nil]
457
+ # rubocop: disable Metrics/CyclomaticComplexity
458
+ def gen_certificate(crt, ch, chain = [], ocsp_response = nil)
416
459
  exs = Message::Extensions.new
417
460
  # status_request
418
461
  exs << Message::Extension::OCSPResponse.new(ocsp_response) \
419
462
  unless ocsp_response.nil?
420
463
  ces = [Message::CertificateEntry.new(crt, exs)] \
421
464
  + (chain || []).map { |c| Message::CertificateEntry.new(c) }
422
- Message::Certificate.new(certificate_list: ces)
465
+ ct = Message::Certificate.new(certificate_list: ces)
466
+
467
+ # compress_certificate
468
+ cc = ch.extensions[Message::ExtensionType::COMPRESS_CERTIFICATE]
469
+ if !cc.nil? && !cc.algorithms.empty?
470
+ cca = (@settings[:compress_certificate_algorithms] || []).find do |a|
471
+ cc.algorithms.include?(a)
472
+ end
473
+
474
+ unless cca.nil?
475
+ ct = Message::CompressedCertificate.new(
476
+ certificate_message: ct,
477
+ algorithm: cca
478
+ )
479
+ end
480
+ end
481
+
482
+ ct
423
483
  end
484
+ # rubocop: enable Metrics/CyclomaticComplexity
424
485
 
425
486
  # @param key [OpenSSL::PKey::PKey]
426
487
  # @param signature_scheme [TTTLS13::SignatureScheme]
@@ -442,11 +503,12 @@ module TTTLS13
442
503
  # @raise [TTTLS13::Error::ErrorAlerts]
443
504
  #
444
505
  # @return [TTTLS13::Message::Finished]
506
+ # @return [String]
445
507
  def recv_finished(cipher)
446
- cf = recv_message(receivable_ccs: true, cipher: cipher)
508
+ cf, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
447
509
  terminate(:unexpected_message) unless cf.is_a?(Message::Finished)
448
510
 
449
- cf
511
+ [cf, orig_msg]
450
512
  end
451
513
 
452
514
  # @param named_group [TTTLS13::NamedGroup]
@@ -0,0 +1,87 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ module TTTLS13
5
+ module SslKeyLogFile
6
+ module Label
7
+ CLIENT_EARLY_TRAFFIC_SECRET = 'CLIENT_EARLY_TRAFFIC_SECRET'
8
+ CLIENT_HANDSHAKE_TRAFFIC_SECRET = 'CLIENT_HANDSHAKE_TRAFFIC_SECRET'
9
+ SERVER_HANDSHAKE_TRAFFIC_SECRET = 'SERVER_HANDSHAKE_TRAFFIC_SECRET'
10
+ CLIENT_TRAFFIC_SECRET_0 = 'CLIENT_TRAFFIC_SECRET_0'
11
+ SERVER_TRAFFIC_SECRET_0 = 'SERVER_TRAFFIC_SECRET_0'
12
+ end
13
+
14
+ class Writer
15
+ # @param path [String]
16
+ #
17
+ # @raise [SystemCallError]
18
+ def initialize(path)
19
+ @file = File.new(path, 'a+')
20
+ end
21
+
22
+ # @param client_random [String]
23
+ # @param secret [String]
24
+ def write_client_early_traffic_secret(client_random, secret)
25
+ write_key_log(
26
+ Label::CLIENT_EARLY_TRAFFIC_SECRET,
27
+ client_random,
28
+ secret
29
+ )
30
+ end
31
+
32
+ # @param client_random [String]
33
+ # @param secret [String]
34
+ def write_client_handshake_traffic_secret(client_random, secret)
35
+ write_key_log(
36
+ Label::CLIENT_HANDSHAKE_TRAFFIC_SECRET,
37
+ client_random,
38
+ secret
39
+ )
40
+ end
41
+
42
+ # @param client_random [String]
43
+ # @param secret [String]
44
+ def write_server_handshake_traffic_secret(client_random, secret)
45
+ write_key_log(
46
+ Label::SERVER_HANDSHAKE_TRAFFIC_SECRET,
47
+ client_random,
48
+ secret
49
+ )
50
+ end
51
+
52
+ # @param client_random [String]
53
+ # @param secret [String]
54
+ def write_client_traffic_secret_0(client_random, secret)
55
+ write_key_log(
56
+ Label::CLIENT_TRAFFIC_SECRET_0,
57
+ client_random,
58
+ secret
59
+ )
60
+ end
61
+
62
+ # @param client_random [String]
63
+ # @param secret [String]
64
+ def write_server_traffic_secret_0(client_random, secret)
65
+ write_key_log(
66
+ Label::SERVER_TRAFFIC_SECRET_0,
67
+ client_random,
68
+ secret
69
+ )
70
+ end
71
+
72
+ def close
73
+ @file&.close
74
+ end
75
+
76
+ private
77
+
78
+ # @param label [TTTLS13::SslKeyLogFile::Label]
79
+ # @param client_random [String]
80
+ # @param secret [String]
81
+ def write_key_log(label, client_random, secret)
82
+ s = "#{label} #{client_random.unpack1('H*')} #{secret.unpack1('H*')}\n"
83
+ @file&.print(s)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -19,10 +19,6 @@ module TTTLS13
19
19
  CF = 12
20
20
 
21
21
  class Transcript < Hash
22
- def initialize
23
- super
24
- end
25
-
26
22
  alias super_include? include?
27
23
 
28
24
  # @param digest [String] name of digest algorithm
@@ -62,12 +58,12 @@ module TTTLS13
62
58
  exc_prefix = Message::HandshakeType::MESSAGE_HASH \
63
59
  + "\x00\x00" \
64
60
  + OpenSSL::Digest.new(digest).digest_length.to_uint8 \
65
- + OpenSSL::Digest.digest(digest, self[CH1].serialize) \
66
- + self[HRR].serialize
61
+ + OpenSSL::Digest.digest(digest, self[CH1].last) \
62
+ + self[HRR].last
67
63
  end
68
64
 
69
65
  messages = (CH..end_index).to_a.map do |m|
70
- include?(m) ? self[m].serialize : ''
66
+ include?(m) ? self[m].last : ''
71
67
  end
72
68
  exc_prefix + messages.join
73
69
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTTLS13
4
- VERSION = '0.2.15'
4
+ VERSION = '0.2.18'
5
5
  end
data/lib/tttls1.3.rb CHANGED
@@ -17,6 +17,7 @@ require 'tttls1.3/transcript'
17
17
  require 'tttls1.3/key_schedule'
18
18
  require 'tttls1.3/message'
19
19
  require 'tttls1.3/sequence_number'
20
+ require 'tttls1.3/sslkeylogfile'
20
21
  require 'tttls1.3/connection'
21
22
  require 'tttls1.3/client'
22
23
  require 'tttls1.3/server'
data/spec/client_spec.rb CHANGED
@@ -11,7 +11,7 @@ RSpec.describe Client do
11
11
  client = Client.new(mock_socket, 'localhost')
12
12
  extensions, _priv_keys = client.send(:gen_ch_extensions)
13
13
  client.send(:send_client_hello, extensions)
14
- Record.deserialize(mock_socket.read, Cryptograph::Passer.new)
14
+ Record.deserialize(mock_socket.read, Cryptograph::Passer.new).first
15
15
  end
16
16
 
17
17
  it 'should send default ClientHello' do
@@ -37,7 +37,7 @@ RSpec.describe Client do
37
37
  + msg_len.to_uint16 \
38
38
  + TESTBINARY_SERVER_HELLO)
39
39
  client = Client.new(mock_socket, 'localhost')
40
- client.send(:recv_server_hello)
40
+ client.send(:recv_server_hello).first
41
41
  end
42
42
 
43
43
  it 'should receive ServerHello' do
@@ -65,20 +65,20 @@ RSpec.describe Client do
65
65
  end
66
66
 
67
67
  it 'should receive EncryptedExtensions' do
68
- message = client.send(:recv_encrypted_extensions, cipher)
68
+ message, = client.send(:recv_encrypted_extensions, cipher)
69
69
  expect(message.msg_type).to eq HandshakeType::ENCRYPTED_EXTENSIONS
70
70
  end
71
71
 
72
72
  it 'should receive Certificate' do
73
73
  client.send(:recv_encrypted_extensions, cipher) # to skip
74
- message = client.send(:recv_certificate, cipher)
74
+ message, = client.send(:recv_certificate, cipher)
75
75
  expect(message.msg_type).to eq HandshakeType::CERTIFICATE
76
76
  end
77
77
 
78
78
  it 'should receive CertificateVerify' do
79
79
  client.send(:recv_encrypted_extensions, cipher) # to skip
80
80
  client.send(:recv_certificate, cipher) # to skip
81
- message = client.send(:recv_certificate_verify, cipher)
81
+ message, = client.send(:recv_certificate_verify, cipher)
82
82
  expect(message.msg_type).to eq HandshakeType::CERTIFICATE_VERIFY
83
83
  end
84
84
 
@@ -86,7 +86,7 @@ RSpec.describe Client do
86
86
  client.send(:recv_encrypted_extensions, cipher) # to skip
87
87
  client.send(:recv_certificate, cipher) # to skip
88
88
  client.send(:recv_certificate_verify, cipher) # to skip
89
- message = client.send(:recv_finished, cipher)
89
+ message, = client.send(:recv_finished, cipher)
90
90
  expect(message.msg_type).to eq HandshakeType::FINISHED
91
91
  end
92
92
  end
@@ -97,14 +97,20 @@ RSpec.describe Client do
97
97
  end
98
98
 
99
99
  let(:transcript) do
100
+ ch = ClientHello.deserialize(TESTBINARY_CLIENT_HELLO)
101
+ sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
102
+ ee = EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS)
103
+ ct = Certificate.deserialize(TESTBINARY_CERTIFICATE)
104
+ cv = CertificateVerify.deserialize(TESTBINARY_CERTIFICATE_VERIFY)
105
+ sf = Finished.deserialize(TESTBINARY_SERVER_FINISHED)
100
106
  transcript = Transcript.new
101
107
  transcript.merge!(
102
- CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
103
- SH => ServerHello.deserialize(TESTBINARY_SERVER_HELLO),
104
- EE => EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS),
105
- CT => Certificate.deserialize(TESTBINARY_CERTIFICATE),
106
- CV => CertificateVerify.deserialize(TESTBINARY_CERTIFICATE_VERIFY),
107
- SF => Finished.deserialize(TESTBINARY_SERVER_FINISHED)
108
+ CH => [ch, TESTBINARY_CLIENT_HELLO],
109
+ SH => [sh, TESTBINARY_SERVER_HELLO],
110
+ EE => [ee, TESTBINARY_ENCRYPTED_EXTENSIONS],
111
+ CT => [ct, TESTBINARY_CERTIFICATE],
112
+ CV => [cv, TESTBINARY_CERTIFICATE_VERIFY],
113
+ SF => [sf, TESTBINARY_SERVER_FINISHED]
108
114
  )
109
115
  transcript
110
116
  end
@@ -140,7 +146,7 @@ RSpec.describe Client do
140
146
  write_iv: TESTBINARY_CLIENT_FINISHED_WRITE_IV,
141
147
  sequence_number: SequenceNumber.new
142
148
  )
143
- Record.deserialize(mock_socket.read, hs_rcipher)
149
+ Record.deserialize(mock_socket.read, hs_rcipher).first
144
150
  end
145
151
 
146
152
  it 'should send Finished' do
@@ -170,14 +176,17 @@ RSpec.describe Client do
170
176
  end
171
177
 
172
178
  let(:transcript) do
179
+ ch = ClientHello.deserialize(TESTBINARY_CLIENT_HELLO)
180
+ sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
181
+ ee = EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS)
173
182
  transcript = Transcript.new
174
183
  transcript.merge!(
175
- CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
176
- SH => ServerHello.deserialize(TESTBINARY_SERVER_HELLO),
177
- EE => EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS),
178
- CT => ct,
179
- CV => cv,
180
- SF => sf
184
+ CH => [ch, TESTBINARY_CLIENT_HELLO],
185
+ SH => [sh, TESTBINARY_SERVER_HELLO],
186
+ EE => [ee, TESTBINARY_ENCRYPTED_EXTENSIONS],
187
+ CT => [ct, TESTBINARY_CERTIFICATE],
188
+ CV => [cv, TESTBINARY_CERTIFICATE_VERIFY],
189
+ SF => [sf, TESTBINARY_SERVER_FINISHED]
181
190
  )
182
191
  end
183
192
 
@@ -0,0 +1,54 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe Alpn do
8
+ context 'valid compress_certificate' do
9
+ let(:algorithms) do
10
+ [CertificateCompressionAlgorithm::ZLIB]
11
+ end
12
+
13
+ let(:extension) do
14
+ CompressCertificate.new(algorithms)
15
+ end
16
+
17
+ it 'should be generated' do
18
+ expect(extension.extension_type)
19
+ .to eq ExtensionType::COMPRESS_CERTIFICATE
20
+ expect(extension.algorithms).to eq algorithms
21
+ end
22
+
23
+ it 'should be serialized' do
24
+ expect(extension.serialize)
25
+ .to eq ExtensionType::COMPRESS_CERTIFICATE \
26
+ + 3.to_uint16 \
27
+ + 2.to_uint8 \
28
+ + "\x00\x01"
29
+ end
30
+ end
31
+
32
+ context 'invalid compress_certificate, empty,' do
33
+ let(:extension) do
34
+ CompressCertificate.new([])
35
+ end
36
+
37
+ it 'should not be generated' do
38
+ expect { extension }.to raise_error(ErrorAlerts)
39
+ end
40
+ end
41
+
42
+ context 'valid compress_certificate binary' do
43
+ let(:extension) do
44
+ CompressCertificate.deserialize(TESTBINARY_COMPRESS_CERTIFICATE)
45
+ end
46
+
47
+ it 'should generate valid object' do
48
+ expect(extension.extension_type)
49
+ .to eq ExtensionType::COMPRESS_CERTIFICATE
50
+ expect(extension.algorithms)
51
+ .to eq [CertificateCompressionAlgorithm::ZLIB]
52
+ end
53
+ end
54
+ end
@@ -32,15 +32,18 @@ RSpec.describe Connection do
32
32
  end
33
33
 
34
34
  let(:transcript) do
35
+ ch = ClientHello.deserialize(TESTBINARY_CLIENT_HELLO)
36
+ sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
37
+ ee = EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS)
35
38
  transcript = Transcript.new
36
39
  transcript.merge!(
37
- CH => ClientHello.deserialize(TESTBINARY_CLIENT_HELLO),
38
- SH => ServerHello.deserialize(TESTBINARY_SERVER_HELLO),
39
- EE => EncryptedExtensions.deserialize(TESTBINARY_ENCRYPTED_EXTENSIONS),
40
- CT => ct,
41
- CV => cv,
42
- CF => cf,
43
- SF => sf
40
+ CH => [ch, TESTBINARY_CLIENT_HELLO],
41
+ SH => [sh, TESTBINARY_SERVER_HELLO],
42
+ EE => [ee, TESTBINARY_ENCRYPTED_EXTENSIONS],
43
+ CT => [ct, TESTBINARY_CERTIFICATE],
44
+ CV => [cv, TESTBINARY_CERTIFICATE_VERIFY],
45
+ CF => [cf, TESTBINARY_CLIENT_FINISHED],
46
+ SF => [sf, TESTBINARY_SERVER_FINISHED]
44
47
  )
45
48
  end
46
49
 
@@ -115,16 +118,20 @@ RSpec.describe Connection do
115
118
  end
116
119
 
117
120
  let(:transcript) do
121
+ ch1 = ClientHello.deserialize(TESTBINARY_HRR_CLIENT_HELLO1)
122
+ hrr = ServerHello.deserialize(TESTBINARY_HRR_HELLO_RETRY_REQUEST)
123
+ ch = ClientHello.deserialize(TESTBINARY_HRR_CLIENT_HELLO)
124
+ sh = ServerHello.deserialize(TESTBINARY_HRR_SERVER_HELLO)
125
+ ee = EncryptedExtensions.deserialize(TESTBINARY_HRR_ENCRYPTED_EXTENSIONS)
118
126
  transcript = Transcript.new
119
127
  transcript.merge!(
120
- CH1 => ClientHello.deserialize(TESTBINARY_HRR_CLIENT_HELLO1),
121
- HRR => ServerHello.deserialize(TESTBINARY_HRR_HELLO_RETRY_REQUEST),
122
- CH => ClientHello.deserialize(TESTBINARY_HRR_CLIENT_HELLO),
123
- SH => ServerHello.deserialize(TESTBINARY_HRR_SERVER_HELLO),
124
- EE =>
125
- EncryptedExtensions.deserialize(TESTBINARY_HRR_ENCRYPTED_EXTENSIONS),
126
- CT => ct,
127
- CV => cv
128
+ CH1 => [ch1, TESTBINARY_HRR_CLIENT_HELLO1],
129
+ HRR => [hrr, TESTBINARY_HRR_HELLO_RETRY_REQUEST],
130
+ CH => [ch, TESTBINARY_HRR_CLIENT_HELLO],
131
+ SH => [sh, TESTBINARY_HRR_SERVER_HELLO],
132
+ EE => [ee, TESTBINARY_HRR_ENCRYPTED_EXTENSIONS],
133
+ CT => [ct, TESTBINARY_HRR_CERTIFICATE],
134
+ CV => [cv, TESTBINARY_HRR_CERTIFICATE_VERIFY]
128
135
  )
129
136
  end
130
137
 
@@ -0,0 +1,28 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+ using Refinements
6
+
7
+ RSpec.describe EndOfEarlyData do
8
+ context 'end_of_early_data' do
9
+ let(:message) do
10
+ EndOfEarlyData.new
11
+ end
12
+
13
+ it 'should be serialized' do
14
+ expect(message.serialize).to eq HandshakeType::END_OF_EARLY_DATA \
15
+ + ''.prefix_uint24_length
16
+ end
17
+ end
18
+
19
+ context 'valid end_of_early_data binary' do
20
+ let(:message) do
21
+ EndOfEarlyData.deserialize(TESTBINARY_0_RTT_END_OF_EARLY_DATA)
22
+ end
23
+
24
+ it 'should generate valid serializable object' do
25
+ expect(message.serialize).to eq TESTBINARY_0_RTT_END_OF_EARLY_DATA
26
+ end
27
+ end
28
+ end