tttls1.3 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,42 +5,42 @@ module TTTLS13
5
5
  INITIAL = 0
6
6
  EOF = -1
7
7
 
8
- SUPPORTED_ECHCONFIG_VERSIONS = ["\xfe\x0d"].freeze
9
- private_constant :SUPPORTED_ECHCONFIG_VERSIONS
10
-
11
8
  # rubocop: disable Metrics/ClassLength
12
9
  class Connection
13
10
  include Logging
14
11
 
12
+ attr_accessor :state
13
+ attr_accessor :ap_wcipher
14
+ attr_accessor :ap_rcipher
15
+ attr_accessor :alert_wcipher
16
+
15
17
  # @param socket [Socket]
16
- def initialize(socket)
18
+ # @param side [:client or :server]
19
+ def initialize(socket, side)
17
20
  @socket = socket
18
- @endpoint = nil # Symbol or String, :client or :server
21
+ @side = side
22
+ @state = INITIAL
19
23
  @ap_wcipher = Cryptograph::Passer.new
20
24
  @ap_rcipher = Cryptograph::Passer.new
21
25
  @alert_wcipher = Cryptograph::Passer.new
22
26
  @message_queue = [] # Array of [TTTLS13::Message::$Object, String]
23
27
  @binary_buffer = '' # deposit Record.surplus_binary
24
- @cipher_suite = nil # TTTLS13::CipherSuite
25
- @named_group = nil # TTTLS13::NamedGroup
26
- @signature_scheme = nil # TTTLS13::SignatureScheme
27
- @state = 0 # ClientState or ServerState
28
28
  @send_record_size = Message::DEFAULT_RECORD_SIZE_LIMIT
29
29
  @recv_record_size = Message::DEFAULT_RECORD_SIZE_LIMIT
30
- @alpn = nil # String
31
- @exporter_secret = nil # String
32
30
  end
33
31
 
32
+ # @param nst_process [Method]
33
+ #
34
34
  # @raise [TTTLS13::Error::ConfigError]
35
35
  #
36
36
  # @return [String]
37
37
  # rubocop: disable Metrics/CyclomaticComplexity
38
38
  # rubocop: disable Metrics/PerceivedComplexity
39
- def read
39
+ def read(nst_process)
40
40
  # secure channel has not established yet
41
41
  raise Error::ConfigError \
42
- unless (@endpoint == :client && @state == ClientState::CONNECTED) ||
43
- (@endpoint == :server && @state == ServerState::CONNECTED)
42
+ unless (@side == :client && @state == ClientState::CONNECTED) ||
43
+ (@side == :server && @state == ServerState::CONNECTED)
44
44
  return '' if @state == EOF
45
45
 
46
46
  message = nil
@@ -50,7 +50,9 @@ module TTTLS13
50
50
  # message, it MAY send a NewSessionTicket message.
51
51
  break unless message.is_a?(Message::NewSessionTicket)
52
52
 
53
- process_new_session_ticket(message)
53
+ terminate(:unexpected_message) if @side == :server
54
+
55
+ nst_process.call(message)
54
56
  end
55
57
  return '' if message.nil?
56
58
 
@@ -70,8 +72,8 @@ module TTTLS13
70
72
  def write(binary)
71
73
  # secure channel has not established yet
72
74
  raise Error::ConfigError \
73
- unless (@endpoint == :client && @state == ClientState::CONNECTED) ||
74
- (@endpoint == :server && @state == ServerState::CONNECTED)
75
+ unless (@side == :client && @state == ClientState::CONNECTED) ||
76
+ (@side == :server && @state == ServerState::CONNECTED)
75
77
 
76
78
  ap = Message::ApplicationData.new(binary)
77
79
  send_application_data(ap, @ap_wcipher)
@@ -82,82 +84,6 @@ module TTTLS13
82
84
 
83
85
  send_alert(:close_notify)
84
86
  @state = EOF
