tttls1.3 0.2.11 → 0.2.12

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: 8f5aa81468afa7bdfe5706ab689499342070b9ccba1c3407e4aef7e7f5f2a6fc
4
- data.tar.gz: 62b65e459cb2f1a0f14e1be474ab711aeb83d313e14cfdafc3b75dba44ddaf95
3
+ metadata.gz: 9677aea746ca98f9d18cfc1e841d836291b7692088cea9fcc3122e88b0bcb32a
4
+ data.tar.gz: e156e172215e1b76c45a4a43c85e6066499f65e0b0bf8a28c2d6fb524fd8940e
5
5
  SHA512:
6
- metadata.gz: f11b5d1dae32d9e9aca363fee567840d0bf2da02a95e4f7930965c03ac3d53b4751d65cfd4eb709ab47a04cb51d4c14a28783e8519ffe0e9a7e479890b017520
7
- data.tar.gz: e24b2a06489681198c28e1b5def42bd512102591c232fa7ccb847d5742a52cb3c62dd7289bfc4012be45f743f176bf945863f03c785805e2eb53412acbad291f
6
+ metadata.gz: f12cffcb976c740136afd8fa7b139400f58cb1a3795e7e7347192630e90b0c8e6c5138e9b98214bbc2a7f88a91ecd58332390ef1c1239ccf9d56a71f3f342743
7
+ data.tar.gz: 5ab10fcdab0e5cac1c4940bb92753c06db1656f615a3146b552b54c119b28483388bbe8b725b8a412b13df0fa3f1f668eaebc7cfb537e10753a3f2e686cf2279
data/.rubocop.yml CHANGED
@@ -1,12 +1,15 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.6
3
3
 
4
- Style/NumericLiterals:
4
+ Style/ConditionalAssignment:
5
5
  Enabled: false
6
6
 
7
7
  Style/Documentation:
8
8
  Enabled: false
9
9
 
10
+ Style/NumericLiterals:
11
+ Enabled: false
12
+
10
13
  Metrics/AbcSize:
11
14
  Max: 30
12
15
 
data/README.md CHANGED
@@ -100,6 +100,8 @@ tttls1.3 client is configurable using keyword arguments.
100
100
  | `:ticket_age_add` | String | nil | The ticket\_age\_add for PSK. |
101
101
  | `:ticket_timestamp` | Integer | nil | The ticket\_timestamp for PSK. |
102
102
  | `:record_size_limit` | Integer | nil | The record\_size\_limit offerd in ClientHello extensions. If not needed to be present, set nil. |
103
+ | `:check_certificate_status` | Boolean | false | If needed to check certificate status, set true. |
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. |
103
105
  | `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
104
106
  | `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
105
107
 
@@ -111,7 +113,7 @@ tttls1.3 server is configurable using keyword arguments.
111
113
  | key | type | default value | description |
112
114
  |-----|------|---------------|-------------|
113
115
  | `:crt_file` | String | nil | Path to the certificate file. This is a required setting. |
114
- | `:chain_files` | Array of OpenSSL::X509::Certificate | nil | Paths to the itermediate certificate files. |
116
+ | `:chain_files` | Array of String | nil | Paths to the itermediate certificate files. |
115
117
  | `:key_file` | String | nil | Path to the private key file. This is a required setting. |
116
118
  | `:cipher_suites` | Array of TTTLS13::CipherSuite constant | `TLS_AES_256_GCM_SHA384`, `TLS_CHACHA20_POLY1305_SHA256`, `TLS_AES_128_GCM_SHA256` | List of supported cipher suites. |
117
119
  | `:signature_algorithms` | Array of TTTLS13::SignatureScheme constant | `ECDSA_SECP256R1_SHA256`, `ECDSA_SECP384R1_SHA384`, `ECDSA_SECP521R1_SHA512`, `RSA_PSS_RSAE_SHA256`, `RSA_PSS_RSAE_SHA384`, `RSA_PSS_RSAE_SHA512`, `RSA_PKCS1_SHA256`, `RSA_PKCS1_SHA384`, `RSA_PKCS1_SHA512` | List of supported signature algorithms. |
data/Rakefile CHANGED
@@ -9,9 +9,11 @@ require 'fileutils'
9
9
  TMP_DIR = __dir__ + '/tmp'
10
10
  CA_KEY = TMP_DIR + '/ca.key'
11
11
  CA_CRT = TMP_DIR + '/ca.crt'
12
+ INTER_KEY = TMP_DIR + '/intermediate.key'
13
+ INTER_CRT = TMP_DIR + '/intermediate.crt'
12
14
  SERVER_KEY = TMP_DIR + '/server.key'
13
15
  SERVER_CRT = TMP_DIR + '/server.crt'
14
- certs = [CA_KEY, CA_CRT, SERVER_KEY, SERVER_CRT]
16
+ certs = [CA_KEY, CA_CRT, INTER_KEY, INTER_CRT, SERVER_KEY, SERVER_CRT]
15
17
 
16
18
  directory TMP_DIR
17
19
 
@@ -64,15 +66,66 @@ file CA_CRT => [TMP_DIR, CA_KEY] do
64
66
  File.write(CA_CRT, ca_crt.to_pem)
65
67
  end
66
68
 
