tttls1.3 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,6 +3,7 @@
3
3
 
4
4
  module TTTLS13
5
5
  using Refinements
6
+
6
7
  module ClientState
7
8
  # initial value is 0, eof value is -1
8
9
  START = 1
@@ -62,11 +63,6 @@ module TTTLS13
62
63
 
63
64
  # rubocop: disable Metrics/ClassLength
64
65
  class Client < Connection
65
- DOWNGRADE_PROTECTION_TLS_1_2 = "\x44\x4F\x57\x4E\x47\x52\x44\x01"
66
- private_constant :DOWNGRADE_PROTECTION_TLS_1_2
67
- DOWNGRADE_PROTECTION_TLS_1_1 = "\x44\x4F\x57\x4E\x47\x52\x44\x00"
68
- private_constant :DOWNGRADE_PROTECTION_TLS_1_1
69
-
70
66
  # @param socket [Socket]
71
67
  # @param hostname [String]
72
68
  # @param settings [Hash]
@@ -79,20 +75,8 @@ module TTTLS13
79
75
  logger.level = @settings[:loglevel]
80
76
 
81
77
  @early_data = ''
82
- @early_data_write_cipher = nil # Cryptograph::$Object
83
78
  @succeed_early_data = false
84
79
  raise Error::ConfigError unless valid_settings?
85
- return unless use_psk?
86
-
87
- digest = CipherSuite.digest(@settings[:psk_cipher_suite])
88
- @psk = gen_psk_from_nst(@settings[:resumption_master_secret],
89
- @settings[:ticket_nonce], digest)
90
- @key_schedule = KeySchedule.new(
91
- psk: @psk,
92
- shared_secret: nil,
93
- cipher_suite: @settings[:psk_cipher_suite],
94
- transcript: @transcript
95
- )
96
80
  end
97
81
 
98
82
  # NOTE:
@@ -135,98 +119,160 @@ module TTTLS13
135
119
  # rubocop: disable Metrics/MethodLength
136
120
  # rubocop: disable Metrics/PerceivedComplexity
137
121
  def connect
122
+ transcript = Transcript.new
123
+ key_schedule = nil # TTTLS13::KeySchedule
124
+ psk = nil
125
+ priv_keys = {} # Hash of NamedGroup => OpenSSL::PKey::$Object
126
+ if use_psk?
127
+ psk = gen_psk_from_nst(
128
+ @settings[:resumption_master_secret],
129
+ @settings[:ticket_nonce],
130
+ CipherSuite.digest(@settings[:psk_cipher_suite])
131
+ )
132
+ key_schedule = KeySchedule.new(
133
+ psk: psk,
134
+ shared_secret: nil,
135
+ cipher_suite: @settings[:psk_cipher_suite],
136
+ transcript: transcript
137
+ )
138
+ end
139
+
140
+ hs_wcipher = nil # TTTLS13::Cryptograph::$Object
141
+ hs_rcipher = nil # TTTLS13::Cryptograph::$Object
142
+ e_wcipher = nil # TTTLS13::Cryptograph::$Object
143
+
138
144
  @state = ClientState::START
139
145
  loop do
140
146
  case @state
141
147
  when ClientState::START
142
148
  logger.debug('ClientState::START')
143
149
 
144
- exs, @priv_keys = gen_ch_extensions
145
- @transcript[CH] = send_client_hello(exs)
150
+ extensions, priv_keys = gen_ch_extensions
151
+ binder_key = (use_psk? ? key_schedule.binder_key_res : nil)
152
+ transcript[CH] = send_client_hello(extensions, binder_key)
153
+
146
154
  send_ccs # compatibility mode
147
155
  if use_early_data?
148
- @early_data_write_cipher \
149
- = gen_cipher(@settings[:psk_cipher_suite],
150
- @key_schedule.early_data_write_key,
151
- @key_schedule.early_data_write_iv)
152
- send_early_data
156
+ e_wcipher = gen_cipher(
157
+ @settings[:psk_cipher_suite],
158
+ key_schedule.early_data_write_key,
159
+ key_schedule.early_data_write_iv
160
+ )
161
+ send_early_data(e_wcipher)
153
162
  end
154
163
 
155
164
  @state = ClientState::WAIT_SH
156
165
  when ClientState::WAIT_SH
157
166
  logger.debug('ClientState::WAIT_SH')
158
167
 
159
- sh = @transcript[SH] = recv_server_hello
160
- terminate(:illegal_parameter) unless sh.only_appearable_extensions?
168
+ sh = transcript[SH] = recv_server_hello
169
+
161
170
  # support only TLS 1.3