85
-
86
- nil
87
- end
88
-
89
- # @return [TTTLS13::CipherSuite, nil]
90
- def negotiated_cipher_suite
91
- @cipher_suite
92
- end
93
-
94
- # @return [TTTLS13::NamedGroup, nil]
95
- def negotiated_named_group
96
- @named_group
97
- end
98
-
99
- # @return [TTTLS13::SignatureScheme, nil]
100
- def negotiated_signature_scheme
101
- @signature_scheme
102
- end
103
-
104
- # @return [String]
105
- def negotiated_alpn
106
- @alpn
107
- end
108
-
109
- # @param label [String]
110
- # @param context [String]
111
- # @param key_length [Integer]
112
- #
113
- # @return [String, nil]
114
- def exporter(label, context, key_length)
115
- return nil if @exporter_secret.nil? || @cipher_suite.nil?
116
-
117
- digest = CipherSuite.digest(@cipher_suite)
118
- do_exporter(@exporter_secret, digest, label, context, key_length)
119
- end
120
-
121
- private
122
-
123
- # @param secret [String] (early_)exporter_secret
124
- # @param digest [String] name of digest algorithm
125
- # @param label [String]
126
- # @param context [String]
127
- # @param key_length [Integer]
128
- #
129
- # @return [String]
130
- def do_exporter(secret, digest, label, context, key_length)
131
- derived_secret = KeySchedule.hkdf_expand_label(
132
- secret,
133
- label,
134
- OpenSSL::Digest.digest(digest, ''),
135
- OpenSSL::Digest.new(digest).digest_length,
136
- digest
137
- )
138
-
139
- KeySchedule.hkdf_expand_label(
140
- derived_secret,
141
- 'exporter',
142
- OpenSSL::Digest.digest(digest, context),
143
- key_length,
144
- digest
145
- )
146
- end
147
-
148
- # @param cipher_suite [TTTLS13::CipherSuite]
149
- # @param write_key [String]
150
- # @param write_iv [String]
151
- #
152
- # @return [TTTLS13::Cryptograph::Aead]
153
- def gen_cipher(cipher_suite, write_key, write_iv)
154
- seq_num = SequenceNumber.new
155
- Cryptograph::Aead.new(
156
- cipher_suite: cipher_suite,
157
- write_key: write_key,
158
- write_iv: write_iv,
159
- sequence_number: seq_num
160
- )
161
87
  end
162
88
 
163
89
  # @param type [TTTLS13::Message::ContentType]
@@ -213,7 +139,7 @@ module TTTLS13
213
139
 
214
140
  # @param record [TTTLS13::Message::Record]
215
141
  def send_record(record)
216
- logger.debug("send \n" + record.pretty_inspect)
142
+ logger.info(Convert.obj2html(record))
217
143
  @socket.write(record.serialize(@send_record_size))
218
144
  end
219
145
 
@@ -288,167 +214,10 @@ module TTTLS13
288
214
  terminate(:unexpected_message)
289
215
  end
290
216
 
291
- logger.debug("receive \n" + record.pretty_inspect)
217
+ logger.info(Convert.obj2html(record))
292
218
  [record, orig_msgs]
293
219
  end
294
220
 