69
+ file INTER_KEY => TMP_DIR do
70
+ puts "generate #{INTER_KEY}..."
71
+ inter_key = OpenSSL::PKey::RSA.generate(2048)
72
+ File.write(INTER_KEY, inter_key.to_pem)
73
+ end
74
+
75
+ file INTER_CRT => [TMP_DIR, INTER_KEY] do
76
+ ca_key = OpenSSL::PKey::RSA.new(File.read(CA_KEY))
77
+ ca_crt = OpenSSL::X509::Certificate.new(File.read(CA_CRT))
78
+ inter_key = OpenSSL::PKey::RSA.new(File.read(INTER_KEY))
79
+
80
+ puts "generate #{INTER_CRT}..."
81
+ sub = OpenSSL::X509::Name.new
82
+ sub.add_entry('CN', 'test-intermediate')
83
+
84
+ inter_crt = OpenSSL::X509::Certificate.new
85
+ inter_crt.not_before = Time.now
86
+ inter_crt.not_after = Time.now + (60 * 60 * 24 * 365 * 10)
87
+ inter_crt.public_key = inter_key.public_key
88
+ inter_crt.serial = OpenSSL::BN.rand(64)
89
+ inter_crt.version = 2
90
+ inter_crt.issuer = ca_crt.subject
91
+ inter_crt.subject = sub
92
+
93
+ factory = OpenSSL::X509::ExtensionFactory.new
94
+ factory.subject_certificate = inter_crt
95
+ factory.issuer_certificate = ca_crt
96
+ inter_crt.add_extension(
97
+ factory.create_extension(
98
+ 'keyUsage',
99
+ 'critical, cRLSign, keyCertSign'
100
+ )
101
+ )
102
+ inter_crt.add_extension(
103
+ factory.create_extension(
104
+ 'basicConstraints',
105
+ 'critical, CA:true'
106
+ )
107
+ )
108
+ inter_crt.add_extension(
109
+ factory.create_extension(
110
+ 'subjectKeyIdentifier',
111
+ 'hash'
112
+ )
113
+ )
114
+
115
+ digest = OpenSSL::Digest::SHA256.new
116
+ inter_crt.sign(ca_key, digest)
117
+ File.write(INTER_CRT, inter_crt.to_pem)
118
+ end
119
+
67
120
  file SERVER_KEY => TMP_DIR do
68
121
  puts "generate #{SERVER_KEY}..."
69
122
  server_key = OpenSSL::PKey::RSA.generate(2048)
70
123
  File.write(SERVER_KEY, server_key.to_pem)
71
124
  end
72
125
 
73
- file SERVER_CRT => [TMP_DIR, CA_CRT, SERVER_KEY] do
74
- ca_key = OpenSSL::PKey::RSA.new(File.read(CA_KEY))
75
- ca_crt = OpenSSL::X509::Certificate.new(File.read(CA_CRT))
126
+ file SERVER_CRT => [TMP_DIR, INTER_CRT, SERVER_KEY] do
127
+ inter_key = OpenSSL::PKey::RSA.new(File.read(INTER_KEY))
128
+ inter_crt = OpenSSL::X509::Certificate.new(File.read(INTER_CRT))
76
129
  server_key = OpenSSL::PKey::RSA.new(File.read(SERVER_KEY))
77
130
 
78
131
  puts "generate #{SERVER_CRT}..."
@@ -85,12 +138,12 @@ file SERVER_CRT => [TMP_DIR, CA_CRT, SERVER_KEY] do
85
138
  server_crt.public_key = server_key.public_key
86
139
  server_crt.serial = OpenSSL::BN.rand(64)
87
140
  server_crt.version = 2
88
- server_crt.issuer = ca_crt.issuer
141
+ server_crt.issuer = inter_crt.subject
89
142
  server_crt.subject = sub
90
143
 
91
144
  factory = OpenSSL::X509::ExtensionFactory.new
92
145
  factory.subject_certificate = server_crt
93
- factory.issuer_certificate = ca_crt
146
+ factory.issuer_certificate = inter_crt
94
147
  server_crt.add_extension(
95
148
  factory.create_extension(
96
149
  'basicConstraints',
@@ -109,9 +162,15 @@ file SERVER_CRT => [TMP_DIR, CA_CRT, SERVER_KEY] do
109
162
  'DNS:localhost'
110
163
  )
111
164
  )
165
+ server_crt.add_extension(
166
+ factory.create_extension(
167
+ 'authorityInfoAccess',
168
+ 'caIssuers;URI:http://localhost:8080,OCSP;URI:http://localhost:8080'
169
+ )
170
+ )
112
171
 
113
172
  digest = OpenSSL::Digest::SHA256.new
114
- server_crt.sign(ca_key, digest)
173
+ server_crt.sign(inter_key, digest)
115
174
  File.write(SERVER_CRT, server_crt.to_pem)
116
175
  end
117
176
 
@@ -22,7 +22,7 @@ process_new_session_ticket = proc do |nst, rms, cs|
22
22
  settings_2nd[:ticket_timestamp] = nst.timestamp
23
23
  end
24
24
  settings_1st = {
25
- ca_file: FileTest.exists?(ca_file) ? ca_file : nil,
25
+ ca_file: File.exist?(ca_file) ? ca_file : nil,
26
26
  alpn: ['http/1.1'],
27
27
  process_new_session_ticket: process_new_session_ticket
28
28
  }
@@ -0,0 +1,31 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'helper'
5
+
6
+ hostname, port = (ARGV[0] || 'localhost:4433').split(':')
7
+ ca_file = __dir__ + '/../tmp/ca.crt'
8
+ req = simple_http_request(hostname)
9
+
10
+ process_certificate_status = proc do |res, cert, chain|
11
+ puts 'stapled OCSPResponse: '
12
+ puts res.basic.status.pretty_inspect unless res.nil?
13
+ puts '-' * 10
14
+
15
+ TTTLS13::Client.softfail_check_certificate_status(res, cert, chain)
16
+ end
17
+
18
+ socket = TCPSocket.new(hostname, port)
19
+ settings = {
20
+ ca_file: File.exist?(ca_file) ? ca_file : nil,
21
+ alpn: ['http/1.1'],
22
+ check_certificate_status: true,
23
+ process_certificate_status: process_certificate_status
24
+ }
25
+ client = TTTLS13::Client.new(socket, hostname, settings)
26
+ client.connect
27
+ client.write(req)
28
+
29
+ print recv_http_response(client)
30
+ client.close unless client.eof?
31
+ socket.close
@@ -10,6 +10,7 @@ port = ARGV[0] || 4433
10
10
 
11
11
  settings = {
12
12
  crt_file: __dir__ + '/../tmp/server.crt',
13
+ chain_files: [__dir__ + '/../tmp/intermediate.crt'],
13
14
  key_file: __dir__ + '/../tmp/server.key',
14
15
  alpn: ['http/1.1']
15
16
  }
data/lib/tttls1.3.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openssl'
4
+ require 'net/http'
4
5
  require 'pp'
5
6
  require 'logger'
6
7
 
@@ -59,6 +59,8 @@ module TTTLS13
59
59
  ticket_age_add: nil,
60
60
  ticket_timestamp: nil,
61
61
  record_size_limit: nil,
