tttls1.3 0.2.15 → 0.2.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,23 +11,19 @@ module TTTLS13
11
11
  attr_reader :type
12
12
  attr_reader :legacy_record_version
13
13
  attr_reader :messages
14
- attr_reader :surplus_binary
15
14
  attr_reader :cipher
16
15
 
17
16
  # @param type [TTTLS13::Message::ContentType]
18
17
  # @param legacy_record_version [TTTLS13::Message::ProtocolVersion]
19
18
  # @param messages [Array of TTTLS13::Message::$Object]
20
- # @param surplus_binary [String]
21
19
  # @param cipher [TTTLS13::Cryptograph::$Object]
22
20
  def initialize(type:,
23
21
  legacy_record_version: ProtocolVersion::TLS_1_2,
24
22
  messages:,
25
- surplus_binary: '',
26
23
  cipher:)
27
24
  @type = type
28
25
  @legacy_record_version = legacy_record_version
29
26
  @messages = messages
30
- @surplus_binary = surplus_binary
31
27
  @cipher = cipher
32
28
  end
33
29
 
@@ -40,7 +36,7 @@ module TTTLS13
40
36
  #
41
37
  # @return [String]
42
38
  def serialize(record_size_limit = DEFAULT_RECORD_SIZE_LIMIT)
43
- tlsplaintext = @messages.map(&:serialize).join + @surplus_binary
39
+ tlsplaintext = @messages.map(&:serialize).join
44
40
  if @cipher.is_a?(Cryptograph::Aead)
45
41
  max = @cipher.tlsplaintext_length_limit(record_size_limit)