162
- terminate(:protocol_version) unless negotiated_tls_1_3?
171
+ terminate(:protocol_version) unless sh.negotiated_tls_1_3?
163
172
 
164
173
  # validate parameters
165
- terminate(:illegal_parameter) unless valid_sh_legacy_version?
166
- terminate(:illegal_parameter) unless valid_sh_random?
167
- terminate(:illegal_parameter) unless valid_sh_legacy_session_id_echo?
168
- terminate(:illegal_parameter) unless valid_sh_cipher_suite?
174
+ terminate(:illegal_parameter) unless sh.appearable_extensions?
175
+ terminate(:illegal_parameter) if sh.downgraded?
169
176
  terminate(:illegal_parameter) \
170
- if @transcript.include?(HRR) &&
171
- neq_hrr_cipher_suite?(sh.cipher_suite)
172
- terminate(:illegal_parameter) unless valid_sh_compression_method?
177
+ unless sh.legacy_compression_method == "\x00"
178
+
179
+ # validate sh using ch
180
+ ch = transcript[CH]
181
+ terminate(:illegal_parameter) \
182
+ unless sh.legacy_version == ch.legacy_version
183
+ terminate(:illegal_parameter) \
184
+ unless sh.legacy_session_id_echo == ch.legacy_session_id
185
+ terminate(:illegal_parameter) \
186
+ unless ch.cipher_suites.include?(sh.cipher_suite)
187
+ terminate(:unsupported_extension) \
188
+ unless (sh.extensions.keys - ch.extensions.keys).empty?
189
+
190
+ # validate sh using hrr
191
+ if transcript.include?(HRR)
192
+ hrr = transcript[HRR]
193
+ terminate(:illegal_parameter) \
194
+ unless sh.cipher_suite == hrr.cipher_suite
195
+
196
+ sh_sv = sh.extensions[Message::ExtensionType::SUPPORTED_VERSIONS]
197
+ hrr_sv = hrr.extensions[Message::ExtensionType::SUPPORTED_VERSIONS]
198
+ terminate(:illegal_parameter) \
199
+ unless sh_sv.versions == hrr_sv.versions
200
+ end
173
201
 
174
202
  # handling HRR
175
203
  if sh.hrr?
176
- terminate(:unexpected_message) if received_2nd_hrr?
204
+ terminate(:unexpected_message) if transcript.include?(HRR)
205
+ ch1 = transcript[CH1] = transcript.delete(CH)
206
+ hrr = transcript[HRR] = transcript.delete(SH)
177
207
 
178
- @transcript[CH1] = @transcript.delete(CH)
179
- @transcript[HRR] = @transcript.delete(SH)
208
+ # validate cookie
209
+ diff_sets = sh.extensions.keys - ch1.extensions.keys
180
210
  terminate(:unsupported_extension) \
181
- unless offered_ch_extensions?(sh.extensions, HRR)
182
- terminate(:illegal_parameter) unless valid_hrr_key_share?
183
-
184
- ch = send_new_client_hello(@transcript[CH1], @transcript[HRR])
185
- @transcript[CH] = ch
211
+ unless (diff_sets - [Message::ExtensionType::COOKIE]).empty?
212
+
213
+ # validate key_share
214
+ # TODO: pre_shared_key
215
+ ngl = ch1.extensions[Message::ExtensionType::SUPPORTED_GROUPS]
216
+ .named_group_list
217
+ kse = ch1.extensions[Message::ExtensionType::KEY_SHARE]
218
+ .key_share_entry
219
+ group = hrr.extensions[Message::ExtensionType::KEY_SHARE]
220
+ .key_share_entry.first.group
221
+ terminate(:illegal_parameter) \
222
+ unless ngl.include?(group) && !kse.map(&:group).include?(group)
223
+
224
+ # send new client_hello
225
+ extensions, pk = gen_newch_extensions(ch1, hrr)
226
+ priv_keys = pk.merge(priv_keys)
227
+ binder_key = (use_psk? ? key_schedule.binder_key_res : nil)
228
+ transcript[CH] = send_new_client_hello(ch1, hrr, extensions,
229
+ binder_key)
186
230
  @state = ClientState::WAIT_SH
187
231
  next
188
232
  end
189
233
 
190
- # validate extensions
191
- terminate(:unsupported_extension) \
192
- unless offered_ch_extensions?(sh.extensions)
193
-
194
- versions \
195
- = sh.extensions[Message::ExtensionType::SUPPORTED_VERSIONS].versions
196
- terminate(:illegal_parameter) \
197
- if @transcript.include?(HRR) &&
198
- neq_hrr_supported_versions?(versions)
199
-
200
234
  # generate shared secret
