tttls1.3 0.2.15 → 0.2.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -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