tttls1.3 0.3.1 → 0.3.2

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.
@@ -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