201
- @psk = nil unless sh.extensions
202
- .include?(Message::ExtensionType::PRE_SHARED_KEY)
203
- terminate(:illegal_parameter) unless valid_sh_key_share?
235
+ psk = nil unless sh.extensions
236
+ .include?(Message::ExtensionType::PRE_SHARED_KEY)
237
+ ch_ks = ch.extensions[Message::ExtensionType::KEY_SHARE]
238
+ .key_share_entry.map(&:group)
239
+ sh_ks = sh.extensions[Message::ExtensionType::KEY_SHARE]
240
+ .key_share_entry.first.group
241
+ terminate(:illegal_parameter) unless ch_ks.include?(sh_ks)
204
242
 
205
243
  kse = sh.extensions[Message::ExtensionType::KEY_SHARE]
206
244
  .key_share_entry.first
207
245
  ke = kse.key_exchange
208
- group = kse.group
209
- priv_key = @priv_keys[group]
210
- shared_secret = gen_shared_secret(ke, priv_key, group)
246
+ @named_group = kse.group
247
+ priv_key = priv_keys[@named_group]
248
+ shared_secret = gen_shared_secret(ke, priv_key, @named_group)
211
249
  @cipher_suite = sh.cipher_suite
212
- @key_schedule = KeySchedule.new(psk: @psk,
213
- shared_secret: shared_secret,
214
- cipher_suite: @cipher_suite,
215
- transcript: @transcript)
216
- @write_cipher = gen_cipher(@cipher_suite,
217
- @key_schedule.client_handshake_write_key,
218
- @key_schedule.client_handshake_write_iv)
219
- @read_cipher = gen_cipher(@cipher_suite,
220
- @key_schedule.server_handshake_write_key,
221
- @key_schedule.server_handshake_write_iv)
250
+ key_schedule = KeySchedule.new(
251
+ psk: psk,
252
+ shared_secret: shared_secret,
253
+ cipher_suite: @cipher_suite,
254
+ transcript: transcript
255
+ )
256
+ @alert_wcipher = hs_wcipher = gen_cipher(
257
+ @cipher_suite,
258
+ key_schedule.client_handshake_write_key,
259
+ key_schedule.client_handshake_write_iv
260
+ )
261
+ hs_rcipher = gen_cipher(
262
+ @cipher_suite,
263
+ key_schedule.server_handshake_write_key,
264
+ key_schedule.server_handshake_write_iv
265
+ )
222
266
  @state = ClientState::WAIT_EE
223
267
  when ClientState::WAIT_EE
224
268
  logger.debug('ClientState::WAIT_EE')
225
269
 
226
- ee = @transcript[EE] = recv_encrypted_extensions
227
- terminate(:illegal_parameter) unless ee.only_appearable_extensions?
270
+ ee = transcript[EE] = recv_encrypted_extensions(hs_rcipher)
271
+ terminate(:illegal_parameter) unless ee.appearable_extensions?
272
+
273
+ ch = transcript[CH]
228
274
  terminate(:unsupported_extension) \
229
- unless offered_ch_extensions?(ee.extensions)
275
+ unless (ee.extensions.keys - ch.extensions.keys).empty?
230
276
 
231
277
  rsl = ee.extensions[Message::ExtensionType::RECORD_SIZE_LIMIT]
232
278
  @send_record_size = rsl.record_size_limit unless rsl.nil?
@@ -235,17 +281,19 @@ module TTTLS13
235
281
  if ee.extensions.include?(Message::ExtensionType::EARLY_DATA)
236
282
 
237
283
  @state = ClientState::WAIT_CERT_CR
238
- @state = ClientState::WAIT_FINISHED unless @psk.nil?
284
+ @state = ClientState::WAIT_FINISHED unless psk.nil?
239
285
  when ClientState::WAIT_CERT_CR
240
286
  logger.debug('ClientState::WAIT_EE')
241
287
 
242
- message = recv_message
288
+ message = recv_message(receivable_ccs: true, cipher: hs_rcipher)
243
289
  if message.msg_type == Message::HandshakeType::CERTIFICATE
244
- ct = @transcript[CT] = message
245
- terminate(:illegal_parameter) unless ct.only_appearable_extensions?
290
+ ct = transcript[CT] = message
291
+ terminate(:illegal_parameter) unless ct.appearable_extensions?
292
+
293
+ ch = transcript[CH]
246
294
  terminate(:unsupported_extension) \
247
295
  unless ct.certificate_list.map(&:extensions)
248
- .all? { |ex| offered_ch_extensions?(ex) }
296
+ .all? { |e| (e.keys - ch.extensions.keys).empty? }
249
297
 
250
298
  terminate(:certificate_unknown) \
