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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba824030b1a295566777d4d12c35e259d379bc9a830b0cb95792356cc547a436
4
- data.tar.gz: c3f2e8fd07567133cce7e8f24fcaf02499b8cceff6088ca403ca2e9be9e5ab5f
3
+ metadata.gz: 1a07aded25aecad8bd61ff9fd49a70df15c8abf356d4747891486dd81386b68d
4
+ data.tar.gz: 4637b3288dab22caae951cc43c283057fd3ed215fc5fa86e318becc3369ac7b2
5
5
  SHA512:
6
- metadata.gz: 00e939bf927db1923274985cdad6526d16b6d99216f62ff3978b3bae9cdcedf675482b96f49a224f9f982f1d8c6f7ca0b49f282086422e73e93b4b74d13f0722
7
- data.tar.gz: 1e523ad0d29d6f29dbd94388f9f895abf69324ceb4336406b13e21793395abdf795a0f043ee89899e888b851d85f2190064e93b70efec092964e34c94b15ac76
6
+ metadata.gz: 621a8f82c99e21e964cfb6defe14e2f8864f1c42cc94c9af725de2ff73929226d99a694c893ada3fc44c5224be70ec87bfcb291eceab271b33e4759c6c900cd8
7
+ data.tar.gz: 9088db06f998013577eb647d064e97035047a2cef7799010bc91f18384787bdf158357fd33c296b92ec1bc07a2ad1b307c98d0217735dfef5c6acf565f3c9433
@@ -3,7 +3,7 @@ name: CI
3
3
  on:
4
4
  push:
5
5
  branches:
6
- - master
6
+ - main
7
7
  pull_request:
8
8
  branches:
9
9
  - '*'
@@ -13,12 +13,14 @@ jobs:
13
13
  runs-on: ubuntu-latest
14
14
  strategy:
15
15
  matrix:
16
- ruby-version: ['2.6.x', '2.7.x']
16
+ ruby-version: ['2.7.x', '3.0.x', '3.1.x']
17
17
  steps:
18
+ - uses: actions/checkout@v3
18
19
  - uses: docker://thekuwayama/openssl:latest
19
20
  - name: Set up Ruby
20
- uses: actions/setup-ruby@v1
21
- - uses: actions/checkout@v1
21
+ uses: ruby/setup-ruby@v1
22
+ with:
23
+ ruby-version: ${{ matrix.ruby }}
22
24
  - name: Install dependencies
23
25
  run: |
24
26
  gem --version
data/.gitignore CHANGED
@@ -14,3 +14,4 @@ Gemfile.lock
14
14
  /coverage/
15
15
  /spec/reports/
16
16
  /tmp/
17
+ .DS_Store
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.6
2
+ TargetRubyVersion: 2.7
3
3
 
4
4
  Style/ConditionalAssignment:
5
5
  Enabled: false
@@ -28,3 +28,7 @@ Metrics/BlockLength:
28
28
  Layout/LineLength:
29
29
  Exclude:
30
30
  - 'tttls1.3.gemspec'
31
+
32
+ # https://github.com/rubocop/rubocop/issues/10258
33
+ Layout/BlockAlignment:
34
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.1.2
data/Gemfile CHANGED
@@ -6,10 +6,12 @@ gem 'logger'
6
6
  gem 'openssl'
7
7
  gem 'rake'
8
8
 
9
- group :test do
9
+ group :development do
10
10
  gem 'byebug'
11
+ gem 'http_parser.rb'
11
12
  gem 'rspec', '3.9.0'
12
13
  gem 'rubocop', '0.78.0'
14
+ gem 'webrick'
13
15
  end
14
16
 