62
+ check_certificate_status: false,
63
+ process_certificate_status: nil,
62
64
  compatibility_mode: true,
63
65
  loglevel: Logger::WARN
64
66
  }.freeze
@@ -300,7 +302,8 @@ module TTTLS13
300
302
  message = recv_message(receivable_ccs: true, cipher: hs_rcipher)
301
303
  if message.msg_type == Message::HandshakeType::CERTIFICATE
302
304
  ct = transcript[CT] = message
303
- terminate_invalid_certificate(ct, transcript[CH])
305
+ alert = check_invalid_certificate(ct, transcript[CH])
306
+ terminate(alert) unless alert.nil?
304
307
 
305
308
  @state = ClientState::WAIT_CV
306
309
  elsif message.msg_type == Message::HandshakeType::CERTIFICATE_REQUEST
@@ -314,7 +317,8 @@ module TTTLS13
314
317
  logger.debug('ClientState::WAIT_CERT')
315
318
 
316
319
  ct = transcript[CT] = recv_certificate(hs_rcipher)
317
- terminate_invalid_certificate(ct, transcript[CH])
320
+ alert = check_invalid_certificate(ct, transcript[CH])
321
+ terminate(alert) unless alert.nil?
318
322
 
319
323
  @state = ClientState::WAIT_CV
320
324
  when ClientState::WAIT_CV
@@ -392,6 +396,58 @@ module TTTLS13
392
396
  @succeed_early_data
393
397
  end
394
398
 
399
+ # @param res [OpenSSL::OCSP::Response]
400
+ # @param cert [OpenSSL::X509::Certificate]
401
+ # @param chain [Array of OpenSSL::X509::Certificate, nil]
402
+ #
403
+ # @return [Boolean]
404
+ #
405
+ # @example
406
+ # meth = Client.method(:softfail_check_certificate_status)
407
+ # Client.new(
408
+ # socket,
409
+ # hostname,
410
+ # check_certificate_status: true,
411
+ # process_certificate_status: meth
412
+ # )
413
+ # rubocop: disable Metrics/AbcSize
414
+ # rubocop: disable Metrics/CyclomaticComplexity
415
+ # rubocop: disable Metrics/PerceivedComplexity
416
+ def self.softfail_check_certificate_status(res, cert, chain)
417
+ ocsp_response = res
418
+ store = OpenSSL::X509::Store.new
419
+ store.set_default_paths
420
+ context = OpenSSL::X509::StoreContext.new(store, cert, chain)
421
+ context.verify
422
+ cid = OpenSSL::OCSP::CertificateId.new(cert, context.chain[1])
423
+
424
+ # When NOT received OCSPResponse in TLS handshake, this method will
425
+ # send OCSPRequest. If ocsp_uri is NOT presented in Certificate, return
426
+ # true. Also, if it sends OCSPRequest and does NOT receive a HTTPresponse
427
+ # within 2 seconds, return true.
428
+ if ocsp_response.nil?
429
+ uri = cert.ocsp_uris&.find { |u| URI::DEFAULT_PARSER.make_regexp =~ u }
430
+ return true if uri.nil?
431
+
432
+ begin
433
+ Timeout.timeout(2) { ocsp_response = send_ocsp_request(cid, uri) }
434
+ rescue StandardError
435
+ return true
436
+ end
437
+ end
438
+ return false \
439
+ if ocsp_response.status != OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
440
+
441
+ status = ocsp_response.basic.status.find { |s| s.first.cmp(cid) }
442
+ return false if status[1] != OpenSSL::OCSP::V_CERTSTATUS_GOOD
443
+ return false if !status[3].nil? && status[3] < Time.now
444
+
445
+ ocsp_response.basic.verify(chain, store)
446
+ end
447
+ # rubocop: enable Metrics/AbcSize
448
+ # rubocop: enable Metrics/CyclomaticComplexity
449
+ # rubocop: enable Metrics/PerceivedComplexity
450
+
395
451
  private
396
452
 
397
453
  # @return [Boolean]
@@ -471,6 +527,7 @@ module TTTLS13
471
527
  # @return [Hash of NamedGroup => OpenSSL::PKey::EC.$Object]
472
528
  # rubocop: disable Metrics/AbcSize
473
529
  # rubocop: disable Metrics/CyclomaticComplexity
530
+ # rubocop: disable Metrics/MethodLength
474
531
  # rubocop: disable Metrics/PerceivedComplexity
475
532
  def gen_ch_extensions
476
533
  exs = []
@@ -519,10 +576,15 @@ module TTTLS13
519
576
  exs << Message::Extension::Alpn.new(@settings[:alpn].reject(&:empty?)) \
520
577
  if !@settings[:alpn].nil? && !@settings[:alpn].empty?
521
578
 
579
+ # status_request
580
+ exs << Message::Extension::OCSPStatusRequest.new \
581
+ if @settings[:check_certificate_status]
582
+
522
583
  [Message::Extensions.new(exs), priv_keys]
523
584
  end
524
585
  # rubocop: enable Metrics/AbcSize
525
586
  # rubocop: enable Metrics/CyclomaticComplexity
587
+ # rubocop: enable Metrics/MethodLength
526
588
  # rubocop: enable Metrics/PerceivedComplexity
527
589
 
528
590
  # @param extensions [TTTLS13::Message::Extensions]
@@ -753,16 +815,32 @@ module TTTLS13
753
815
 
754
816
  # @param ct [TTTLS13::Message::Certificate]
755
817
  # @param ch [TTTLS13::Message::ClientHello]
756
- def terminate_invalid_certificate(ct, ch)
757
- terminate(:illegal_parameter) unless ct.appearable_extensions?
818
+ #
819
+ # @return [Symbol, nil] return key of ALERT_DESCRIPTION, if invalid
820
+ def check_invalid_certificate(ct, ch)
821
+ return :illegal_parameter unless ct.appearable_extensions?
758
822
 
759
- terminate(:unsupported_extension) \
823
+ return :unsupported_extension \
760
824
  unless ct.certificate_list.map(&:extensions)
761
825
  .all? { |e| (e.keys - ch.extensions.keys).empty? }
762
826
 