251
299
  unless trusted_certificate?(ct.certificate_list,
@@ -253,7 +301,7 @@ module TTTLS13
253
301
 
254
302
  @state = ClientState::WAIT_CV
255
303
  elsif message.msg_type == Message::HandshakeType::CERTIFICATE_REQUEST
256
- @transcript[CR] = message
304
+ transcript[CR] = message
257
305
  # TODO: client authentication
258
306
  @state = ClientState::WAIT_CERT
259
307
  else
@@ -262,11 +310,13 @@ module TTTLS13
262
310
  when ClientState::WAIT_CERT
263
311
  logger.debug('ClientState::WAIT_EE')
264
312
 
265
- ct = @transcript[CT] = recv_certificate
266
- terminate(:illegal_parameter) unless ct.only_appearable_extensions?
313
+ ct = transcript[CT] = recv_certificate(hs_rcipher)
314
+ terminate(:illegal_parameter) unless ct.appearable_extensions?
315
+
316
+ ch = transcript[CH]
267
317
  terminate(:unsupported_extension) \
268
318
  unless ct.certificate_list.map(&:extensions)
269
- .all? { |ex| offered_ch_extensions?(ex) }
319
+ .all? { |e| (e.keys - ch.extensions.keys).empty? }
270
320
 
271
321
  terminate(:certificate_unknown) \
272
322
  unless trusted_certificate?(ct.certificate_list,
@@ -276,27 +326,52 @@ module TTTLS13
276
326
  when ClientState::WAIT_CV
277
327
  logger.debug('ClientState::WAIT_EE')
278
328
 
279
- @transcript[CV] = recv_certificate_verify
280
- terminate(:decrypt_error) unless verified_certificate_verify?
329
+ cv = transcript[CV] = recv_certificate_verify(hs_rcipher)
330
+ digest = CipherSuite.digest(@cipher_suite)
331
+ hash = transcript.hash(digest, CT)
332
+ terminate(:decrypt_error) \
333
+ unless verified_certificate_verify?(transcript[CT], cv, hash)
334
+
335
+ @signature_scheme = cv.signature_scheme
336
+
281
337
  @state = ClientState::WAIT_FINISHED
282
338
  when ClientState::WAIT_FINISHED
283
339
  logger.debug('ClientState::WAIT_EE')
284
340
 
285
- @transcript[SF] = recv_finished
286
- terminate(:decrypt_error) unless verified_finished?
287
- @transcript[EOED] = send_eoed \
341
+ sf = transcript[SF] = recv_finished(hs_rcipher)
342
+ digest = CipherSuite.digest(@cipher_suite)
343
+ verified = verified_finished?(
344
+ finished: sf,
345
+ digest: digest,
346
+ finished_key: key_schedule.server_finished_key,
347
+ hash: transcript.hash(digest, CV)
348
+ )
349
+ terminate(:decrypt_error) unless verified
350
+
351
+ transcript[EOED] = send_eoed(e_wcipher) \
288
352
  if use_early_data? && succeed_early_data?
353
+
289
354
  # TODO: Send Certificate [+ CertificateVerify]
290
- @transcript[CF] = send_finished
291
- @write_cipher = gen_cipher(@cipher_suite,
292
- @key_schedule.client_application_write_key,
293
- @key_schedule.client_application_write_iv)
294
- @read_cipher = gen_cipher(@cipher_suite,
295
- @key_schedule.server_application_write_key,
296
- @key_schedule.server_application_write_iv)
355
+ signature = sign_finished(
356
+ digest: digest,
357
+ finished_key: key_schedule.client_finished_key,
358
+ hash: transcript.hash(digest, EOED)
359
+ )
360
+ transcript[CF] = send_finished(signature, hs_wcipher)
361
+ @alert_wcipher = @ap_wcipher = gen_cipher(
362
+ @cipher_suite,
363
+ key_schedule.client_application_write_key,
364
+ key_schedule.client_application_write_iv
365
+ )
366
+ @ap_rcipher = gen_cipher(
367
+ @cipher_suite,
368
+ key_schedule.server_application_write_key,
369
+ key_schedule.server_application_write_iv
370
+ )
371
+ @resumption_master_secret = key_schedule.resumption_master_secret
297
372
  @state = ClientState::CONNECTED
298
373
  when ClientState::CONNECTED
299
- logger.debug('ClientState::WAIT_EE')
374
+ logger.debug('ClientState::CONNECTED')
300
375
 
301
376
  break
302
377
  end
@@ -369,13 +444,14 @@ module TTTLS13
369
444
  !(@early_data.nil? || @early_data.empty?)
370
445
  end
371
446
 
372
- def send_early_data
447
+ # @param cipher [TTTLS13::Cryptograph::Aead]
448
+ def send_early_data(cipher)
373
449
  ap = Message::ApplicationData.new(@early_data)
374
450
  ap_record = Message::Record.new(
375
451
  type: Message::ContentType::APPLICATION_DATA,
376
452
  legacy_record_version: Message::ProtocolVersion::TLS_1_2,
377
453
  messages: [ap],
378
- cipher: @early_data_write_cipher
454
+ cipher: cipher
379
455
  )
380
456
  send_record(ap_record)
381
457
  end
@@ -395,8 +471,6 @@ module TTTLS13
395
471
 
396
472
  # @return [TTTLS13::Message::Extensions]
397
473
  # @return [Hash of NamedGroup => OpenSSL::PKey::EC.$Object]
398
- # rubocop: disable Metrics/AbcSize
399
- # rubocop: disable Metrics/CyclomaticComplexity
400
474
  def gen_ch_extensions
401
475
  exs = []
402
476
  # supported_versions: only TLS 1.3
@@ -428,24 +502,22 @@ module TTTLS13
428
502
  exs << key_share
429
503
 
430
504
  # server_name
431
- exs << Message::Extension::ServerName.new(@hostname) \
432
- if !@hostname.nil? && !@hostname.empty?
505
+ exs << Message::Extension::ServerName.new(@hostname)
433
506
 
434
507
  # early_data
435
508
  exs << Message::Extension::EarlyDataIndication.new if use_early_data?
436
509
 
437
510
  [Message::Extensions.new(exs), priv_keys]
438
511
  end
439
- # rubocop: enable Metrics/AbcSize
440
- # rubocop: enable Metrics/CyclomaticComplexity
441
512
 
442
- # @param exs [TTTLS13::Message::Extensions]
513
+ # @param extensions [TTTLS13::Message::Extensions]
514
+ # @param binder_key [String, nil]
443
515
  #
444
516
  # @return [TTTLS13::Message::ClientHello]
445
- def send_client_hello(exs)
517
+ def send_client_hello(extensions, binder_key = nil)
446
518
  ch = Message::ClientHello.new(
447
519
  cipher_suites: CipherSuites.new(@settings[:cipher_suites]),
448
- extensions: exs
520
+ extensions: extensions
449
521
  )
450
522
 
451
523
  if use_psk?
@@ -460,18 +532,25 @@ module TTTLS13
460
532
  )
461
533
  ch.extensions[Message::ExtensionType::PSK_KEY_EXCHANGE_MODES] = pkem
462
534
  # at the end, sign PSK binder
463
- sign_psk_binder(ch)
535
+ sign_psk_binder(
536
+ ch: ch,
537
+ binder_key: binder_key
538
+ )
464
539
  end
465
540
 
466
- send_handshakes(Message::ContentType::HANDSHAKE, [ch], @write_cipher)
541
+ send_handshakes(Message::ContentType::HANDSHAKE, [ch],
542
+ Cryptograph::Passer.new)
467
543
 
468
544
  ch
469
545
  end
470
546
 
547
+ # @param ch1 [TTTLS13::Message::ClientHello]
548
+ # @param hrr [TTTLS13::Message::ServerHello]
471
549
  # @param ch [TTTLS13::Message::ClientHello]
550
+ # @param binder_key [String]
472
551
  #
473
552
  # @return [String]
474
- def sign_psk_binder(ch)
553
+ def sign_psk_binder(ch1: nil, hrr: nil, ch:, binder_key:)
475
554
  # pre_shared_key
476
555
  #
477
556
  # binder is computed as an HMAC over a transcript hash containing a
@@ -494,9 +573,13 @@ module TTTLS13
494
573
  )