295
- # @param ch1 [TTTLS13::Message::ClientHello]
296
- # @param hrr [TTTLS13::Message::ServerHello]
297
- # @param ch [TTTLS13::Message::ClientHello]
298
- # @param binder_key [String]
299
- # @param digest [String] name of digest algorithm
300
- #
301
- # @return [String]
302
- def do_sign_psk_binder(ch1:, hrr:, ch:, binder_key:, digest:)
303
- # TODO: ext binder
304
- hash_len = OpenSSL::Digest.new(digest).digest_length
305
- tt = Transcript.new
306
- tt[CH1] = [ch1, ch1.serialize] unless ch1.nil?
307
- tt[HRR] = [hrr, hrr.serialize] unless hrr.nil?
308
- tt[CH] = [ch, ch.serialize]
309
- # transcript-hash (CH1 + HRR +) truncated-CH
310
- hash = tt.truncate_hash(digest, CH, hash_len + 3)
311
- OpenSSL::HMAC.digest(digest, binder_key, hash)
312
- end
313
-
314
- # @param key [OpenSSL::PKey::PKey]
315
- # @param signature_scheme [TTTLS13::SignatureScheme]
316
- # @param context [String]
317
- # @param hash [String]
318
- #
319
- # @raise [TTTLS13::Error::ErrorAlerts]
320
- #
321
- # @return [String]
322
- # rubocop: disable Metrics/CyclomaticComplexity
323
- def do_sign_certificate_verify(key:, signature_scheme:, context:, hash:)
324
- content = "\x20" * 64 + context + "\x00" + hash
325
-
326
- # RSA signatures MUST use an RSASSA-PSS algorithm, regardless of whether
327
- # RSASSA-PKCS1-v1_5 algorithms appear in "signature_algorithms".
328
- case signature_scheme
329
- when SignatureScheme::RSA_PKCS1_SHA256,
330
- SignatureScheme::RSA_PSS_RSAE_SHA256,
331
- SignatureScheme::RSA_PSS_PSS_SHA256
332
- key.sign_pss('SHA256', content, salt_length: :digest,
333
- mgf1_hash: 'SHA256')
334
- when SignatureScheme::RSA_PKCS1_SHA384,
335
- SignatureScheme::RSA_PSS_RSAE_SHA384,
336
- SignatureScheme::RSA_PSS_PSS_SHA384
337
- key.sign_pss('SHA384', content, salt_length: :digest,
338
- mgf1_hash: 'SHA384')
339
- when SignatureScheme::RSA_PKCS1_SHA512,
340
- SignatureScheme::RSA_PSS_RSAE_SHA512,
341
- SignatureScheme::RSA_PSS_PSS_SHA512
342
- key.sign_pss('SHA512', content, salt_length: :digest,
343
- mgf1_hash: 'SHA512')
344
- when SignatureScheme::ECDSA_SECP256R1_SHA256
345
- key.sign('SHA256', content)
346
- when SignatureScheme::ECDSA_SECP384R1_SHA384
347
- key.sign('SHA384', content)
348
- when SignatureScheme::ECDSA_SECP521R1_SHA512
349
- key.sign('SHA512', content)
350
- else # TODO: ED25519, ED448
351
- terminate(:internal_error)
352
- end
353
- end
354
- # rubocop: enable Metrics/CyclomaticComplexity
355
-
356
- # @param public_key [OpenSSL::PKey::PKey]
357
- # @param signature_scheme [TTTLS13::SignatureScheme]
358
- # @param signature [String]
359
- # @param context [String]
360
- # @param hash [String]
361
- #
362
- # @raise [TTTLS13::Error::ErrorAlerts]
363
- #
364
- # @return [Boolean]
365
- # rubocop: disable Metrics/CyclomaticComplexity
366
- def do_verified_certificate_verify?(public_key:, signature_scheme:,
367
- signature:, context:, hash:)
368
- content = "\x20" * 64 + context + "\x00" + hash
369
-
370
- # RSA signatures MUST use an RSASSA-PSS algorithm, regardless of whether
371
- # RSASSA-PKCS1-v1_5 algorithms appear in "signature_algorithms".
372
- case signature_scheme
373
- when SignatureScheme::RSA_PKCS1_SHA256,
374
- SignatureScheme::RSA_PSS_RSAE_SHA256,
375
- SignatureScheme::RSA_PSS_PSS_SHA256
376
- public_key.verify_pss('SHA256', signature, content, salt_length: :auto,
377
- mgf1_hash: 'SHA256')
378
- when SignatureScheme::RSA_PKCS1_SHA384,
379
- SignatureScheme::RSA_PSS_RSAE_SHA384,
380
- SignatureScheme::RSA_PSS_PSS_SHA384
381
- public_key.verify_pss('SHA384', signature, content, salt_length: :auto,
382
- mgf1_hash: 'SHA384')
383
- when SignatureScheme::RSA_PKCS1_SHA512,
384
- SignatureScheme::RSA_PSS_RSAE_SHA512,
385
- SignatureScheme::RSA_PSS_PSS_SHA512
386
- public_key.verify_pss('SHA512', signature, content, salt_length: :auto,
387
- mgf1_hash: 'SHA512')
388
- when SignatureScheme::ECDSA_SECP256R1_SHA256
389
- public_key.verify('SHA256', signature, content)
390
- when SignatureScheme::ECDSA_SECP384R1_SHA384
391
- public_key.verify('SHA384', signature, content)
392
- when SignatureScheme::ECDSA_SECP521R1_SHA512
393
- public_key.verify('SHA512', signature, content)
394
- else # TODO: ED25519, ED448
395
- terminate(:internal_error)
396
- end
397
- end
398
- # rubocop: enable Metrics/CyclomaticComplexity
399
-
400
- # @param digest [String] name of digest algorithm
401
- # @param finished_key [String]
402
- # @param hash [String]
403
- #
404
- # @return [String]
405
- def sign_finished(digest:, finished_key:, hash:)
406
- OpenSSL::HMAC.digest(digest, finished_key, hash)
407
- end
408
-
409
- # @param finished [TTTLS13::Message::Finished]
410
- # @param digest [String] name of digest algorithm
411
- # @param finished_key [String]
412
- # @param hash [String]
413
- #
414
- # @return [Boolean]
415
- def verified_finished?(finished:, digest:, finished_key:, hash:)
416
- sign_finished(digest: digest, finished_key: finished_key, hash: hash) \
417
- == finished.verify_data
418
- end
419
-
420
- # @param key_exchange [String]
421
- # @param priv_key [OpenSSL::PKey::$Object]
422
- # @param group [TTTLS13::NamedGroup]
423
- #
424
- # @return [String]
425
- def gen_shared_secret(key_exchange, priv_key, group)
426
- curve = NamedGroup.curve_name(group)
427
- terminate(:internal_error) if curve.nil?
428
-
429
- pub_key = OpenSSL::PKey::EC::Point.new(
430
- OpenSSL::PKey::EC::Group.new(curve),
431
- OpenSSL::BN.new(key_exchange, 2)
432
- )
433
-
434
- priv_key.dh_compute_key(pub_key)
435
- end
436
-
437
- # @param transcript [TTTLS13::Transcript]
438
- #
439
- # @return [Boolean]
440
- def receivable_ccs?(transcript)
441
- # Received ccs before the first ClientHello message or after the peer's
442
- # Finished message, peer MUST abort.
443
- #
444
- # Server may receive an unprotected record of type change_cipher_spec
445
- # between the first and second ClientHello
446
- finished = (@endpoint == :client ? SF : CF)
447
-
448
- (transcript.include?(CH) || transcript.include?(CH1)) &&
449
- !transcript.include?(finished)
450
- end
451
-
452
221
  # @param symbol [Symbol] key of ALERT_DESCRIPTION