46
42
  fragments = tlsplaintext.scan(/.{1,#{max}}/m)
@@ -66,6 +62,8 @@ module TTTLS13
66
62
  # @raise [TTTLS13::Error::ErrorAlerts]
67
63
  #
68
64
  # @return [TTTLS13::Message::Record]
65
+ # @return [Array of String]
66
+ # @return [String]
69
67
  # rubocop: disable Metrics/AbcSize
70
68
  # rubocop: disable Metrics/CyclomaticComplexity
71
69
  # rubocop: disable Metrics/PerceivedComplexity
@@ -93,13 +91,17 @@ module TTTLS13
93
91
  fragment, inner_type = cipher.decrypt(fragment, binary.slice(0, 5))
94
92
  end
95
93
 
96
- messages, surplus_binary = deserialize_fragment(buffered + fragment,
97
- inner_type || type)
98
- Record.new(type: type,
99
- legacy_record_version: legacy_record_version,
100
- messages: messages,
101
- surplus_binary: surplus_binary,
102
- cipher: cipher)
94
+ messages, orig_msgs, surplus_binary = deserialize_fragment(
95
+ buffered + fragment,
96
+ inner_type || type
97
+ )
98
+ record = Record.new(
99
+ type: type,
100
+ legacy_record_version: legacy_record_version,
101
+ messages: messages,
102
+ cipher: cipher
103
+ )
104
+ [record, orig_msgs, surplus_binary]
103
105
  end
104
106
  # rubocop: enable Metrics/AbcSize
105
107
  # rubocop: enable Metrics/CyclomaticComplexity
@@ -116,6 +118,7 @@ module TTTLS13
116
118
  Message::ServerHello,
117
119
  Message::EncryptedExtensions,
118
120
  Message::Certificate,
121
+ Message::CompressedCertificate,
119
122
  Message::CertificateVerify,
120
123
  Message::Finished,
121
124
  Message::EndOfEarlyData,
@@ -152,20 +155,24 @@ module TTTLS13
152
155
  raise Error::ErrorAlerts, :internal_error if binary.nil?
153
156
 
154
157
  surplus_binary = ''
158
+ orig_msgs = []
155
159
  case type
156
160
  when ContentType::HANDSHAKE
157
- messages, surplus_binary = deserialize_handshake(binary)
161
+ messages, orig_msgs, surplus_binary = deserialize_handshake(binary)
158
162
  when ContentType::CCS
159
163
  messages = [ChangeCipherSpec.deserialize(binary)]
164
+ orig_msgs = [binary]
160
165
  when ContentType::APPLICATION_DATA
161
166
  messages = [ApplicationData.deserialize(binary)]
167
+ orig_msgs = [binary]
162
168
  when ContentType::ALERT
163
169
  messages = [Alert.deserialize(binary)]
170
+ orig_msgs = [binary]
164
171
  else
165
172
  raise Error::ErrorAlerts, :unexpected_message
166
173
  end
167
174
 
168
- [messages, surplus_binary]
175
+ [messages, orig_msgs, surplus_binary]
169
176
  end
170
177
 
171
178
  # @param binary [String]
@@ -173,11 +180,13 @@ module TTTLS13
173
180
  # @raise [TTTLS13::Error::ErrorAlerts]
174
181
  #
175
182
  # @return [Array of TTTLS13::Message::$Object]
183
+ # @return [Array of String]
176
184
  # @return [String]
177
185
  def deserialize_handshake(binary)
178
186
  raise Error::ErrorAlerts, :internal_error if binary.nil?
179
187
 
180
188
  handshakes = []
189
+ orig_msgs = []
181
190
  i = 0
182
191
  while i < binary.length
183
192
  # Handshake.length is kind of uint24 and Record.length is kind of
@@ -185,18 +194,19 @@ module TTTLS13
185
194
  if binary.length < 4 + i ||
186
195
  binary.length < 4 + i + Convert.bin2i(binary.slice(i + 1, 3))
187
196
  surplus_binary = binary[i..]
188
- return [handshakes, surplus_binary]
197
+ return [handshakes, orig_msgs, surplus_binary]
189
198
  end
190
199
 
191
200
  msg_len = Convert.bin2i(binary.slice(i + 1, 3))
192
201
  msg_bin = binary.slice(i, msg_len + 4)
202
+ orig_msgs << msg_bin
193
203
  message = do_deserialize_handshake(msg_bin)
194
204
  i += msg_len + 4
195
205
  handshakes << message
196
206
  end
197
207
 
198
208
  surplus_binary = binary[i..]
199
- [handshakes, surplus_binary]
209
+ [handshakes, orig_msgs, surplus_binary]
200
210
  end
201
211
 
202
212
  # @param binary [String]
@@ -226,6 +236,8 @@ module TTTLS13
226
236
  NewSessionTicket.deserialize(binary)
227
237
  when HandshakeType::END_OF_EARLY_DATA
228
238
  EndOfEarlyData.deserialize(binary)
239
+ when HandshakeType::COMPRESSED_CERTIFICATE
240
+ CompressedCertificate.deserialize(binary)
229
241
  else
230
242
  raise Error::ErrorAlerts, :unexpected_message
231
243
  end
@@ -21,26 +21,27 @@ module TTTLS13
21
21
  DEFAULT_VERSIONS = [ProtocolVersion::TLS_1_3].freeze
22
22
 
23
23
  module HandshakeType
24
- HELLO_REQUEST = "\x00" # RESERVED
25
- CLIENT_HELLO = "\x01"
26
- SERVER_HELLO = "\x02"
27
- HELLO_VERIFY_REQUEST = "\x03" # RESERVED
28
- NEW_SESSION_TICKET = "\x04"
29
- END_OF_EARLY_DATA = "\x05"
30
- HELLO_RETRY_REQUEST = "\x06" # RESERVED
31
- ENCRYPTED_EXTENSIONS = "\x08"
32
- CERTIFICATE = "\x0b"
33
- SERVER_KEY_EXCHANGE = "\x0c" # RESERVED
34
- CERTIFICATE_REQUEST = "\x0d"
35
- SERVER_HELLO_DONE = "\x0e" # RESERVED
36
- CERTIFICATE_VERIFY = "\x0f"
37
- CLIENT_KEY_EXCHANGE = "\x10" # RESERVED
38
- FINISHED = "\x14"
39
- CERTIFICATE_URL = "\x15" # RESERVED
40
- CERTIFICATE_STATUS = "\x16" # RESERVED
41
- SUPPLEMENTAL_DATA = "\x17" # RESERVED
42
- KEY_UPDATE = "\x18"
43
- MESSAGE_HASH = "\xfe"
24
+ HELLO_REQUEST = "\x00" # RESERVED
25
+ CLIENT_HELLO = "\x01"
26
+ SERVER_HELLO = "\x02"
27
+ HELLO_VERIFY_REQUEST = "\x03" # RESERVED
28
+ NEW_SESSION_TICKET = "\x04"
29
+ END_OF_EARLY_DATA = "\x05"
30
+ HELLO_RETRY_REQUEST = "\x06" # RESERVED
31
+ ENCRYPTED_EXTENSIONS = "\x08"
32
+ CERTIFICATE = "\x0b"
33
+ SERVER_KEY_EXCHANGE = "\x0c" # RESERVED
34
+ CERTIFICATE_REQUEST = "\x0d"
35
+ SERVER_HELLO_DONE = "\x0e" # RESERVED
36
+ CERTIFICATE_VERIFY = "\x0f"
37
+ CLIENT_KEY_EXCHANGE = "\x10" # RESERVED
38
+ FINISHED = "\x14"
39
+ CERTIFICATE_URL = "\x15" # RESERVED
40
+ CERTIFICATE_STATUS = "\x16" # RESERVED
41
+ SUPPLEMENTAL_DATA = "\x17" # RESERVED
42
+ KEY_UPDATE = "\x18"
43
+ COMPRESSED_CERTIFICATE = "\x19"
44
+ MESSAGE_HASH = "\xfe"
44
45
  end
45
46
 
46
47
  module ExtensionType
@@ -56,6 +57,7 @@ module TTTLS13
56
57
  CLIENT_CERTIFICATE_TYPE = "\x00\x13"
57
58
  SERVER_CERTIFICATE_TYPE = "\x00\x14"
58
59
  PADDING = "\x00\x15"
60
+ COMPRESS_CERTIFICATE = "\x00\x1b"
59
61
  RECORD_SIZE_LIMIT = "\x00\x1c"
60
62
  PWD_PROTECT = "\x00\x1d"
61
63
  PWD_CLEAR = "\x00\x1e"
@@ -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,6 +58,7 @@ 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,
57
63
  loglevel: Logger::WARN
58
64
  }.freeze
@@ -140,7 +146,6 @@ module TTTLS13
140
146
  transcript = Transcript.new
141
147
  key_schedule = nil # TTTLS13::KeySchedule
142
148
  priv_key = nil # OpenSSL::PKey::$Object
143
-
144
149
  hs_wcipher = nil # TTTLS13::Cryptograph::$Object
145
150
  hs_rcipher = nil # TTTLS13::Cryptograph::$Object
146
151
 
@@ -151,7 +156,7 @@ module TTTLS13
151
156
  logger.debug('ServerState::START')
152
157
 
153
158
  receivable_ccs = transcript.include?(CH1)
154
- ch = transcript[CH] = recv_client_hello(receivable_ccs)
159
+ ch, = transcript[CH] = recv_client_hello(receivable_ccs)
155
160
 
156
161
  # support only TLS 1.3
157
162
  terminate(:protocol_version) unless ch.negotiated_tls_1_3?
@@ -183,7 +188,7 @@ module TTTLS13
183
188
  logger.debug('ServerState::RECVD_CH')
184
189
 
185
190
  # select parameters
186
- ch = transcript[CH]
191
+ ch, = transcript[CH]
187
192
  @cipher_suite = select_cipher_suite(ch)
188
193
  @named_group = select_named_group(ch)
189
194
  @signature_scheme = select_signature_scheme(ch, @crt)
@@ -192,8 +197,9 @@ module TTTLS13
192
197
 
193
198
  # send HRR
194
199
  if @named_group.nil?
195
- ch1 = transcript[CH1] = transcript.delete(CH)
196
- transcript[HRR] = send_hello_retry_request(ch1, @cipher_suite)
200
+ ch1, = transcript[CH1] = transcript.delete(CH)
201
+ hrr = send_hello_retry_request(ch1, @cipher_suite)
202
+ transcript[HRR] = [hrr, hrr.serialize]
197
203
  @state = ServerState::START
198
204
  next
199
205
  end
@@ -201,10 +207,14 @@ module TTTLS13
201
207
  when ServerState::NEGOTIATED
202
208
  logger.debug('ServerState::NEGOTIATED')
203
209
 
204
- ch = transcript[CH]
210
+ ch, = transcript[CH]
205
211
  extensions, priv_key = gen_sh_extensions(@named_group)
206
- transcript[SH] = send_server_hello(extensions, @cipher_suite,
207
- ch.legacy_session_id)
212
+ sh = send_server_hello(
213
+ extensions,
214
+ @cipher_suite,
215
+ ch.legacy_session_id
216
+ )
217
+ transcript[SH] = [sh, sh.serialize]
208
218
  send_ccs if @settings[:compatibility_mode]
209
219
 
210
220
  # generate shared secret
@@ -235,29 +245,30 @@ module TTTLS13
235
245
  when ServerState::WAIT_FLIGHT2
236
246
  logger.debug('ServerState::WAIT_FLIGHT2')
237
247
 
238
- ch = transcript[CH]
248
+ ch, = transcript[CH]
239
249
  rsl = @send_record_size \
240
250
  if ch.extensions.include?(Message::ExtensionType::RECORD_SIZE_LIMIT)
241
- ee = transcript[EE] = gen_encrypted_extensions(ch, @alpn, rsl)
251
+ ee = gen_encrypted_extensions(ch, @alpn, rsl)
252
+ transcript[EE] = [ee, ee.serialize]
242
253
  # TODO: [Send CertificateRequest]
243
254
 
244
255
  # status_request
245
256
  ocsp_response = fetch_ocsp_response \
246
257
  if ch.extensions.include?(Message::ExtensionType::STATUS_REQUEST)
247
- ct = transcript[CT] = gen_certificate(@crt, @chain, ocsp_response)
258
+ ct = gen_certificate(@crt, ch, @chain, ocsp_response)
259
+ transcript[CT] = [ct, ct.serialize]
248
260
  digest = CipherSuite.digest(@cipher_suite)
249
- cv = transcript[CV] = gen_certificate_verify(
250
- @key,
251
- @signature_scheme,
252
- transcript.hash(digest, CT)
253
- )
261
+ hash = transcript.hash(digest, CT)
262
+ cv = gen_certificate_verify(@key, @signature_scheme, hash)
263
+ transcript[CV] = [cv, cv.serialize]
254
264
  finished_key = key_schedule.server_finished_key
255
265
  signature = sign_finished(
256
266
  digest: digest,
257
267
  finished_key: finished_key,
258
268
  hash: transcript.hash(digest, CV)
259
269
  )
260
- sf = transcript[SF] = Message::Finished.new(signature)
270
+ sf = Message::Finished.new(signature)
271
+ transcript[SF] = [sf, sf.serialize]
261
272
  send_server_parameters([ee, ct, cv, sf], hs_wcipher)
262
273
  @state = ServerState::WAIT_FINISHED
263
274
  when ServerState::WAIT_CERT
@@ -267,7 +278,7 @@ module TTTLS13
267
278
  when ServerState::WAIT_FINISHED
268
279
  logger.debug('ServerState::WAIT_FINISHED')
269
280
 
270
- cf = transcript[CF] = recv_finished(hs_rcipher)
281
+ cf, = transcript[CF] = recv_finished(hs_rcipher)
271
282
  digest = CipherSuite.digest(@cipher_suite)
272
283
  verified = verified_finished?(
273
284
  finished: cf,
@@ -325,12 +336,15 @@ module TTTLS13
325
336
  # @raise [TTTLS13::Error::ErrorAlerts]
326
337
  #
327
338
  # @return [TTTLS13::Message::ClientHello]
339
+ # @return [String]
328
340
  def recv_client_hello(receivable_ccs)
329
- ch = recv_message(receivable_ccs: receivable_ccs,
330
- cipher: Cryptograph::Passer.new)
341
+ ch, orig_msg = recv_message(
342
+ receivable_ccs: receivable_ccs,
343
+ cipher: Cryptograph::Passer.new
344
+ )
331
345
  terminate(:unexpected_message) unless ch.is_a?(Message::ClientHello)
332
346
 
333
- ch
347
+ [ch, orig_msg]
334
348
  end
335
349
 
336
350
  # @param extensions [TTTLS13::Message::Extensions]
@@ -408,19 +422,39 @@ module TTTLS13
408
422
  end
409
423
 
410
424
  # @param crt [OpenSSL::X509::Certificate]
425
+ # @param ch [TTTLS13::Message::ClientHell]
411
426
  # @param chain [Array of OpenSSL::X509::Certificate]
412
427
  # @param ocsp_response [OpenSSL::OCSP::Response]
413
428
  #
414
- # @return [TTTLS13::Message::Certificate, nil]
415
- def gen_certificate(crt, chain = [], ocsp_response = nil)
429
+ # @return [TTTLS13::Message::Certificate, CompressedCertificate, nil]
430
+ # rubocop: disable Metrics/CyclomaticComplexity
431
+ def gen_certificate(crt, ch, chain = [], ocsp_response = nil)
416
432
  exs = Message::Extensions.new
417
433
  # status_request
418
434
  exs << Message::Extension::OCSPResponse.new(ocsp_response) \
419
435
  unless ocsp_response.nil?
420
436
  ces = [Message::CertificateEntry.new(crt, exs)] \
421
437
  + (chain || []).map { |c| Message::CertificateEntry.new(c) }
422
- Message::Certificate.new(certificate_list: ces)
438
+ ct = Message::Certificate.new(certificate_list: ces)
439
+
440
+ # compress_certificate
441
+ cc = ch.extensions[Message::ExtensionType::COMPRESS_CERTIFICATE]
442
+ if !cc.nil? && !cc.algorithms.empty?
443
+ cca = (@settings[:compress_certificate_algorithms] || []).find do |a|
444
+ cc.algorithms.include?(a)
445
+ end
446
+
447
+ unless cca.nil?
448
+ ct = Message::CompressedCertificate.new(
449
+ certificate_message: ct,
450
+ algorithm: cca
451
+ )
452
+ end
453
+ end
454
+
455
+ ct
423
456
  end
457
+ # rubocop: enable Metrics/CyclomaticComplexity
424
458
 
425
459
  # @param key [OpenSSL::PKey::PKey]
426
460
  # @param signature_scheme [TTTLS13::SignatureScheme]
@@ -442,11 +476,12 @@ module TTTLS13
442
476
  # @raise [TTTLS13::Error::ErrorAlerts]
443
477
  #
444
478
  # @return [TTTLS13::Message::Finished]
479
+ # @return [String]
445
480
  def recv_finished(cipher)
446
- cf = recv_message(receivable_ccs: true, cipher: cipher)
481
+ cf, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
447
482
  terminate(:unexpected_message) unless cf.is_a?(Message::Finished)
448
483
 
449
- cf
484
+ [cf, orig_msg]
450
485
  end
451
486
 
452
487
  # @param named_group [TTTLS13::NamedGroup]
@@ -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.16'
5
5
  end
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