495
574
  ch.extensions[Message::ExtensionType::PRE_SHARED_KEY] = psk
496
575
 
497
- transcript = @transcript.clone
498
- transcript[CH] = ch
499
- psk.offered_psks.binders[0] = do_sign_psk_binder(digest, transcript)
576
+ psk.offered_psks.binders[0] = do_sign_psk_binder(
577
+ ch1: ch1,
578
+ hrr: hrr,
579
+ ch: ch,
580
+ binder_key: binder_key,
581
+ digest: digest
582
+ )
500
583
  end
501
584
 
502
585
  # @return [Integer]
@@ -507,24 +590,20 @@ module TTTLS13
507
590
  (age + Convert.bin2i(@settings[:ticket_age_add])) % (2**32)
508
591
  end
509
592
 
510
- # NOTE:
511
- # https://tools.ietf.org/html/rfc8446#section-4.1.2
512
- #
513
593
  # @param ch1 [TTTLS13::Message::ClientHello]
514
594
  # @param hrr [TTTLS13::Message::ServerHello]
515
595
  #
516
- # @return [TTTLS13::Message::ClientHello]
517
- def send_new_client_hello(ch1, hrr)
518
- arr = []
519
-
596
+ # @return [TTTLS13::Message::Extensions]
597
+ # @return [Hash of NamedGroup => OpenSSL::PKey::EC.$Object]
598
+ def gen_newch_extensions(ch1, hrr)
599
+ exs = []
520
600
  # key_share