453
222
  #
454
223
  # @raise [TTTLS13::Error::ErrorAlerts]
@@ -467,116 +236,6 @@ module TTTLS13
467
236
  end
468
237
 
469
238
  @state = EOF
470
- nil
471
- end
472
-
473
- # @param _nst [TTTLS13::Message::NewSessionTicket]
474
- #
475
- # @raise [TTTLS13::Error::ErrorAlerts]
476
- def process_new_session_ticket(_nst)
477
- terminate(:unexpected_message) if @endpoint == :server
478
- end
479
-
480
- # @param certificate_list [Array of CertificateEntry]
481
- # @param ca_file [String] path to ca.crt
482
- # @param hostname [String]
483
- #
484
- # @return [Boolean]
485
- def trusted_certificate?(certificate_list, ca_file = nil, hostname = nil)
486
- chain = certificate_list.map(&:cert_data).map do |c|
487
- OpenSSL::X509::Certificate.new(c)
488
- end
489
- cert = chain.shift
490
-
491
- # not support CN matching, only support SAN matching
492
- return false if !hostname.nil? && !matching_san?(cert, hostname)
493
-
494
- store = OpenSSL::X509::Store.new
495
- store.set_default_paths
496
- store.add_file(ca_file) unless ca_file.nil?
497
- # TODO: parse authorityInfoAccess::CA Issuers
498
- ctx = OpenSSL::X509::StoreContext.new(store, cert, chain)
499
- now = Time.now
500
- ctx.verify && cert.not_before < now && now < cert.not_after
501
- end
502
-
503
- # @param cert [OpenSSL::X509::Certificate]
504
- # @param name [String]
505
- #
506
- # @return [Boolean]
507
- def matching_san?(cert, name)
508
- san = cert.extensions.find { |ex| ex.oid == 'subjectAltName' }
509
- return false if san.nil?
510
-
511
- ostr = OpenSSL::ASN1.decode(san.to_der).value.last
512
- OpenSSL::ASN1.decode(ostr.value)
513
- .map(&:value)
514
- .map { |s| s.gsub('.', '\.').gsub('*', '.*') }
515
- .any? { |s| name.match(/#{s}/) }
516
- end
517
-
518
- # @param signature_algorithms [Array of SignatureAlgorithms]
519
- # @param crt [OpenSSL::X509::Certificate]
520
- #
521
- # @return [Array of TTTLS13::Message::Extension::SignatureAlgorithms]
522
- def do_select_signature_algorithms(signature_algorithms, crt)
523
- pka = OpenSSL::ASN1.decode(crt.public_key.to_der)
524
- .value.first.value.first.value
525
- signature_algorithms.select do |sa|
526
- case sa
527
- when SignatureScheme::ECDSA_SECP256R1_SHA256,
528
- SignatureScheme::ECDSA_SECP384R1_SHA384,
529
- SignatureScheme::ECDSA_SECP521R1_SHA512
530
- pka == 'id-ecPublicKey'
531
- when SignatureScheme::RSA_PSS_PSS_SHA256,
532
- SignatureScheme::RSA_PSS_PSS_SHA384,
533
- SignatureScheme::RSA_PSS_PSS_SHA512
534
- pka == 'rsassaPss'
535
- when SignatureScheme::RSA_PSS_RSAE_SHA256,
536
- SignatureScheme::RSA_PSS_RSAE_SHA384,
537
- SignatureScheme::RSA_PSS_RSAE_SHA512
538
- pka == 'rsaEncryption'
539
- else
540
- # RSASSA-PKCS1-v1_5 algorithms refer solely to signatures which appear
541
- # in certificates and are not defined for use in signed TLS handshake
542
- # messages
543
- false
544
- end
545
- end
546
- end
547
-
548
- class << self
549
- # @param cid [OpenSSL::OCSP::CertificateId]
550
- #
551
- # @return [OpenSSL::OCSP::Request]
552
- def gen_ocsp_request(cid)
553
- ocsp_request = OpenSSL::OCSP::Request.new
554
- ocsp_request.add_certid(cid)
555
- ocsp_request.add_nonce
556
- ocsp_request
557
- end
558
-
559
- # @param ocsp_request [OpenSSL::OCSP::Request]
560
- # @param uri_string [String]
561
- #
562
- # @raise [Net::OpenTimeout, OpenSSL::OCSP::OCSPError, URI::$Exception]
563
- #
564
- # @return [OpenSSL::OCSP::Response, n
565
- def send_ocsp_request(ocsp_request, uri_string)
566
- # send HTTP POST
567
- uri = URI.parse(uri_string)
568
- path = uri.path
569
- path = '/' if path.nil? || path.empty?
570
- http_response = Net::HTTP.start(uri.host, uri.port) do |http|
571
- http.post(
572
- path,
573
- ocsp_request.to_der,
574
- 'content-type' => 'application/ocsp-request'
575
- )
576
- end
577
-
578
- OpenSSL::OCSP::Response.new(http_response.body)
579
- end
580
239
  end
581
240
  end
582
241
  # rubocop: enable Metrics/ClassLength