763
- terminate(:certificate_unknown) \
764
- unless trusted_certificate?(ct.certificate_list,
765
- @settings[:ca_file], @hostname)
827
+ return :certificate_unknown unless trusted_certificate?(
828
+ ct.certificate_list,
829
+ @settings[:ca_file],
830
+ @hostname
831
+ )
832
+
833
+ if @settings[:check_certificate_status]
834
+ ee = ct.certificate_list.first
835
+ ocsp_response = ee.extensions[Message::ExtensionType::STATUS_REQUEST]
836
+ &.ocsp_response
837
+ cert = ee.cert_data
838
+ chain = ct.certificate_list[1..]&.map(&:cert_data)
839
+ return :bad_certificate_status_response \
840
+ unless satisfactory_certificate_status?(ocsp_response, cert, chain)
841
+ end
842
+
843
+ nil
766
844
  end
767
845
 
768
846
  # @param ct [TTTLS13::Message::Certificate]
@@ -784,6 +862,15 @@ module TTTLS13
784
862
  )
785
863
  end
786
864
 
865
+ # @param ocsp_response [OpenSSL::OCSP::Response]
866
+ # @param cert [OpenSSL::X509::Certificate]
867
+ # @param chain [Array of OpenSSL::X509::Certificate, nil]
868
+ #
869
+ # @return [Boolean]
870
+ def satisfactory_certificate_status?(ocsp_response, cert, chain)
871
+ @settings[:process_certificate_status]&.call(ocsp_response, cert, chain)
872
+ end
873
+
787
874
  # @param nst [TTTLS13::Message::NewSessionTicket]
788
875
  #
789
876
  # @raise [TTTLS13::Error::ErrorAlerts]
@@ -273,7 +273,7 @@ module TTTLS13
273
273
 
274
274
  # Received a protected ccs, peer MUST abort the handshake.
275
275
  if record.type == Message::ContentType::APPLICATION_DATA &&
276
- record.messages.first.is_a?(Message::ChangeCipherSpec)
276
+ record.messages.any? { |m| m.is_a?(Message::ChangeCipherSpec) }
277
277
  terminate(:unexpected_message)
278
278
  end
279
279
 
@@ -474,8 +474,10 @@ module TTTLS13
474
474
  #
475
475
  # @return [Boolean]
476
476
  def trusted_certificate?(certificate_list, ca_file = nil, hostname = nil)
477
- cert_bin = certificate_list.first.cert_data
478
- cert = OpenSSL::X509::Certificate.new(cert_bin)
477
+ chain = certificate_list.map(&:cert_data).map do |c|
478
+ OpenSSL::X509::Certificate.new(c)
479
+ end
480
+ cert = chain.shift
479
481
 
480
482
  # not support CN matching, only support SAN matching
481
483
  return false if !hostname.nil? && !matching_san?(cert, hostname)
@@ -483,9 +485,6 @@ module TTTLS13
483
485
  store = OpenSSL::X509::Store.new
484
486
  store.set_default_paths
485
487
  store.add_file(ca_file) unless ca_file.nil?
486
- chain = certificate_list[1..].map(&:cert_data).map do |c|
487
- OpenSSL::X509::Certificate.new(c)
488
- end
489
488
  # TODO: parse authorityInfoAccess::CA Issuers
490
489
  ctx = OpenSSL::X509::StoreContext.new(store, cert, chain)
491
490
  now = Time.now
@@ -539,6 +538,32 @@ module TTTLS13
539
538
  end
540
539
  end
541
540
  end
541
+
542
+ class << self
543
+ # @param cid [OpenSSL::OCSP::CertificateId]
544
+ # @param uri [String]
545
+ #
546
+ # @return [OpenSSL::OCSP::Response]
547
+ def send_ocsp_request(cid, uri)
548
+ # generate OCSPRequest
549
+ ocsp_request = OpenSSL::OCSP::Request.new
550
+ ocsp_request.add_certid(cid)
551
+ ocsp_request.add_nonce
552
+ # send HTTP POST
553
+ uri = URI.parse(uri)
554
+ path = uri.path
555
+ path = '/' if path.nil? || path.empty?
556
+ http_response = Net::HTTP.start uri.host, uri.port do |http|
557
+ http.post(
558
+ path,
559
+ ocsp_request.to_der,
560
+ 'content-type' => 'application/ocsp-request'
561
+ )
562
+ end
563
+
564
+ OpenSSL::OCSP::Response.new(http_response.body)
565
+ end
566
+ end
542
567
  end
543
568
  # rubocop: enable Metrics/ClassLength
544
569
  end
@@ -9,23 +9,20 @@ module TTTLS13
9
9
  OCSP = "\x01"
10
10
  end
11
11
 
12
- class StatusRequest
12
+ class OCSPStatusRequest
13
13
  attr_reader :extension_type
14
14
  attr_reader :responder_id_list
15
15
  attr_reader :request_extensions
16
16
 
17
- # @param responder_id_list [Array of String]
18
- # @param request_extensions [String]
17
+ # @param responder_id_list [Array of OpenSSL::ASN1::ASN1Data]
18
+ # @param request_extensions [Array of OpenSSL::ASN1::ASN1Data]
19
19
  #
20
20
  # @example
21
- # StatusRequest.new(
22
- # responder_id_list: [],
23
- # request_extensions: []
24
- # )
25
- def initialize(responder_id_list: [], request_extensions: '')
21
+ # OCSPStatusRequest.new
22
+ def initialize(responder_id_list: [], request_extensions: [])
26
23
  @extension_type = ExtensionType::STATUS_REQUEST
27
24
  @responder_id_list = responder_id_list || []
28
- @request_extensions = request_extensions || ''
25
+ @request_extensions = request_extensions || []
29
26
  end
30
27
 
31
28
  # @return [String]
@@ -34,9 +31,9 @@ module TTTLS13
34
31
  binary += CertificateStatusType::OCSP
35
32
  binary += @responder_id_list.length.to_uint16
36
33
  binary += @responder_id_list.map do |id|
37
- id.length.to_uint16 + id
34
+ id.to_der.prefix_uint16_length
38
35
  end.join
39
- binary += @request_extensions.prefix_uint16_length
36
+ binary += @request_extensions.map(&:to_der).join.prefix_uint16_length
40
37
 
41
38
  @extension_type + binary.prefix_uint16_length
42
39
  end
