tttls1.3 0.2.11 → 0.2.12

Sign up to get free protection for your applications and to get access to all the features.
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