tttls1.3 0.2.14 → 0.2.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,58 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ module TTTLS13
5
+ using Refinements
6
+ module Message
7
+ module Extension
8
+ module CertificateCompressionAlgorithm
9
+ ZLIB = "\x00\x01"
10
+ # BROTLI = "\x00\x02" # UNSUPPORTED
11
+ # ZSTD = "\x00\x03" # UNSUPPORTED
12
+ end
13
+
14
+ # https://tools.ietf.org/html/rfc8879
15
+ class CompressCertificate
16
+ attr_reader :extension_type
17
+ attr_reader :algorithms
18
+
19
+ # @param algorithms [Array of CertificateCompressionAlgorithm]
20
+ #
21
+ # @raise [TTTLS13::Error::ErrorAlerts]
22
+ #
23
+ # @example
24
+ # CompressCertificate([CertificateCompressionAlgorithm::ZLIB])
25
+ def initialize(algorithms)
26
+ @extension_type = ExtensionType::COMPRESS_CERTIFICATE
27
+ @algorithms = algorithms || []
28
+ raise Error::ErrorAlerts, :internal_error \
29
+ if @algorithms.join.length < 2 ||
30
+ @algorithms.join.length > 2**8 - 2
31
+ end
32
+
33
+ # @return [String]
34
+ def serialize
35
+ binary = @algorithms.join.prefix_uint8_length
36
+
37
+ @extension_type + binary.prefix_uint16_length
38
+ end
39
+
40
+ # @param binary [String]
41
+ #
42
+ # @raise [TTTLS13::Error::ErrorAlerts]
43
+ #
44
+ # @return [TTTLS13::Message::Extension::CompressCertificate, nil]
45
+ def self.deserialize(binary)
46
+ raise Error::ErrorAlerts, :internal_error if binary.nil?
47
+
48
+ return nil if binary.length < 3
49
+
50
+ al_len = Convert.bin2i(binary.slice(0, 1))
51
+ return nil if binary.length != al_len + 1
52
+
53
+ CompressCertificate.new(binary.slice(1, al_len + 1).scan(/.{2}/m))
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -35,17 +35,17 @@ module TTTLS13
35
35
 
36
36
  # @return [String]
37
37
  def serialize
38
- binary = @supported_signature_algorithms.join
38
+ binary = @supported_signature_algorithms.join.prefix_uint16_length
39
39
 
40
- @extension_type + binary.prefix_uint16_length.prefix_uint16_length
40
+ @extension_type + binary.prefix_uint16_length
41
41
  end
42
42
 
43
43
  # @param binary [String]
44
44
  #
45
45
  # @raise [TTTLS13::Error::ErrorAlerts]
46
46
  #
47
- # @return [TTTLS13::Message::Extensions::SignatureAlgorithms, nil]
48
- def self.deserialize(binary)
47
+ # @return [Array of SignatureScheme]
48
+ def self.deserialize_supported_signature_algorithms(binary)
49
49
  raise Error::ErrorAlerts, :internal_error if binary.nil?
50
50
 
51
51
  return nil if binary.length < 2
@@ -61,7 +61,17 @@ module TTTLS13
61
61
  end
62
62
  return nil unless ssa_len + 2 == binary.length
63
63
 
64
- SignatureAlgorithms.new(supported_signature_algorithms)
64
+ supported_signature_algorithms
65
+ end
66
+
67
+ # @param binary [String]
68
+ #
69
+ # @return [TTTLS13::Message::Extensions::SignatureAlgorithms, nil]
70
+ def self.deserialize(binary)
71
+ ssa = deserialize_supported_signature_algorithms(binary)
72
+ return nil if ssa.nil?
73
+
74
+ SignatureAlgorithms.new(ssa)
65
75
  end
66
76
  end
67
77
  end
@@ -13,11 +13,12 @@ module TTTLS13
13
13
 
14
14
  # @param binary [String]
15
15
  #
16
- # @return [TTTLS13::Message::Extensions::SignatureAlgorithmsCert]
16
+ # @return [TTTLS13::Message::Extensions::SignatureAlgorithmsCert, nil]
17
17
  def self.deserialize(binary)
18
- extension = SignatureAlgorithms.deserialize(binary)
19
- extension.extension_type = ExtensionType::SIGNATURE_ALGORITHMS_CERT
20
- extension
18
+ ssa = deserialize_supported_signature_algorithms(binary)
19
+ return nil if ssa.nil?
20
+
21
+ SignatureAlgorithmsCert.new(ssa)
21
22
  end
22
23
  end
23
24
  end
@@ -21,9 +21,9 @@ module TTTLS13
21
21
 
22
22
  # @return [String]
23
23
  def serialize
24
- binary = @named_group_list.join
24
+ binary = @named_group_list.join.prefix_uint16_length
25
25
 
26
- @extension_type + binary.prefix_uint16_length.prefix_uint16_length
26
+ @extension_type + binary.prefix_uint16_length
27
27
  end
28
28
 
29
29
  # @param binary [String]
@@ -121,6 +121,7 @@ module TTTLS13
121
121
  # @return [TTTLS13::Message::Extension::$Object, nil]
122
122
  # rubocop: disable Metrics/CyclomaticComplexity
123
123
  # rubocop: disable Metrics/MethodLength
124
+ # rubocop: disable Metrics/PerceivedComplexity
124
125
  def deserialize_extension(binary, extension_type, msg_type)
125
126
  raise Error::ErrorAlerts, :internal_error if binary.nil?
126
127
 
@@ -143,6 +144,8 @@ module TTTLS13
143
144
  Extension::SignatureAlgorithms.deserialize(binary)
144
145
  when ExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION
145
146
  Extension::Alpn.deserialize(binary)
147
+ when ExtensionType::COMPRESS_CERTIFICATE
148
+ Extension::CompressCertificate.deserialize(binary)
146
149
  when ExtensionType::RECORD_SIZE_LIMIT
147
150
  Extension::RecordSizeLimit.deserialize(binary)
148
151
  when ExtensionType::PRE_SHARED_KEY
@@ -165,6 +168,7 @@ module TTTLS13
165
168
  end
166
169
  # rubocop: enable Metrics/CyclomaticComplexity
167
170
  # rubocop: enable Metrics/MethodLength
171
+ # rubocop: enable Metrics/PerceivedComplexity
168
172
  end
169
173
  end
170
174
  end
@@ -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.14'
4
+ VERSION = '0.2.17'
5
5
  end