@@ -45,8 +42,9 @@ module TTTLS13
45
42
  #
46
43
  # @raise [TTTLS13::Error::ErrorAlerts]
47
44
  #
48
- # @return [TTTLS13::Message::Extension::StatusRequest, nil]
45
+ # @return [TTTLS13::Message::Extension::OCSPStatusRequest, nil]
49
46
  # rubocop: disable Metrics/CyclomaticComplexity
47
+ # rubocop: disable Metrics/PerceivedComplexity
50
48
  def self.deserialize(binary)
51
49
  raise Error::ErrorAlerts, :internal_error if binary.nil?
52
50
  return nil if binary.length < 5 ||
@@ -64,14 +62,20 @@ module TTTLS13
64
62
 
65
63
  re_len = Convert.bin2i(binary.slice(i, 2))
66
64
  i += 2
67
- request_extensions = binary.slice(i, re_len)
65
+ exs_bin = binary.slice(i, re_len)
66
+ begin
67
+ request_extensions = OpenSSL::ASN1.decode_all(exs_bin)
68
+ rescue OpenSSL::ASN1::ASN1Error
69
+ return nil
70
+ end
68
71
  i += re_len
69
72
  return nil unless i == binary.length
70
73
 
71
- StatusRequest.new(responder_id_list: responder_id_list,
72
- request_extensions: request_extensions)
74
+ OCSPStatusRequest.new(responder_id_list: responder_id_list,
75
+ request_extensions: request_extensions)
73
76
  end
74
77
  # rubocop: enable Metrics/CyclomaticComplexity
78
+ # rubocop: enable Metrics/PerceivedComplexity
75
79
 
76
80
  class << self
77
81
  private
@@ -80,7 +84,7 @@ module TTTLS13
80
84
  #
81
85
  # @raise [TTTLS13::Error::ErrorAlerts]
82
86
  #
83
- # @return [Array of String, nil] received unparsable binary, nil
87
+ # @return [Array of ASN1Data, nil] received unparsable binary, nil
84
88
  def deserialize_request_ids(binary)
85
89
  raise Error::ErrorAlerts, :internal_error if binary.nil?
86
90
 
@@ -92,7 +96,11 @@ module TTTLS13
92
96
  id_len = Convert.bin2i(binary.slice(i, 2))
93
97
  i += 2
94
98
  id = binary.slice(i, id_len)
95
- request_ids += id
99
+ begin
100
+ request_ids += OpenSSL::ASN1.decode(id)
101
+ rescue OpenSSL::ASN1::ASN1Error
102
+ return nil
103
+ end
96
104
  i += id_len
97
105
  end
98
106
  return nil if i != binary.length
@@ -101,6 +109,54 @@ module TTTLS13
101
109
  end
102
110
  end
103
111
  end
112
+
113
+ class OCSPResponse
114
+ attr_reader :extension_type
115
+ attr_reader :ocsp_response
116
+
117
+ # @param ocsp_response [OpenSSL::OCSP::Response]
118
+ #
119
+ # @example
120
+ # OCSPResponse.new(
121
+ # OpenSSL::OCSP::Response.create(status, basic_resp)
122
+ # )
123
+ def initialize(ocsp_response)
124
+ @extension_type = ExtensionType::STATUS_REQUEST
125
+ @ocsp_response = ocsp_response
126
+ end
127
+
128
+ # @return [String]
129
+ def serialize
130
+ binary = ''
131
+ binary += CertificateStatusType::OCSP
132
+ binary += @ocsp_response.to_der.prefix_uint24_length
133
+
134
+ @extension_type + binary.prefix_uint16_length
135
+ end
136
+
137
+ # @param binary [String]
138
+ #
139
+ # @raise [TTTLS13::Error::ErrorAlerts]
140
+ #
141
+ # @return [TTTLS13::Message::Extension::OCSPResponse, nil]
142
+ def self.deserialize(binary)
143
+ raise Error::ErrorAlerts, :internal_error if binary.nil?
144
+ return nil if binary.length < 4 ||
145
+ binary[0] != CertificateStatusType::OCSP
146
+
147
+ res_len = Convert.bin2i(binary.slice(1, 3))
148
+ res = binary.slice(4, res_len)
149
+ ocsp_response = nil
150
+ begin
151
+ ocsp_response = OpenSSL::OCSP::Response.new(res)
152
+ rescue OpenSSL::OCSP::OCSPError
153
+ return nil
154
+ end
155
+ return nil if 4 + res_len != binary.length
156
+
157
+ OCSPResponse.new(ocsp_response)
158
+ end
159
+ end
104
160
  end
105
161
  end
106
162
  end
@@ -110,12 +110,23 @@ module TTTLS13
110
110
  #
111
111
  # @return [TTTLS13::Message::Extension::$Object, nil]
112
112
  # rubocop: disable Metrics/CyclomaticComplexity
113
+ # rubocop: disable Metrics/MethodLength
114
+ # rubocop: disable Metrics/PerceivedComplexity
113
115
  def deserialize_extension(binary, extension_type, msg_type)
114
116
  raise Error::ErrorAlerts, :internal_error if binary.nil?
115
117
 
116
118
  case extension_type
117
119
  when ExtensionType::SERVER_NAME
118
120
  Extension::ServerName.deserialize(binary)
121
+ when ExtensionType::STATUS_REQUEST
122
+ if msg_type == HandshakeType::CLIENT_HELLO # ||
123
+ # msg_type == HandshakeType::CERTIFICATE_REQUEST
124
+ Extension::OCSPStatusRequest.deserialize(binary)
125
+ elsif msg_type == HandshakeType::CERTIFICATE
126
+ Extension::OCSPResponse.deserialize(binary)
127
+ else
128
+ return nil
129
+ end
119
130
  when ExtensionType::SUPPORTED_GROUPS
120
131
  Extension::SupportedGroups.deserialize(binary)
121
132
  when ExtensionType::SIGNATURE_ALGORITHMS
@@ -143,6 +154,8 @@ module TTTLS13
143
154
  end
144
155
  end
145
156
  # rubocop: enable Metrics/CyclomaticComplexity
157
+ # rubocop: enable Metrics/MethodLength
158
+ # rubocop: enable Metrics/PerceivedComplexity
146
159
  end