521
601
  if hrr.extensions.include?(Message::ExtensionType::KEY_SHARE)
522
602
  group = hrr.extensions[Message::ExtensionType::KEY_SHARE]
523
603
  .key_share_entry.first.group
524
604
  key_share, priv_keys \
525
605
  = Message::Extension::KeyShare.gen_ch_key_share([group])
526
- arr << key_share
527
- @priv_keys = priv_keys.merge(@priv_keys)
606
+ exs << key_share
528
607
  end
529
608
 
530
609
  # cookie
@@ -535,21 +614,45 @@ module TTTLS13
535
614
  # HelloRetryRequest into a "cookie" extension in the new ClientHello.
536
615
  #
537
616
  # https://tools.ietf.org/html/rfc8446#section-4.2.2
538
- arr << hrr.extensions[Message::ExtensionType::COOKIE] \
617
+ exs << hrr.extensions[Message::ExtensionType::COOKIE] \
539
618
  if hrr.extensions.include?(Message::ExtensionType::COOKIE)
540
619
 
541
620
  # early_data
542
- new_exs = ch1.extensions.merge(Message::Extensions.new(arr))
621
+ new_exs = ch1.extensions.merge(Message::Extensions.new(exs))
543
622
  new_exs.delete(Message::ExtensionType::EARLY_DATA)
623
+
624
+ [new_exs, priv_keys]
625
+ end
626
+
627
+ # NOTE:
628
+ # https://tools.ietf.org/html/rfc8446#section-4.1.2
629
+ #
630
+ # @param ch1 [TTTLS13::Message::ClientHello]
631
+ # @param hrr [TTTLS13::Message::ServerHello]
632
+ # @param extensions [TTTLS13::Message::Extensions]
633
+ # @param binder_key [String, nil]
634
+ #
635
+ # @return [TTTLS13::Message::ClientHello]
636
+ def send_new_client_hello(ch1, hrr, extensions, binder_key = nil)
544
637
  ch = Message::ClientHello.new(
545
638
  legacy_version: ch1.legacy_version,
546
639
  random: ch1.random,
547
640
  legacy_session_id: ch1.legacy_session_id,
548
641
  cipher_suites: ch1.cipher_suites,
549
642
  legacy_compression_methods: ch1.legacy_compression_methods,
550
- extensions: new_exs
643
+ extensions: extensions
551
644
  )
552
- send_handshakes(Message::ContentType::HANDSHAKE, [ch], @write_cipher)
645
+
646
+ # pre_shared_key
647
+ #
648
+ # Updating the "pre_shared_key" extension if present by recomputing
649
+ # the "obfuscated_ticket_age" and binder values.
650
+ if ch1.extensions.include?(Message::ExtensionType::PRE_SHARED_KEY)
651
+ sign_psk_binder(ch1: ch1, hrr: hrr, ch: ch, binder_key: binder_key)
652
+ end
653
+
654
+ send_handshakes(Message::ContentType::HANDSHAKE, [ch],
655
+ Cryptograph::Passer.new)
553
656
 
554
657
  ch
555
658
  end
@@ -558,208 +661,98 @@ module TTTLS13
558
661
  #
559
662
  # @return [TTTLS13::Message::ServerHello]
560
663
  def recv_server_hello
561
- sh = recv_message
664
+ sh = recv_message(receivable_ccs: true, cipher: Cryptograph::Passer.new)
562
665
  terminate(:unexpected_message) unless sh.is_a?(Message::ServerHello)
563
666
 
564
667
  sh
565
668
  end
566
669
 
670
+ # @param cipher [TTTLS13::Cryptograph::Aead]
671
+ #
567
672
  # @raise [TTTLS13::Error::ErrorAlerts]
568
673
  #
569
674
  # @return [TTTLS13::Message::EncryptedExtensions]
570
- def recv_encrypted_extensions
571
- ee = recv_message
675
+ def recv_encrypted_extensions(cipher)
676
+ ee = recv_message(receivable_ccs: true, cipher: cipher)
572
677
  terminate(:unexpected_message) \
573
678
  unless ee.is_a?(Message::EncryptedExtensions)
574
679
 
575
680
  ee
576
681
  end
577
682
 
683
+ # @param cipher [TTTLS13::Cryptograph::Aead]
684
+ #
578
685
  # @raise [TTTLS13::Error::ErrorAlerts]