15
17
  gemspec
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/tttls1.3.svg)](https://badge.fury.io/rb/tttls1.3)
4
4
  [![Actions Status](https://github.com/thekuwayama/tttls1.3/workflows/CI/badge.svg)](https://github.com/thekuwayama/tttls1.3/actions?workflow=CI)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/47f3c267d9cfd2c8e388/maintainability)](https://codeclimate.com/github/thekuwayama/tttls1.3/maintainability)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/b5ae1b3a43828142d2fa/maintainability)](https://codeclimate.com/github/thekuwayama/tttls1.3/maintainability)
6
6
 
7
7
  tttls1.3 is Ruby implementation of [TLS 1.3](https://tools.ietf.org/html/rfc8446) protocol.
8
8
 
@@ -74,7 +74,7 @@ server.write(YOUR_MESSAGE)
74
74
  server.close
75
75
  ```
76
76
 
77
- [Here](https://github.com/thekuwayama/tttls1.3/tree/master/example) are some examples of HTTPS.
77
+ [Here](https://github.com/thekuwayama/tttls1.3/tree/main/example) are some examples of HTTPS.
78
78
 
79
79
 
80
80
  ## Settings
@@ -102,7 +102,9 @@ tttls1.3 client is configurable using keyword arguments.
102
102
  | `:record_size_limit` | Integer | nil | The record\_size\_limit offerd in ClientHello extensions. If not needed to be present, set nil. |
103
103
  | `:check_certificate_status` | Boolean | false | If needed to check certificate status, set true. |
104
104
  | `:process_certificate_status` | Proc | `TTTLS13::Client.method(:softfail_check_certificate_status)` | Proc(or Method) that checks received OCSPResponse. Its 3 arguments are OpenSSL::OCSP::Response, end-entity certificate(OpenSSL::X509::Certificate) and certificates chain(Array of Certificate) used for verification and it returns Boolean. |
105
+ | `:compress_certificate_algorithms` | Array of TTTLS13::Message::Extension::CertificateCompressionAlgorithm constant | `ZLIB` | The compression algorithms are supported for compressing the Certificate message. |
105
106
  | `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
107
+ | `:sslkeylogfile` | String | nil | If needed to log SSLKEYLOGFILE, set the file path. |
106
108
  | `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
107
109
 
108
110
 
@@ -120,7 +122,9 @@ tttls1.3 server is configurable using keyword arguments.
120
122
  | `:supported_groups` | Array of TTTLS13::NamedGroup constant | `SECP256R1`, `SECP384R1`, `SECP521R1` | List of supported named groups. |
121
123
  | `:alpn` | Array of String | nil | List of supported application protocols. If not needed to check this extension, set nil. |
122
124
  | `:process_ocsp_response` | Proc | nil | Proc that gets OpenSSL::OCSP::Response. If not needed to staple OCSP::Response, set nil. |
125
+ | `:compress_certificate_algorithms` | Array of TTTLS13::Message::Extension::CertificateCompressionAlgorithm constant | `ZLIB` | The compression algorithms are supported for compressing the Certificate message. |
123
126
  | `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
127
+ | `:sslkeylogfile` | String | nil | If needed to log SSLKEYLOGFILE, set the file path. |
124
128
  | `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
125
129
 
126
130
 
@@ -10,7 +10,8 @@ req = simple_http_request(hostname)
10
10
  socket = TCPSocket.new(hostname, port)
11
11
  settings = {
12
12
  ca_file: File.exist?(ca_file) ? ca_file : nil,
13
- alpn: ['http/1.1']
13
+ alpn: ['http/1.1'],
14
+ sslkeylogfile: '/tmp/sslkeylogfile.log'
14
15
  }
15
16
  client = TTTLS13::Client.new(socket, hostname, **settings)
16
17
  client.connect
@@ -12,7 +12,8 @@ settings = {
12
12
  crt_file: __dir__ + '/../tmp/server.crt',
13
13
  chain_files: [__dir__ + '/../tmp/intermediate.crt'],
14
14
  key_file: __dir__ + '/../tmp/server.key',
15
- alpn: ['http/1.1']
15
+ alpn: ['http/1.1'],
16
+ sslkeylogfile: '/tmp/sslkeylogfile.log'
16
17
  }
17
18
 
18
19
  q = Queue.new
@@ -49,7 +50,7 @@ Etc.nprocessors.times do
49
50
  rescue Timeout::Error
50
51
  logger.warn 'Timeout'
51
52
  ensure
52
- s.close
53
+ s&.close
53
54
  end
54
55
  end
55
56
  end
@@ -43,6 +43,11 @@ module TTTLS13
43
43
  ].freeze
44
44
  private_constant :DEFAULT_CH_NAMED_GROUP_LIST
45
45
 
46
+ DEFALUT_CH_COMPRESS_CERTIFICATE_ALGORITHMS = [
47
+ Message::Extension::CertificateCompressionAlgorithm::ZLIB
48
+ ].freeze
49
+ private_constant :DEFALUT_CH_COMPRESS_CERTIFICATE_ALGORITHMS
50
+
46
51
  DEFAULT_CLIENT_SETTINGS = {
47
52
  ca_file: nil,
48
53
  cipher_suites: DEFAULT_CH_CIPHER_SUITES,
@@ -61,7 +66,9 @@ module TTTLS13
61
66
  record_size_limit: nil,
62
67
  check_certificate_status: false,
63
68
  process_certificate_status: nil,
69
+ compress_certificate_algorithms: DEFALUT_CH_COMPRESS_CERTIFICATE_ALGORITHMS,
64
70
  compatibility_mode: true,
71
+ sslkeylogfile: nil,
65
72
  loglevel: Logger::WARN
66
73
  }.freeze
67
74
  private_constant :DEFAULT_CLIENT_SETTINGS
@@ -145,6 +152,15 @@ module TTTLS13
145
152
  hs_wcipher = nil # TTTLS13::Cryptograph::$Object
146
153
  hs_rcipher = nil # TTTLS13::Cryptograph::$Object
147
154
  e_wcipher = nil # TTTLS13::Cryptograph::$Object
155
+ sslkeylogfile = nil # TTTLS13::SslKeyLogFile::Writer
156
+ unless @settings[:sslkeylogfile].nil?
157
+ begin
158
+ sslkeylogfile = SslKeyLogFile::Writer.new(@settings[:sslkeylogfile])
159
+ rescue SystemCallError => e
160
+ msg = "\"#{@settings[:sslkeylogfile]}\" file can NOT open: #{e}"
161
+ logger.warn(msg)
162
+ end
163
+ end
148
164
 
149
165
  @state = ClientState::START
150
166
  loop do
@@ -154,8 +170,8 @@ module TTTLS13
154
170
 
155
171
  extensions, priv_keys = gen_ch_extensions
156
172
  binder_key = (use_psk? ? key_schedule.binder_key_res : nil)
157
- transcript[CH] = send_client_hello(extensions, binder_key)
158
-
173
+ ch = send_client_hello(extensions, binder_key)
174
+ transcript[CH] = [ch, ch.serialize]
159
175
  send_ccs if @settings[:compatibility_mode]
160
176
  if use_early_data?
161
177
  e_wcipher = gen_cipher(
@@ -163,6 +179,10 @@ module TTTLS13
163
179
  key_schedule.early_data_write_key,
164
180
  key_schedule.early_data_write_iv
165
181
  )
182
+ sslkeylogfile&.write_client_early_traffic_secret(
183
+ transcript[CH].first.random,
184
+ key_schedule.client_early_traffic_secret
185
+ )
166
186
  send_early_data(e_wcipher)
167
187
  end
168
188
 
@@ -170,7 +190,7 @@ module TTTLS13
170
190
  when ClientState::WAIT_SH
171
191
  logger.debug('ClientState::WAIT_SH')
172
192
 
173
- sh = transcript[SH] = recv_server_hello
193
+ sh, = transcript[SH] = recv_server_hello
174
194
 
175
195
  # downgrade protection
176
196
  if !sh.negotiated_tls_1_3? && sh.downgraded?
@@ -187,7 +207,7 @@ module TTTLS13
187
207
  unless sh.legacy_compression_method == "\x00"
188
208
 
189
209
  # validate sh using ch
190
- ch = transcript[CH]
210
+ ch, = transcript[CH]
191
211
  terminate(:illegal_parameter) \
192
212
  unless sh.legacy_version == ch.legacy_version
193
213
  terminate(:illegal_parameter) \
@@ -199,7 +219,7 @@ module TTTLS13
199
219
 
200
220
  # validate sh using hrr
201
221
  if transcript.include?(HRR)
202
- hrr = transcript[HRR]
222
+ hrr, = transcript[HRR]
203
223
  terminate(:illegal_parameter) \
204
224
  unless sh.cipher_suite == hrr.cipher_suite
205
225
 
@@ -212,8 +232,9 @@ module TTTLS13
212
232
  # handling HRR
213
233
  if sh.hrr?
214
234
  terminate(:unexpected_message) if transcript.include?(HRR)
215
- ch1 = transcript[CH1] = transcript.delete(CH)
216
- hrr = transcript[HRR] = transcript.delete(SH)
235
+
236
+ ch1, = transcript[CH1] = transcript.delete(CH)
237
+ hrr, = transcript[HRR] = transcript.delete(SH)
217
238
 
218
239
  # validate cookie
219
240
  diff_sets = sh.extensions.keys - ch1.extensions.keys
@@ -235,8 +256,9 @@ module TTTLS13
235
256
  extensions, pk = gen_newch_extensions(ch1, hrr)
236
257
  priv_keys = pk.merge(priv_keys)
237
258
  binder_key = (use_psk? ? key_schedule.binder_key_res : nil)
238
- transcript[CH] = send_new_client_hello(ch1, hrr, extensions,
239
- binder_key)
259
+ ch = send_new_client_hello(ch1, hrr, extensions, binder_key)
260
+ transcript[CH] = [ch, ch.serialize]
261
+
240
262
  @state = ClientState::WAIT_SH
241
263
  next
242
264
  end
@@ -268,46 +290,63 @@ module TTTLS13
268
290
  key_schedule.client_handshake_write_key,
269
291
  key_schedule.client_handshake_write_iv
270
292
  )
293
+ sslkeylogfile&.write_client_handshake_traffic_secret(
294
+ transcript[CH].first.random,
295
+ key_schedule.client_handshake_traffic_secret
296
+ )
271
297
  hs_rcipher = gen_cipher(
272
298
  @cipher_suite,
273
299
  key_schedule.server_handshake_write_key,
274
300
  key_schedule.server_handshake_write_iv
275
301
  )
302
+ sslkeylogfile&.write_server_handshake_traffic_secret(
303
+ transcript[CH].first.random,
304
+ key_schedule.server_handshake_traffic_secret
305
+ )
276
306
  @state = ClientState::WAIT_EE
277
307
  when ClientState::WAIT_EE
278
308
  logger.debug('ClientState::WAIT_EE')
279
309
 
280
- ee = transcript[EE] = recv_encrypted_extensions(hs_rcipher)
310
+ ee, = transcript[EE] = recv_encrypted_extensions(hs_rcipher)
281
311
  terminate(:illegal_parameter) unless ee.appearable_extensions?
282
312
 
283
- ch = transcript[CH]
313
+ ch, = transcript[CH]
284
314
  terminate(:unsupported_extension) \
285
315
  unless (ee.extensions.keys - ch.extensions.keys).empty?
286
316
 
287
317
  rsl = ee.extensions[Message::ExtensionType::RECORD_SIZE_LIMIT]
288
318
  @recv_record_size = rsl.record_size_limit unless rsl.nil?
289
-
290
319
  @succeed_early_data = true \
291
320
  if ee.extensions.include?(Message::ExtensionType::EARLY_DATA)
292
-
293
321
  @alpn = ee.extensions[
294
322
  Message::ExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION
295
323
  ]&.protocol_name_list&.first
296
-
297
324
  @state = ClientState::WAIT_CERT_CR
298
325
  @state = ClientState::WAIT_FINISHED unless psk.nil?
299
326
  when ClientState::WAIT_CERT_CR
300
327
  logger.debug('ClientState::WAIT_CERT_CR')
301
328
 
302
- message = recv_message(receivable_ccs: true, cipher: hs_rcipher)
303
- if message.msg_type == Message::HandshakeType::CERTIFICATE
304
- ct = transcript[CT] = message
305
- alert = check_invalid_certificate(ct, transcript[CH])
329
+ message, orig_msg = recv_message(
330
+ receivable_ccs: true,
331
+ cipher: hs_rcipher
332
+ )
333
+ case message.msg_type
334
+ when Message::HandshakeType::CERTIFICATE,
335
+ Message::HandshakeType::COMPRESSED_CERTIFICATE
336
+ ct, = transcript[CT] = [message, orig_msg]
337
+ terminate(:bad_certificate) \
338
+ if ct.is_a?(Message::CompressedCertificate) &&
339
+ !@settings[:compress_certificate_algorithms]
340
+ .include?(ct.algorithm)
341
+
342
+ ct = ct.certificate_message \
343
+ if ct.is_a?(Message::CompressedCertificate)
344
+ alert = check_invalid_certificate(ct, transcript[CH].first)
306
345
  terminate(alert) unless alert.nil?
307
346
 
308
347
  @state = ClientState::WAIT_CV
309
- elsif message.msg_type == Message::HandshakeType::CERTIFICATE_REQUEST
310
- transcript[CR] = message
348
+ when Message::HandshakeType::CERTIFICATE_REQUEST
349
+ transcript[CR] = [message, orig_msg]
311
350
  # TODO: client authentication
312
351
  @state = ClientState::WAIT_CERT
313
352
  else
@@ -316,56 +355,74 @@ module TTTLS13
316
355
  when ClientState::WAIT_CERT
317
356
  logger.debug('ClientState::WAIT_CERT')
318
357
 
319
- ct = transcript[CT] = recv_certificate(hs_rcipher)
320
- alert = check_invalid_certificate(ct, transcript[CH])
358
+ ct, = transcript[CT] = recv_certificate(hs_rcipher)
359
+ if ct.is_a?(Message::CompressedCertificate) &&
360
+ !@settings[:compress_certificate_algorithms].include?(ct.algorithm)
361
+ terminate(:bad_certificate)
362
+ elsif ct.is_a?(Message::CompressedCertificate)
363
+ ct = ct.certificate_message
364
+ end
365
+
366
+ alert = check_invalid_certificate(ct, transcript[CH].first)
321
367
  terminate(alert) unless alert.nil?
322
368
 
323
369
  @state = ClientState::WAIT_CV
324
370
  when ClientState::WAIT_CV
325
371
  logger.debug('ClientState::WAIT_CV')
326
372
 
327
- cv = transcript[CV] = recv_certificate_verify(hs_rcipher)
373
+ cv, = transcript[CV] = recv_certificate_verify(hs_rcipher)
328
374
  digest = CipherSuite.digest(@cipher_suite)
329
375
  hash = transcript.hash(digest, CT)
376
+ ct, = transcript[CT]
377
+ ct = ct.certificate_message \
378
+ if ct.is_a?(Message::CompressedCertificate)
330
379
  terminate(:decrypt_error) \
331
- unless verified_certificate_verify?(transcript[CT], cv, hash)
380
+ unless verified_certificate_verify?(ct, cv, hash)
332
381
 
333
382
  @signature_scheme = cv.signature_scheme
334
-
335
383
  @state = ClientState::WAIT_FINISHED
336
384
  when ClientState::WAIT_FINISHED
337
385
  logger.debug('ClientState::WAIT_FINISHED')
338
386
 
339
- sf = transcript[SF] = recv_finished(hs_rcipher)
387
+ sf, = transcript[SF] = recv_finished(hs_rcipher)
340
388
  digest = CipherSuite.digest(@cipher_suite)
341
- verified = verified_finished?(
389
+ terminate(:decrypt_error) unless verified_finished?(
342
390
  finished: sf,
343
391
  digest: digest,
344
392
  finished_key: key_schedule.server_finished_key,
345
393
  hash: transcript.hash(digest, CV)
346
394
  )
347
- terminate(:decrypt_error) unless verified
348
-
349
- transcript[EOED] = send_eoed(e_wcipher) \
350
- if use_early_data? && succeed_early_data?
351
395
 
396
+ if use_early_data? && succeed_early_data?
397
+ eoed = send_eoed(e_wcipher)
398
+ transcript[EOED] = [eoed, eoed.serialize]
399
+ end
352
400
  # TODO: Send Certificate [+ CertificateVerify]
353
401
  signature = sign_finished(
354
402
  digest: digest,
355
403
  finished_key: key_schedule.client_finished_key,
356
404
  hash: transcript.hash(digest, EOED)
357
405
  )
358
- transcript[CF] = send_finished(signature, hs_wcipher)
406
+ cf = send_finished(signature, hs_wcipher)
407
+ transcript[CF] = [cf, cf.serialize]
359
408
  @alert_wcipher = @ap_wcipher = gen_cipher(
360
409
  @cipher_suite,
361
410
  key_schedule.client_application_write_key,
362
411
  key_schedule.client_application_write_iv
363
412
  )
413
+ sslkeylogfile&.write_client_traffic_secret_0(
414
+ transcript[CH].first.random,
415
+ key_schedule.client_application_traffic_secret
416
+ )
364
417
  @ap_rcipher = gen_cipher(
365
418
  @cipher_suite,
366
419
  key_schedule.server_application_write_key,
367
420
  key_schedule.server_application_write_iv
368
421
  )
422
+ sslkeylogfile&.write_server_traffic_secret_0(
423
+ transcript[CH].first.random,
424
+ key_schedule.server_application_traffic_secret
425
+ )
369
426
  @exporter_master_secret = key_schedule.exporter_master_secret
370
427
  @resumption_master_secret = key_schedule.resumption_master_secret
371
428
  @state = ClientState::CONNECTED
@@ -375,6 +432,7 @@ module TTTLS13
375
432
  break
376
433
  end
377
434
  end
435
+ sslkeylogfile&.close
378
436
  end
379
437
  # rubocop: enable Metrics/AbcSize
380
438
  # rubocop: enable Metrics/BlockLength
@@ -578,6 +636,14 @@ module TTTLS13
578
636
  exs << Message::Extension::OCSPStatusRequest.new \
579
637
  if @settings[:check_certificate_status]
580
638
 
639
+ # compress_certificate
640
+ if !@settings[:compress_certificate_algorithms].nil? &&
641
+ !@settings[:compress_certificate_algorithms].empty?
642
+ exs << Message::Extension::CompressCertificate.new(
643
+ @settings[:compress_certificate_algorithms]
644
+ )
645
+ end
646
+
581
647
  [exs, priv_keys]
582
648
  end
583
649
  # rubocop: enable Metrics/AbcSize
@@ -735,11 +801,15 @@ module TTTLS13
735
801
  # @raise [TTTLS13::Error::ErrorAlerts]
736
802
  #
737
803
  # @return [TTTLS13::Message::ServerHello]
804
+ # @return [String]
738
805
  def recv_server_hello
739
- sh = recv_message(receivable_ccs: true, cipher: Cryptograph::Passer.new)
806
+ sh, orig_msg = recv_message(
807
+ receivable_ccs: true,
808
+ cipher: Cryptograph::Passer.new
809
+ )
740
810
  terminate(:unexpected_message) unless sh.is_a?(Message::ServerHello)
741
811
 
742
- sh
812
+ [sh, orig_msg]
743
813
  end
744
814
 
745
815
  # @param cipher [TTTLS13::Cryptograph::Aead]
@@ -747,12 +817,13 @@ module TTTLS13
747
817
  # @raise [TTTLS13::Error::ErrorAlerts]
748
818
  #
749
819
  # @return [TTTLS13::Message::EncryptedExtensions]
820
+ # @return [String]
750
821
  def recv_encrypted_extensions(cipher)
751
- ee = recv_message(receivable_ccs: true, cipher: cipher)
822
+ ee, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
752
823
  terminate(:unexpected_message) \
753
824
  unless ee.is_a?(Message::EncryptedExtensions)
754
825
 
755
- ee
826
+ [ee, orig_msg]
756
827
  end
757
828
 
758
829
  # @param cipher [TTTLS13::Cryptograph::Aead]
@@ -760,11 +831,12 @@ module TTTLS13
760
831
  # @raise [TTTLS13::Error::ErrorAlerts]
761
832
  #
762
833
  # @return [TTTLS13::Message::Certificate]
834
+ # @return [String]
763
835
  def recv_certificate(cipher)
764
- ct = recv_message(receivable_ccs: true, cipher: cipher)
836
+ ct, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
765
837
  terminate(:unexpected_message) unless ct.is_a?(Message::Certificate)
766
838
 
767
- ct
839
+ [ct, orig_msg]
768
840
  end
769
841
 
770
842
  # @param cipher [TTTLS13::Cryptograph::Aead]
@@ -772,11 +844,12 @@ module TTTLS13
772
844
  # @raise [TTTLS13::Error::ErrorAlerts]
773
845
  #
774
846
  # @return [TTTLS13::Message::CertificateVerify]
847
+ # @return [String]
775
848
  def recv_certificate_verify(cipher)
776
- cv = recv_message(receivable_ccs: true, cipher: cipher)
849
+ cv, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
777
850
  terminate(:unexpected_message) unless cv.is_a?(Message::CertificateVerify)
778
851
 
779
- cv
852
+ [cv, orig_msg]
780
853
  end
781
854
 
782
855
  # @param cipher [TTTLS13::Cryptograph::Aead]
@@ -784,11 +857,12 @@ module TTTLS13
784
857
  # @raise [TTTLS13::Error::ErrorAlerts]
785
858
  #
786
859
  # @return [TTTLS13::Message::Finished]
860
+ # @return [String]
787
861
  def recv_finished(cipher)
788
- sf = recv_message(receivable_ccs: true, cipher: cipher)
862
+ sf, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
789
863
  terminate(:unexpected_message) unless sf.is_a?(Message::Finished)
790
864
 
791
- sf
865
+ [sf, orig_msg]
792
866
  end
793
867
 
794
868
  # @param cipher [TTTLS13::Cryptograph::Aead]
@@ -16,7 +16,7 @@ module TTTLS13
16
16
  @ap_wcipher = Cryptograph::Passer.new
17
17
  @ap_rcipher = Cryptograph::Passer.new
18
18
  @alert_wcipher = Cryptograph::Passer.new
19
- @message_queue = [] # Array of TTTLS13::Message::$Object
19
+ @message_queue = [] # Array of [TTTLS13::Message::$Object, String]
20
20
  @binary_buffer = '' # deposit Record.surplus_binary
21
21
  @cipher_suite = nil # TTTLS13::CipherSuite
22
22
  @named_group = nil # TTTLS13::NamedGroup
@@ -42,7 +42,7 @@ module TTTLS13
42
42
 
43
43
  message = nil
44
44
  loop do
45
- message = recv_message(receivable_ccs: false, cipher: @ap_rcipher)
45
+ message, = recv_message(receivable_ccs: false, cipher: @ap_rcipher)
46
46
  # At any time after the server has received the client Finished
47
47
  # message, it MAY send a NewSessionTicket message.
48
48
  break unless message.is_a?(Message::NewSessionTicket)
@@ -220,13 +220,15 @@ module TTTLS13
220
220
  # @raise [TTTLS13::Error::ErrorAlerts
221
221
  #
222
222
  # @return [TTTLS13::Message::$Object]
223
+ # @return [String]
223
224
  # rubocop: disable Metrics/CyclomaticComplexity
224
225
  def recv_message(receivable_ccs:, cipher:)
225
226
  return @message_queue.shift unless @message_queue.empty?
226
227
 
227
228
  messages = nil
229
+ orig_msgs = []
228
230
  loop do
229
- record = recv_record(cipher)
231
+ record, orig_msgs = recv_record(cipher)
230
232
  case record.type
231
233
  when Message::ContentType::HANDSHAKE,
232
234
  Message::ContentType::APPLICATION_DATA
@@ -243,20 +245,22 @@ module TTTLS13
243
245
  end
244
246
  end
245
247
 
246
- @message_queue += messages[1..]
248
+ @message_queue += messages[1..].zip(orig_msgs[1..])
247
249
  message = messages.first
250
+ orig_msg = orig_msgs.first
248
251
  if message.is_a?(Message::Alert)
249
252
  handle_received_alert(message)
250
253
  return nil
251
254
  end
252
255
 
253
- message
256
+ [message, orig_msg]
254
257
  end
255
258
  # rubocop: enable Metrics/CyclomaticComplexity
256
259
 
257
260
  # @param cipher [TTTLS13::Cryptograph::Aead, Passer]
258
261
  #
259
262
  # @return [TTTLS13::Message::Record]
263
+ # @return [Array of String]
260
264
  def recv_record(cipher)
261
265
  binary = @socket.read(5)
262
266
  record_len = Convert.bin2i(binary.slice(3, 2))
@@ -264,9 +268,13 @@ module TTTLS13
264
268
 
265
269
  begin
266
270
  buffer = @binary_buffer
267
- record = Message::Record.deserialize(binary, cipher, buffer,
268
- @recv_record_size)
269
- @binary_buffer = record.surplus_binary
271
+ record, orig_msgs, surplus_binary = Message::Record.deserialize(
272
+ binary,
273
+ cipher,
274
+ buffer,
275
+ @recv_record_size
276
+ )
277
+ @binary_buffer = surplus_binary
270
278
  rescue Error::ErrorAlerts => e
271
279
  terminate(e.message.to_sym)
272
280
  end
@@ -278,7 +286,7 @@ module TTTLS13
278
286
  end
279
287
 
280
288
  logger.debug("receive \n" + record.pretty_inspect)
281
- record
289
+ [record, orig_msgs]
282
290
  end
283
291
 
284
292
  # @param ch1 [TTTLS13::Message::ClientHello]
@@ -292,11 +300,9 @@ module TTTLS13
292
300
  # TODO: ext binder
293
301
  hash_len = OpenSSL::Digest.new(digest).digest_length
294
302
  tt = Transcript.new
295
- tt.merge!(
296
- CH1 => ch1,
297
- HRR => hrr,
298
- CH => ch
299
- )
303
+ tt[CH1] = [ch1, ch1.serialize] unless ch1.nil?
304
+ tt[HRR] = [hrr, hrr.serialize] unless hrr.nil?
305
+ tt[CH] = [ch, ch.serialize]
300
306
  # transcript-hash (CH1 + HRR +) truncated-CH
301
307
  hash = tt.truncate_hash(digest, CH, hash_len + 3)
302
308
  OpenSSL::HMAC.digest(digest, binder_key, hash)
@@ -500,11 +506,10 @@ module TTTLS13
500
506
  return false if san.nil?
501
507
 
502
508
  ostr = OpenSSL::ASN1.decode(san.to_der).value.last
503
- matching = OpenSSL::ASN1.decode(ostr.value).map(&:value)
504
- .map { |s| s.gsub('.', '\.').gsub('*', '.*') }
505
- .any? { |s| name.match(/#{s}/) }
506
-
507
- matching
509
+ OpenSSL::ASN1.decode(ostr.value)
510
+ .map(&:value)
511
+ .map { |s| s.gsub('.', '\.').gsub('*', '.*') }
512
+ .any? { |s| name.match(/#{s}/) }
508
513
  end
509
514
 
510
515
  # @param signature_algorithms [Array of SignatureAlgorithms]
@@ -18,6 +18,7 @@ module TTTLS13
18
18
  ExtensionType::CLIENT_CERTIFICATE_TYPE,
19
19
  ExtensionType::SERVER_CERTIFICATE_TYPE,
20
20
  ExtensionType::PADDING,
21
+ ExtensionType::COMPRESS_CERTIFICATE,
21
22
  ExtensionType::RECORD_SIZE_LIMIT,
22
23
  ExtensionType::PWD_PROTECT,
23
24
  ExtensionType::PWD_CLEAR,