147
160
  end
148
161
  end
@@ -61,6 +61,21 @@ module TTTLS13
61
61
  length.to_uint64 + self
62
62
  end
63
63
  end
64
+
65
+ refine OpenSSL::X509::Certificate do
66
+ unless method_defined?(:ocsp_uris)
67
+ define_method(:ocsp_uris) do
68
+ aia = extensions.find { |ex| ex.oid == 'authorityInfoAccess' }
69
+ return nil if aia.nil?
70
+
71
+ ostr = OpenSSL::ASN1.decode(aia.to_der).value.last
72
+ ocsp = OpenSSL::ASN1.decode(ostr.value)
73
+ .map(&:value)
74
+ .select { |des| des.first.value == 'OCSP' }
75
+ ocsp&.map { |o| o[1].value }
76
+ end
77
+ end
78
+ end
64
79
  end
65
80
 
66
81
  module Convert
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTTLS13
4
- VERSION = '0.2.11'
4
+ VERSION = '0.2.12'
5
5
  end
@@ -0,0 +1,18 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIC4TCCAcmgAwIBAgIJALkL6IyOlMwWMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
3
+ BAMMB3Rlc3QtY2EwHhcNMTkxMTI2MDczMzExWhcNMjkxMTIzMDczMzExWjAUMRIw
4
+ EAYDVQQDDAl0ZXN0LW9jc3AwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
5
+ AQDapLrB5S2yXQ9Wt/O9SZzoMW8IChsPgtZYC8h4Z/bcbqRb/6Bq5YfcYxq84cD/
6
+ 8xn7e8R2OCNgva8GBlMy7d0czt3ysLnNlZ+dPu7MU4yS/R40LOhMGEf71mf6PLqj
7
+ 1ecaEclgbIhyIGHlUXQIAnhhpAwzHxKVAhcgBgQFs8NgNViAE3BpjyUW0qXE5RUY
8
+ BQ7V9/Kn/fnsfOk6jMF20V2Kxn5Sj/c+D59+vFX3FmQyqsTKoAKoUuNsFOvHGV0d
9
+ gxLggE5wq4AodrA40MY95HgCZ2rDfEKgfc9rKhLGz6s0etGFMVtjqK6YvpQYUOaS
10
+ 8JStLrGF1eINoJJFibIf69v9AgMBAAGjODA2MAkGA1UdEwQCMAAwEwYDVR0lBAww
11
+ CgYIKwYBBQUHAwkwFAYDVR0RBA0wC4IJdGVzdC1vY3NwMA0GCSqGSIb3DQEBCwUA
12
+ A4IBAQBHC6jRQyZhBJIdfP9CGpNO1dNHicwpFJ61ofwgzW1jEkVfBtVpqvEaEbYE
13
+ LVxru1s8VY281trhwRuZkDRv5hB/CUUbdPICwQlkyCdUoYURrJEm/mirK9494AGh
14
+ f33S+bMXZGAYLYoPYlSGj8EpL1Do3nvJK8//coRJlTEBcfgIIUlRMaeOiGrg3zpM
15
+ 1KGxO3GtG1mpod7BEMv3ZGI85p8wXF4N2Z+phBoAyRGW+R4VW3tF5bbqiKlRr3Lt
16
+ HNsuXHSQykKpxD085eeQLTZGVESrCcmNv8XvVxwGE1r0kmlwexADNvP3HDXseie+
17
+ 8QFIt+zvJb/lDy4xbCT/M4a7L9Gn
18
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpAIBAAKCAQEA2qS6weUtsl0PVrfzvUmc6DFvCAobD4LWWAvIeGf23G6kW/+g
3
+ auWH3GMavOHA//MZ+3vEdjgjYL2vBgZTMu3dHM7d8rC5zZWfnT7uzFOMkv0eNCzo
4
+ TBhH+9Zn+jy6o9XnGhHJYGyIciBh5VF0CAJ4YaQMMx8SlQIXIAYEBbPDYDVYgBNw
5
+ aY8lFtKlxOUVGAUO1ffyp/357HzpOozBdtFdisZ+Uo/3Pg+ffrxV9xZkMqrEyqAC
6
+ qFLjbBTrxxldHYMS4IBOcKuAKHawONDGPeR4Amdqw3xCoH3PayoSxs+rNHrRhTFb
7
+ Y6iumL6UGFDmkvCUrS6xhdXiDaCSRYmyH+vb/QIDAQABAoIBAQC/s1D/siYHzeol
8
+ +XFelI1bVARqwxmI1wmB9wrU7yqViPjYpN+M+iTNyaLm2vUyNH6ibZkKohv6tTUh
9
+ DiiibcXBfWtCX0r5gueIomYThmmpcv6pdnpSRbPPjeRqlhZ6kZBn3hJ3VZGoptXO
10
+ j0UxxKCx03jS1bqgJU4LSNr7+OojjeKh8D9bxwCizhGx9239QwChtQTPr4U3aeTb
11
+ Qwx8WtNH/2zvpdylyXW/eg8MO4WPYXpxWSGQnRJG5knPa7hF+iRnszysbUPNBVUd
12
+ TUQJHBdtukt+7hDbPyMpMu0DwpqhOqsEk2avacWuCYEEE/SWmJ/mvLokbfECSUpy
13
+ ZqfXJPLNAoGBAPtd+m2YVmLJmjO2skv+zGG5KhHNF2cY6xLQWuHW/yChNjSzpLYm
14
+ YygyOd4hBH39ieQkBRs0QOX9S5Dzv6ERU1cr0CVDJeb9TQ9UTxXc01paJ+aoZNr5
15
+ uHoGO16xBR4tmidc4HmbHDFSwmRAFhkooHM9MVACUFABIdWqwEwSZa/HAoGBAN6s
16
+ WhPrsDyRAfKFV9bwD1P5aMPu6pjWOFO3bRIisPRtVzilamCkKvXCh1SyYHaNRjjG
17
+ fQYEZeCZTxHi7GxZltRG5DRsmm8rDz6E4OrTQMHfQNDiuw78uZZ9+YYwaIM3nt1i
18
+ /lN2hs79zj/HPf5qX9rw+CarOL0bdW97a/Monx4bAoGAeMqXXfT3hi9E15bypQxD
19
+ IK6/JaC9n0BdLkRLd/09ymtNxhORkipuOdGw9yo8o2Kj0arxfTol+Z83oedP7dGK
20
+ j/gw5McYvqB4WGZ2PpZIRkHOrMu883FPEexOuVktkWvuiP3brPQ5nwYa/dvCAsMA
21
+ H4CHYuBJwbhZjvinwaaRkN8CgYA9sQh/zmOUVCRy+Yh9jyLgBBCHgDDUyTzvzLjW
22
+ NnBKN+TbV9DiF3mjfxKZX5YkIj3bSvqmaR+Em1Txwqn31tZX15AwCgq7U/W0P4JE
23
+ 7ORbEixV8wsaOuB8FkjEabL677T+5wdJPmRZAq5asyu0yenmsa4+oF9m3S2rBknB
24
+ I3b6EwKBgQD1+0+xdGomMeKHg8jWuDytdlWmNXmbiV0g2yOm533jG67vGDPfgd0H
25
+ PNC62d7r5EhIVJwQZmW/GdOfZ7tI91XN+GjNyslr9t299hoMeRMT+Db2U+mQvKuS
26
+ Oz+MHhO8YnOz9GFbQShqiCFj4zTU/0Ga/BY8Y52lURftt/QIXo+7Vg==
27
+ -----END RSA PRIVATE KEY-----
data/spec/spec_helper.rb CHANGED
@@ -4,6 +4,7 @@
4
4
  RSpec.configure(&:disable_monkey_patching!)