579
686
  #
580
687
  # @return [TTTLS13::Message::Certificate]
581
- def recv_certificate
582
- ct = recv_message
688
+ def recv_certificate(cipher)
689
+ ct = recv_message(receivable_ccs: true, cipher: cipher)
583
690
  terminate(:unexpected_message) unless ct.is_a?(Message::Certificate)
584
691
 
585
692
  ct
586
693
  end
587
694
 
695
+ # @param cipher [TTTLS13::Cryptograph::Aead]
696
+ #
588
697
  # @raise [TTTLS13::Error::ErrorAlerts]
589
698
  #
590
699
  # @return [TTTLS13::Message::CertificateVerify]
591
- def recv_certificate_verify
592
- cv = recv_message
700
+ def recv_certificate_verify(cipher)
701
+ cv = recv_message(receivable_ccs: true, cipher: cipher)
593
702
  terminate(:unexpected_message) unless cv.is_a?(Message::CertificateVerify)
594
703
 
595
704
  cv
596
705
  end
597
706
 
707
+ # @param cipher [TTTLS13::Cryptograph::Aead]
708
+ #
598
709
  # @raise [TTTLS13::Error::ErrorAlerts]
599
710
  #
600
711
  # @return [TTTLS13::Message::Finished]
601
- def recv_finished
602
- sf = recv_message
712
+ def recv_finished(cipher)
713
+ sf = recv_message(receivable_ccs: true, cipher: cipher)
603
714
  terminate(:unexpected_message) unless sf.is_a?(Message::Finished)
604
715
 
605
716
  sf
606
717
  end
607
718
 
719
+ # @param cipher [TTTLS13::Cryptograph::Aead]
720
+ #
608
721
  # @return [TTTLS13::Message::Finished]
609
- def send_finished
610
- cf = Message::Finished.new(sign_finished)
611
- send_handshakes(Message::ContentType::APPLICATION_DATA, [cf],
612
- @write_cipher)
722
+ def send_finished(signature, cipher)
723
+ cf = Message::Finished.new(signature)
724
+ send_handshakes(Message::ContentType::APPLICATION_DATA, [cf], cipher)
613
725
 
614
726
  cf
615
727
  end
616
728
 
729
+ # @param cipher [TTTLS13::Cryptograph::Aead]
730
+ #
617
731
  # @return [TTTLS13::Message::EndOfEarlyData]
618
- def send_eoed
732
+ def send_eoed(cipher)
619
733
  eoed = Message::EndOfEarlyData.new
620
- send_handshakes(Message::ContentType::APPLICATION_DATA, [eoed],
621
- @early_data_write_cipher)
734
+ send_handshakes(Message::ContentType::APPLICATION_DATA, [eoed], cipher)
622
735
 
623
736
  eoed
624
737
  end
625
738
 
739
+ # @param ct [TTTLS13::Message::Certificate]
740
+ # @param cv [TTTLS13::Message::CertificateVerify]
741
+ # @param hash [String]
742
+ #
626
743
  # @return [Boolean]
627
- def verified_certificate_verify?
628
- ct = @transcript[CT]
744
+ def verified_certificate_verify?(ct, cv, hash)
629
745
  public_key = ct.certificate_list.first.cert_data.public_key
630
- cv = @transcript[CV]
631
746
  signature_scheme = cv.signature_scheme
632
747
  signature = cv.signature