5
5
 
6
6
  # rubocop: disable Style/MixinUsage
7
+ require 'date'
7
8
  require 'tttls1.3'
8
9
  include TTTLS13
9
10
  include TTTLS13::Error
@@ -41,10 +42,43 @@ TESTBINARY_SERVER_NAME = <<BIN.split.map(&:hex).map(&:chr).join
41
42
  00 0d 00 00 0a 67 69 74 68 75 62 2e 63 6f 6d
42
43
  BIN
43
44
 
44
- TESTBINARY_STATUS_REQUEST = <<BIN.split.map(&:hex).map(&:chr).join
45
+ TESTBINARY_OCSP_STATUS_REQUEST = <<BIN.split.map(&:hex).map(&:chr).join
45
46
  01 00 00 00 00
46
47
  BIN
47
48
 
49
+ TESTBINARY_OCSP_RESPONSE = <<BIN.split.map(&:hex).map(&:chr).join
50
+ 01 00 01 d0 30 82 01 cc 0a 01 00 a0 82 01 c5 30
51
+ 82 01 c1 06 09 2b 06 01 05 05 07 30 01 01 04 82
52
+ 01 b2 30 82 01 ae 30 81 97 a1 16 30 14 31 12 30
53
+ 10 06 03 55 04 03 0c 09 74 65 73 74 2d 6f 63 73
54
+ 70 18 0f 32 30 31 39 31 31 32 38 32 30 34 32 32
55
+ 38 5a 30 6c 30 6a 30 42 30 09 06 05 2b 0e 03 02
56
+ 1a 05 00 04 14 71 02 ca 0e ca 3e be d8 31 e6 37
57
+ 40 80 9e 37 f6 da 9f a5 27 04 14 ac c2 63 89 fe
58
+ 4d c6 08 1f 1f 4d 77 9e 12 7a bf 32 b6 d6 12 02
59
+ 09 00 cf 1a 4c 8a cc cc 78 33 80 00 18 0f 32 30
60
+ 31 39 31 31 32 38 32 30 34 32 32 38 5a a0 11 18
61
+ 0f 32 30 32 39 31 31 32 38 32 30 34 32 32 38 5a
62
+ 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03
63
+ 82 01 01 00 42 90 e2 2f f0 25 3b cf 11 75 56 83
64
+ c2 dc 10 d1 e8 d3 74 67 9e df db 0e 03 36 9f 64
65
+ 48 61 8b 50 ca 2c dd fc 82 5b 52 d5 9b 06 64 86
66
+ 70 08 c2 0b ca c9 50 b8 42 42 19 80 8f 6e f0 42
67
+ 92 ac 67 4f 74 fa 2a d2 f4 2f 82 15 11 71 4b bd
68
+ 54 d0 21 fb 0a 91 d3 ba 67 5e cb 7d b2 e6 a2 da
69
+ 30 3d b3 92 3d a9 4e 2c f6 4a 0b 22 96 b2 1d 06
70
+ c3 0a c7 41 5f 9e 22 c0 e0 3f 52 cc ff be dd 52
71
+ 80 3f 68 36 ce c0 02 df ae ab 96 a9 be d8 51 b2
72
+ bd ec f9 e7 98 5e 8a 77 69 b6 f1 60 19 49 f0 58
73
+ 26 70 2f 7b 19 cc d0 13 9e 9c ed 8a 5c 87 34 4c
74
+ fd bd 0f 41 3f 5c d8 1e 26 ce bb dd 17 a7 a4 37
75
+ 8f d8 19 39 5b c9 17 18 ca c3 7a eb 5d e7 ba a1
76
+ 12 23 d6 cb 22 0e e1 bf 9e 40 9b e3 5c b5 6b e3
77
+ aa 6e 93 56 4f da da a1 c6 79 13 9d 5c d6 87 2b
78
+ f7 6a 0f fc 2c 03 b2 41 c4 90 b8 3d 50 1c 8a 9b
79
+ 11 1b 41 83
80
+ BIN
81
+
48
82
  TESTBINARY_SUPPORTED_GROUPS = <<BIN.split.map(&:hex).map(&:chr).join
49
83
  00 06 00 17 00 18 00 19
50
84
  BIN
@@ -4,10 +4,10 @@
4
4
  require_relative 'spec_helper'
5
5
  using Refinements
6
6
 
7
- RSpec.describe StatusRequest do
8
- context 'default status_request' do
7
+ RSpec.describe OCSPStatusRequest do
8
+ context 'default OCSPStatusRequest' do
9
9
  let(:extension) do
10
- StatusRequest.new
10
+ OCSPStatusRequest.new
11
11
  end
12
12
 
13
13
  it 'should be generated' do
@@ -21,9 +21,9 @@ RSpec.describe StatusRequest do
21
21
  end