633
- context = 'TLS 1.3, server CertificateVerify'
634
- do_verified_certificate_verify?(public_key: public_key,
635
- signature_scheme: signature_scheme,
636
- signature: signature,
637
- context: context,
638
- handshake_context_end: CT)
639
- end
640
-
641
- # @return [String]
642
- def sign_finished
643
- digest = CipherSuite.digest(@cipher_suite)
644
- finished_key = @key_schedule.client_finished_key
645
- do_sign_finished(digest: digest,
646
- finished_key: finished_key,
647
- handshake_context_end: EOED)
648
- end
649
-
650
- # @return [Boolean]
651
- def verified_finished?
652
- digest = CipherSuite.digest(@cipher_suite)
653
- finished_key = @key_schedule.server_finished_key
654
- signature = @transcript[SF].verify_data
655
- do_verified_finished?(digest: digest,
656
- finished_key: finished_key,
657
- handshake_context_end: CV,
658
- signature: signature)
659
- end
660
-
661
- # NOTE:
662
- # This implementation supports only TLS 1.3,
663
- # so negotiated_tls_1_3? assumes that it sent ClientHello with:
664
- # 1. supported_versions == ["\x03\x04"]
665
- # 2. legacy_versions == ["\x03\x03"]
666
- #
667
- # @return [Boolean]
668
- def negotiated_tls_1_3?
669
- sh = @transcript[SH]
670
- sh_lv = sh.legacy_version
671
- sh_sv = sh.extensions[Message::ExtensionType::SUPPORTED_VERSIONS]
672
- &.versions || []
673
-
674
- sh_lv == Message::ProtocolVersion::TLS_1_2 &&
675
- sh_sv.first == Message::ProtocolVersion::TLS_1_3
676
- end
677
-
678
- # @return [Boolean]
679
- def valid_sh_random?
680
- sh_r8 = @transcript[SH].random[-8..]
681
-
682
- sh_r8 != DOWNGRADE_PROTECTION_TLS_1_2 &&
683
- sh_r8 != DOWNGRADE_PROTECTION_TLS_1_1
684
- end
685
-
686
- # @return [Boolean]
687
- def valid_sh_legacy_version?
688
- @transcript[CH].legacy_version ==
689
- @transcript[SH].legacy_version
690
- end
691
-
692
- # @return [Boolean]
693
- def valid_sh_legacy_session_id_echo?
694
- @transcript[CH].legacy_session_id ==
695
- @transcript[SH].legacy_session_id_echo
696
- end
697
-
698
- # @return [Boolean]
699
- def valid_sh_cipher_suite?
700
- @transcript[CH].cipher_suites.include?(@transcript[SH].cipher_suite)
701
- end
702
-
703
- # @return [Boolean]
704
- def valid_sh_compression_method?
705
- @transcript[SH].legacy_compression_method == "\x00"
706
- end
707
-
708
- # @param extensions [TTTLS13::Message::Extensions]
709
- # @param transcript_index [Integer]
710
- #
711
- # @return [Boolean]
712
- def offered_ch_extensions?(extensions, transcript_index = nil)
713
- keys = extensions.keys
714
- if transcript_index == HRR
715
- keys -= @transcript[CH1].extensions.keys
716
- keys -= [Message::ExtensionType::COOKIE]
717
- else
718
- keys -= @transcript[CH].extensions.keys
719
- end
720
- keys.empty?
721
- end
722
-
723
- # @return [Boolean]
724
- def received_2nd_hrr?
725
- @transcript.include?(HRR)
726
- end
727
-
728
- # @param cipher_suite [TTTLS13::CipherSuite]
729
- #
730
- # @return [Boolean]
731
- def neq_hrr_cipher_suite?(cipher_suite)
732
- cipher_suite != @transcript[HRR].cipher_suite
733
- end
734
748
 
735
- # @param versions [Array of TTTLS13::Message::ProtocolVersion]
736
- #
737
- # @return [Boolean]
738
- def neq_hrr_supported_versions?(versions)
739
- hrr = @transcript[HRR]
740
- versions != hrr.extensions[Message::ExtensionType::SUPPORTED_VERSIONS]
741
- .versions
742
- end
743
-
744
- # @return [Boolean]
745
- def valid_sh_key_share?
746
- offered = @transcript[CH].extensions[Message::ExtensionType::KEY_SHARE]
747
- .key_share_entry.map(&:group)
748
- selected = @transcript[SH].extensions[Message::ExtensionType::KEY_SHARE]
749
- .key_share_entry.first.group
750
- offered.include?(selected)
751
- end
752
-
753
- # @return [Boolean]
754
- def valid_hrr_key_share?
755
- # TODO: pre_shared_key
756
- ch1_exs = @transcript[CH1].extensions
757
- ngl = ch1_exs[Message::ExtensionType::SUPPORTED_GROUPS].named_group_list
758
- kse = ch1_exs[Message::ExtensionType::KEY_SHARE].key_share_entry
759
- group = @transcript[HRR].extensions[Message::ExtensionType::KEY_SHARE]
760
- .key_share_entry.first.group
761
-
762
- ngl.include?(group) && !kse.map(&:group).include?(group)
749
+ do_verified_certificate_verify?(
750
+ public_key: public_key,
751
+ signature_scheme: signature_scheme,
752
+ signature: signature,
753
+ context: 'TLS 1.3, server CertificateVerify',
754
+ hash: hash
755
+ )
763
756
  end
764
757
 
765
758
  # @param nst [TTTLS13::Message::NewSessionTicket]
@@ -768,7 +761,7 @@ module TTTLS13
768
761
  def process_new_session_ticket(nst)
769
762
  super(nst)
770
763
 
771
- rms = @key_schedule.resumption_master_secret
764
+ rms = @resumption_master_secret
772
765
  cs = @cipher_suite
773
766
  @settings[:process_new_session_ticket]&.call(nst, rms, cs)
774
767
  end