22
22
  end
23
23
 
24
- context 'valid status_request' do
24
+ context 'valid OCSPStatusRequest' do
25
25
  let(:extension) do
26
- StatusRequest.new(responder_id_list: [], request_extensions: '')
26
+ OCSPStatusRequest.new(responder_id_list: [], request_extensions: [])
27
27
  end
28
28
 
29
29
  it 'should be generated' do
@@ -37,9 +37,9 @@ RSpec.describe StatusRequest do
37
37
  end
38
38
  end
39
39
 
40
- context 'valid status_request, 0 length request ' do
40
+ context 'valid OCSPStatusRequest, 0 length request ' do
41
41
  let(:extension) do
42
- StatusRequest.new(responder_id_list: nil, request_extensions: nil)
42
+ OCSPStatusRequest.new(responder_id_list: nil, request_extensions: nil)
43
43
  end
44
44
 
45
45
  it 'should be generated' do
@@ -53,9 +53,9 @@ RSpec.describe StatusRequest do
53
53
  end
54
54
  end
55
55
 
56
- context 'valid status_request binary' do
56
+ context 'valid OCSPStatusRequest binary' do
57
57
  let(:extension) do
58
- StatusRequest.deserialize(TESTBINARY_STATUS_REQUEST)
58
+ OCSPStatusRequest.deserialize(TESTBINARY_OCSP_STATUS_REQUEST)
59
59
  end
60
60
 
61
61
  it 'should generate valid object' do
@@ -67,7 +67,74 @@ RSpec.describe StatusRequest do
67
67
  it 'should generate serializable object' do
68
68
  expect(extension.serialize)
69
69
  .to eq ExtensionType::STATUS_REQUEST \
70
- + TESTBINARY_STATUS_REQUEST.prefix_uint16_length
70
+ + TESTBINARY_OCSP_STATUS_REQUEST.prefix_uint16_length
71
+ end
72
+ end
73
+ end
74
+
75
+ RSpec.describe OCSPResponse do
76
+ context 'valid OCSPResponse whose status is good' do
77
+ let(:basic_resp) do
78
+ server_crt = OpenSSL::X509::Certificate.new(
79
+ File.read(__dir__ + '/fixtures/rsa_rsa.crt')
80
+ )
81
+ ca_crt = OpenSSL::X509::Certificate.new(
82
+ File.read(__dir__ + '/fixtures/rsa_ca.crt')
83
+ )
84
+ ocsp_crt = OpenSSL::X509::Certificate.new(
85
+ File.read(__dir__ + '/fixtures/rsa_rsa_ocsp.crt')
86
+ )
87
+ ocsp_key = OpenSSL::PKey.read(
88
+ File.read(__dir__ + '/fixtures/rsa_rsa_ocsp.key')
89
+ )
90
+
91
+ br = OpenSSL::OCSP::BasicResponse.new
92
+ cid = OpenSSL::OCSP::CertificateId.new(server_crt, ca_crt)
93
+ br.add_status(
94
+ cid,
95
+ OpenSSL::OCSP::V_CERTSTATUS_GOOD,
96
+ 0,
97
+ nil,
98
+ Time.now,
99
+ DateTime.now.next_day(1).to_time,
100
+ []
101
+ )
102
+ br.sign(ocsp_crt, ocsp_key)
103
+ br
104
+ end
105
+
106
+ let(:ocsp_response) do
107
+ OpenSSL::OCSP::Response.create(
108
+ OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL,
109
+ basic_resp
110
+ )
111
+ end
112
+
113
+ let(:extension) do
114
+ OCSPResponse.new(ocsp_response)
115
+ end
116
+
117
+ it 'should be generated' do
118
+ expect(extension.extension_type).to eq ExtensionType::STATUS_REQUEST
119
+ expect(extension.ocsp_response).to eq ocsp_response
120
+ end
121
+
122
+ it 'should be serialized' do
123
+ binary = CertificateStatusType::OCSP \
124
+ + ocsp_response.to_der.prefix_uint24_length
125
+
126
+ expect(extension.serialize).to eq ExtensionType::STATUS_REQUEST \
127
+ + binary.prefix_uint16_length
128
+ end
129
+ end
130
+
131
+ context 'valid OCSPResponse binary' do
132
+ let(:extension) do
133
+ OCSPResponse.deserialize(TESTBINARY_OCSP_RESPONSE)
134
+ end
135
+
136
+ it 'should generate valid object' do
137
+ expect(extension.extension_type).to eq ExtensionType::STATUS_REQUEST
71
138
  end
72
139
  end
73
140
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tttls1.3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.11
4
+ version: 0.2.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - thekuwayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-05 00:00:00.000000000 Z
11
+ date: 2020-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -73,6 +73,7 @@ files:
73
73
  - example/https_client_using_0rtt.rb
74
74
  - example/https_client_using_hrr.rb
75
75
  - example/https_client_using_hrr_and_ticket.rb
76
+ - example/https_client_using_status_request.rb
76
77
  - example/https_client_using_ticket.rb
77
78
  - example/https_server.rb
78
79
  - interop/client_spec.rb
@@ -144,6 +145,8 @@ files:
144
145
  - spec/fixtures/rsa_ca.key
145
146
  - spec/fixtures/rsa_rsa.crt
146
147
  - spec/fixtures/rsa_rsa.key
148
+ - spec/fixtures/rsa_rsa_ocsp.crt
149
+ - spec/fixtures/rsa_rsa_ocsp.key
147
150
  - spec/fixtures/rsa_rsassaPss.crt
148
151
  - spec/fixtures/rsa_rsassaPss.key
149
152
  - spec/fixtures/rsa_secp256r1.crt
@@ -217,6 +220,8 @@ test_files:
217
220
  - spec/fixtures/rsa_ca.key
218
221
  - spec/fixtures/rsa_rsa.crt
219
222
  - spec/fixtures/rsa_rsa.key
223
+ - spec/fixtures/rsa_rsa_ocsp.crt
224
+ - spec/fixtures/rsa_rsa_ocsp.key
220
225
  - spec/fixtures/rsa_rsassaPss.crt
221
226
  - spec/fixtures/rsa_rsassaPss.key
222
227
  - spec/fixtures/rsa_secp256r1.crt