tttls1.3 0.2.12 → 0.2.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +15 -10
- data/.rubocop.yml +1 -1
- data/Gemfile +1 -1
- data/README.md +1 -0
- data/example/helper.rb +3 -3
- data/example/https_client_using_0rtt.rb +1 -1
- data/example/https_client_using_hrr_and_ticket.rb +1 -1
- data/example/https_client_using_status_request.rb +1 -1
- data/example/https_client_using_ticket.rb +1 -1
- data/example/https_server.rb +1 -1
- data/lib/tttls1.3/client.rb +21 -23
- data/lib/tttls1.3/connection.rb +14 -6
- data/lib/tttls1.3/cryptograph.rb +1 -1
- data/lib/tttls1.3/message.rb +1 -1
- data/lib/tttls1.3/message/alert.rb +2 -2
- data/lib/tttls1.3/message/extensions.rb +29 -20
- data/lib/tttls1.3/server.rb +29 -13
- data/lib/tttls1.3/version.rb +1 -1
- data/spec/extensions_spec.rb +16 -0
- data/spec/server_hello_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d292d936d6b26ed1f6307bde684a4f982ea1ee2a7f287eeb306d33b048f855a3
|
4
|
+
data.tar.gz: ef33ef7ce5bd53425d7feb6d7ebf4bca2a3803cf50f930375a441cef0543ab0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 815f58f7d9d0d7c64911979b01304826601767d1397cdeda326856916b15f2d5c8e42b38379d91e9f720c29f2c71f6bdbe308d42e70428413fad345f553e1c42
|
7
|
+
data.tar.gz: fcffc6d40024429db1f4a4c5573b0680ce4fb603aa06d9876f274a202726e72078f538222cf0ea974a7bf444b11821350510fb7a89b1384c0bb25ce05ba7877f
|
data/.github/workflows/main.yml
CHANGED
@@ -11,15 +11,20 @@ on:
|
|
11
11
|
jobs:
|
12
12
|
ci:
|
13
13
|
runs-on: ubuntu-latest
|
14
|
+
strategy:
|
15
|
+
matrix:
|
16
|
+
ruby-version: ['2.6.x']
|
14
17
|
steps:
|
15
|
-
- uses: actions/checkout@v1
|
16
|
-
- uses: actions/setup-ruby@v1
|
17
18
|
- uses: thekuwayama/openssl@master
|
18
|
-
|
19
|
-
|
20
|
-
-
|
21
|
-
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
-
|
19
|
+
- name: Set up Ruby
|
20
|
+
uses: actions/setup-ruby@v1
|
21
|
+
- uses: actions/checkout@v1
|
22
|
+
- name: Install dependencies
|
23
|
+
run: |
|
24
|
+
gem install bundler
|
25
|
+
bundle install
|
26
|
+
- name: Run test
|
27
|
+
run: |
|
28
|
+
bundle exec rake
|
29
|
+
bundle exec rake interop:client
|
30
|
+
bundle exec rake interop:server
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -119,6 +119,7 @@ tttls1.3 server is configurable using keyword arguments.
|
|
119
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. |
|
120
120
|
| `:supported_groups` | Array of TTTLS13::NamedGroup constant | `SECP256R1`, `SECP384R1`, `SECP521R1` | List of supported named groups. |
|
121
121
|
| `:alpn` | Array of String | nil | List of supported application protocols. If not needed to check this extension, set nil. |
|
122
|
+
| `:process_ocsp_response` | Proc | nil | Proc that gets OpenSSL::OCSP::Response. If not needed to staple OCSP::Response, set nil. |
|
122
123
|
| `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
|
123
124
|
| `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
|
124
125
|
|
data/example/helper.rb
CHANGED
@@ -36,7 +36,7 @@ def recv_http_response(client)
|
|
36
36
|
parser = HTTP::Parser.new
|
37
37
|
buf = nil
|
38
38
|
|
39
|
-
parser.on_headers_complete =
|
39
|
+
parser.on_headers_complete = lambda do |headers|
|
40
40
|
buf =
|
41
41
|
[
|
42
42
|
'HTTP/' + parser.http_version.join('.'),
|
@@ -47,11 +47,11 @@ def recv_http_response(client)
|
|
47
47
|
+ WEBrick::CRLF
|
48
48
|
end
|
49
49
|
|
50
|
-
parser.on_body =
|
50
|
+
parser.on_body = lambda do |chunk|
|
51
51
|
buf += chunk
|
52
52
|
end
|
53
53
|
|
54
|
-
parser.on_message_complete =
|
54
|
+
parser.on_message_complete = lambda do
|
55
55
|
client.close
|
56
56
|
end
|
57
57
|
|
@@ -11,7 +11,7 @@ settings_2nd = {
|
|
11
11
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
12
12
|
alpn: ['http/1.1']
|
13
13
|
}
|
14
|
-
process_new_session_ticket =
|
14
|
+
process_new_session_ticket = lambda do |nst, rms, cs|
|
15
15
|
return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
|
16
16
|
|
17
17
|
settings_2nd[:ticket] = nst.ticket
|
@@ -11,7 +11,7 @@ settings_2nd = {
|
|
11
11
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
12
12
|
alpn: ['http/1.1']
|
13
13
|
}
|
14
|
-
process_new_session_ticket =
|
14
|
+
process_new_session_ticket = lambda do |nst, rms, cs|
|
15
15
|
return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
|
16
16
|
|
17
17
|
settings_2nd[:key_share_groups] = [] # empty KeyShareClientHello.client_shares
|
@@ -7,7 +7,7 @@ hostname, port = (ARGV[0] || 'localhost:4433').split(':')
|
|
7
7
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
8
8
|
req = simple_http_request(hostname)
|
9
9
|
|
10
|
-
process_certificate_status =
|
10
|
+
process_certificate_status = lambda do |res, cert, chain|
|
11
11
|
puts 'stapled OCSPResponse: '
|
12
12
|
puts res.basic.status.pretty_inspect unless res.nil?
|
13
13
|
puts '-' * 10
|
@@ -11,7 +11,7 @@ settings_2nd = {
|
|
11
11
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
12
12
|
alpn: ['http/1.1']
|
13
13
|
}
|
14
|
-
process_new_session_ticket =
|
14
|
+
process_new_session_ticket = lambda do |nst, rms, cs|
|
15
15
|
return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
|
16
16
|
|
17
17
|
settings_2nd[:ticket] = nst.ticket
|
data/example/https_server.rb
CHANGED
@@ -26,7 +26,7 @@ Etc.nprocessors.times do
|
|
26
26
|
server = TTTLS13::Server.new(s, settings)
|
27
27
|
parser = HTTP::Parser.new
|
28
28
|
|
29
|
-
parser.on_message_complete =
|
29
|
+
parser.on_message_complete = lambda do
|
30
30
|
if !parser.http_method.nil?
|
31
31
|
logger.info 'Receive Request'
|
32
32
|
server.write(simple_http_response('TEST'))
|
data/lib/tttls1.3/client.rb
CHANGED
@@ -403,23 +403,16 @@ module TTTLS13
|
|
403
403
|
# @return [Boolean]
|
404
404
|
#
|
405
405
|
# @example
|
406
|
-
#
|
406
|
+
# m = Client.method(:softfail_check_certificate_status)
|
407
407
|
# Client.new(
|
408
408
|
# socket,
|
409
409
|
# hostname,
|
410
410
|
# check_certificate_status: true,
|
411
|
-
# process_certificate_status:
|
411
|
+
# process_certificate_status: m
|
412
412
|
# )
|
413
|
-
# rubocop: disable Metrics/AbcSize
|
414
|
-
# rubocop: disable Metrics/CyclomaticComplexity
|
415
|
-
# rubocop: disable Metrics/PerceivedComplexity
|
416
413
|
def self.softfail_check_certificate_status(res, cert, chain)
|
417
414
|
ocsp_response = res
|
418
|
-
|
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])
|
415
|
+
cid = OpenSSL::OCSP::CertificateId.new(cert, chain.first)
|
423
416
|
|
424
417
|
# When NOT received OCSPResponse in TLS handshake, this method will
|
425
418
|
# send OCSPRequest. If ocsp_uri is NOT presented in Certificate, return
|
@@ -430,23 +423,25 @@ module TTTLS13
|
|
430
423
|
return true if uri.nil?
|
431
424
|
|
432
425
|
begin
|
433
|
-
|
426
|
+
# send OCSP::Request
|
427
|
+
ocsp_request = gen_ocsp_request(cid)
|
428
|
+
Timeout.timeout(2) do
|
429
|
+
ocsp_response = send_ocsp_request(ocsp_request, uri)
|
430
|
+
end
|
431
|
+
|
432
|
+
# check nonce of OCSP::Response
|
433
|
+
check_nonce = ocsp_request.check_nonce(ocsp_response.basic)
|
434
|
+
return true unless [-1, 1].include?(check_nonce)
|
434
435
|
rescue StandardError
|
435
436
|
return true
|
436
437
|
end
|
437
438
|
end
|
438
|
-
return
|
439
|
+
return true \
|
439
440
|
if ocsp_response.status != OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
|
440
441
|
|
441
442
|
status = ocsp_response.basic.status.find { |s| s.first.cmp(cid) }
|
442
|
-
|
443
|
-
return false if !status[3].nil? && status[3] < Time.now
|
444
|
-
|
445
|
-
ocsp_response.basic.verify(chain, store)
|
443
|
+
status[1] != OpenSSL::OCSP::V_CERTSTATUS_REVOKED
|
446
444
|
end
|
447
|
-
# rubocop: enable Metrics/AbcSize
|
448
|
-
# rubocop: enable Metrics/CyclomaticComplexity
|
449
|
-
# rubocop: enable Metrics/PerceivedComplexity
|
450
445
|
|
451
446
|
private
|
452
447
|
|
@@ -479,6 +474,9 @@ module TTTLS13
|
|
479
474
|
rsl = @settings[:record_size_limit]
|
480
475
|
return false if !rsl.nil? && (rsl < 64 || rsl > 2**14 + 1)
|
481
476
|
|
477
|
+
return false if @settings[:check_certificate_status] &&
|
478
|
+
@settings[:process_certificate_status].nil?
|
479
|
+
|
482
480
|
true
|
483
481
|
end
|
484
482
|
# rubocop: enable Metrics/AbcSize
|
@@ -530,7 +528,7 @@ module TTTLS13
|
|
530
528
|
# rubocop: disable Metrics/MethodLength
|
531
529
|
# rubocop: disable Metrics/PerceivedComplexity
|
532
530
|
def gen_ch_extensions
|
533
|
-
exs =
|
531
|
+
exs = Message::Extensions.new
|
534
532
|
# server_name
|
535
533
|
exs << Message::Extension::ServerName.new(@hostname)
|
536
534
|
|
@@ -580,7 +578,7 @@ module TTTLS13
|
|
580
578
|
exs << Message::Extension::OCSPStatusRequest.new \
|
581
579
|
if @settings[:check_certificate_status]
|
582
580
|
|
583
|
-
[
|
581
|
+
[exs, priv_keys]
|
584
582
|
end
|
585
583
|
# rubocop: enable Metrics/AbcSize
|
586
584
|
# rubocop: enable Metrics/CyclomaticComplexity
|
@@ -673,7 +671,7 @@ module TTTLS13
|
|
673
671
|
# @return [TTTLS13::Message::Extensions]
|
674
672
|
# @return [Hash of NamedGroup => OpenSSL::PKey::EC.$Object]
|
675
673
|
def gen_newch_extensions(ch1, hrr)
|
676
|
-
exs =
|
674
|
+
exs = Message::Extensions.new
|
677
675
|
# key_share
|
678
676
|
if hrr.extensions.include?(Message::ExtensionType::KEY_SHARE)
|
679
677
|
group = hrr.extensions[Message::ExtensionType::KEY_SHARE]
|
@@ -695,7 +693,7 @@ module TTTLS13
|
|
695
693
|
if hrr.extensions.include?(Message::ExtensionType::COOKIE)
|
696
694
|
|
697
695
|
# early_data
|
698
|
-
new_exs = ch1.extensions.merge(
|
696
|
+
new_exs = ch1.extensions.merge(exs)
|
699
697
|
new_exs.delete(Message::ExtensionType::EARLY_DATA)
|
700
698
|
|
701
699
|
[new_exs, priv_keys]
|
data/lib/tttls1.3/connection.rb
CHANGED
@@ -541,19 +541,27 @@ module TTTLS13
|
|
541
541
|
|
542
542
|
class << self
|
543
543
|
# @param cid [OpenSSL::OCSP::CertificateId]
|
544
|
-
# @param uri [String]
|
545
544
|
#
|
546
|
-
# @return [OpenSSL::OCSP::
|
547
|
-
def
|
548
|
-
# generate OCSPRequest
|
545
|
+
# @return [OpenSSL::OCSP::Request]
|
546
|
+
def gen_ocsp_request(cid)
|
549
547
|
ocsp_request = OpenSSL::OCSP::Request.new
|
550
548
|
ocsp_request.add_certid(cid)
|
551
549
|
ocsp_request.add_nonce
|
550
|
+
ocsp_request
|
551
|
+
end
|
552
|
+
|
553
|
+
# @param ocsp_request [OpenSSL::OCSP::Request]
|
554
|
+
# @param uri_string [String]
|
555
|
+
#
|
556
|
+
# @raise [Net::OpenTimeout, OpenSSL::OCSP::OCSPError, URI::$Exception]
|
557
|
+
#
|
558
|
+
# @return [OpenSSL::OCSP::Response, n
|
559
|
+
def send_ocsp_request(ocsp_request, uri_string)
|
552
560
|
# send HTTP POST
|
553
|
-
uri = URI.parse(
|
561
|
+
uri = URI.parse(uri_string)
|
554
562
|
path = uri.path
|
555
563
|
path = '/' if path.nil? || path.empty?
|
556
|
-
http_response = Net::HTTP.start
|
564
|
+
http_response = Net::HTTP.start(uri.host, uri.port) do |http|
|
557
565
|
http.post(
|
558
566
|
path,
|
559
567
|
ocsp_request.to_der,
|
data/lib/tttls1.3/cryptograph.rb
CHANGED
data/lib/tttls1.3/message.rb
CHANGED
@@ -8,7 +8,7 @@ module TTTLS13
|
|
8
8
|
FATAL = "\x02"
|
9
9
|
end
|
10
10
|
|
11
|
-
# rubocop: disable Layout/
|
11
|
+
# rubocop: disable Layout/HashAlignment
|
12
12
|
ALERT_DESCRIPTION = {
|
13
13
|
close_notify: "\x00",
|
14
14
|
unexpected_message: "\x0a",
|
@@ -38,7 +38,7 @@ module TTTLS13
|
|
38
38
|
certificate_required: "\x74",
|
39
39
|
no_application_protocol: "\x78"
|
40
40
|
}.freeze
|
41
|
-
# rubocop: enable Layout/
|
41
|
+
# rubocop: enable Layout/HashAlignment
|
42
42
|
|
43
43
|
class Alert
|
44
44
|
attr_reader :level
|
@@ -44,10 +44,11 @@ module TTTLS13
|
|
44
44
|
#
|
45
45
|
# @return [TTTLS13::Message::Extensions]
|
46
46
|
# rubocop: disable Metrics/CyclomaticComplexity
|
47
|
+
# rubocop: disable Metrics/PerceivedComplexity
|
47
48
|
def self.deserialize(binary, msg_type)
|
48
49
|
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
49
50
|
|
50
|
-
|
51
|
+
exs = Extensions.new
|
51
52
|
i = 0
|
52
53
|
while i < binary.length
|
53
54
|
raise Error::ErrorAlerts, :decode_error if i + 4 > binary.length
|
@@ -66,32 +67,41 @@ module TTTLS13
|
|
66
67
|
ex = Extension::UnknownExtension.new(extension_type: extension_type,
|
67
68
|
extension_data: ex_bin)
|
68
69
|
end
|
69
|
-
|
70
|
+
|
71
|
+
# There MUST NOT be more than one extension of the same type in a
|
72
|
+
# given extension block.
|
73
|
+
raise Error::ErrorAlerts, :unsupported_extension \
|
74
|
+
if exs.include?(extension_type)
|
75
|
+
|
76
|
+
exs[extension_type] = ex
|
70
77
|
i += ex_len
|
71
78
|
end
|
72
79
|
raise Error::ErrorAlerts, :decode_error unless i == binary.length
|
73
80
|
|
74
|
-
|
81
|
+
exs
|
75
82
|
end
|
76
83
|
# rubocop: enable Metrics/CyclomaticComplexity
|
84
|
+
# rubocop: enable Metrics/PerceivedComplexity
|
77
85
|
|
78
86
|
# @param key [TTTLS13::Message::ExtensionType]
|
87
|
+
# @param default
|
79
88
|
#
|
80
89
|
# @return [TTTLS13::Message::Extension::$Object]
|
81
|
-
def
|
90
|
+
def fetch(key, default = nil)
|
82
91
|
return nil if super_fetch(key, nil).is_a?(Extension::UnknownExtension)
|
83
92
|
|
84
|
-
super_fetch(key,
|
93
|
+
super_fetch(key, default)
|
85
94
|
end
|
86
95
|
|
87
|
-
|
88
|
-
|
96
|
+
def [](key)
|
97
|
+
fetch(key)
|
98
|
+
end
|
99
|
+
|
100
|
+
# @param ex [TTTLS13::Message::Extension::$Object]
|
89
101
|
#
|
90
102
|
# @return [TTTLS13::Message::Extension::$Object]
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
super_fetch(key, default)
|
103
|
+
def <<(ex)
|
104
|
+
store(ex.extension_type, ex)
|
95
105
|
end
|
96
106
|
|
97
107
|
class << self
|
@@ -111,7 +121,6 @@ module TTTLS13
|
|
111
121
|
# @return [TTTLS13::Message::Extension::$Object, nil]
|
112
122
|
# rubocop: disable Metrics/CyclomaticComplexity
|
113
123
|
# rubocop: disable Metrics/MethodLength
|
114
|
-
# rubocop: disable Metrics/PerceivedComplexity
|
115
124
|
def deserialize_extension(binary, extension_type, msg_type)
|
116
125
|
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
117
126
|
|
@@ -119,14 +128,15 @@ module TTTLS13
|
|
119
128
|
when ExtensionType::SERVER_NAME
|
120
129
|
Extension::ServerName.deserialize(binary)
|
121
130
|
when ExtensionType::STATUS_REQUEST
|
122
|
-
if msg_type == HandshakeType::CLIENT_HELLO
|
123
|
-
|
124
|
-
Extension::OCSPStatusRequest.deserialize(binary)
|
125
|
-
elsif msg_type == HandshakeType::CERTIFICATE
|
126
|
-
Extension::OCSPResponse.deserialize(binary)
|
127
|
-
else
|
128
|
-
return nil
|
131
|
+
if msg_type == HandshakeType::CLIENT_HELLO
|
132
|
+
return Extension::OCSPStatusRequest.deserialize(binary)
|
129
133
|
end
|
134
|
+
|
135
|
+
if msg_type == HandshakeType::CERTIFICATE
|
136
|
+
return Extension::OCSPResponse.deserialize(binary)
|
137
|
+
end
|
138
|
+
|
139
|
+
Extension::UnknownExtension.deserialize(binary, extension_type)
|
130
140
|
when ExtensionType::SUPPORTED_GROUPS
|
131
141
|
Extension::SupportedGroups.deserialize(binary)
|
132
142
|
when ExtensionType::SIGNATURE_ALGORITHMS
|
@@ -155,7 +165,6 @@ module TTTLS13
|
|
155
165
|
end
|
156
166
|
# rubocop: enable Metrics/CyclomaticComplexity
|
157
167
|
# rubocop: enable Metrics/MethodLength
|
158
|
-
# rubocop: enable Metrics/PerceivedComplexity
|
159
168
|
end
|
160
169
|
end
|
161
170
|
end
|
data/lib/tttls1.3/server.rb
CHANGED
@@ -52,6 +52,7 @@ module TTTLS13
|
|
52
52
|
signature_algorithms: DEFAULT_SP_SIGNATURE_ALGORITHMS,
|
53
53
|
supported_groups: DEFAULT_SP_NAMED_GROUP_LIST,
|
54
54
|
alpn: nil,
|
55
|
+
process_ocsp_response: nil,
|
55
56
|
compatibility_mode: true,
|
56
57
|
loglevel: Logger::WARN
|
57
58
|
}.freeze
|
@@ -236,10 +237,14 @@ module TTTLS13
|
|
236
237
|
|
237
238
|
ch = transcript[CH]
|
238
239
|
rsl = @send_record_size \
|
239
|
-
|
240
|
+
if ch.extensions.include?(Message::ExtensionType::RECORD_SIZE_LIMIT)
|
240
241
|
ee = transcript[EE] = gen_encrypted_extensions(ch, @alpn, rsl)
|
241
242
|
# TODO: [Send CertificateRequest]
|
242
|
-
|
243
|
+
|
244
|
+
# status_request
|
245
|
+
ocsp_response = fetch_ocsp_response \
|
246
|
+
if ch.extensions.include?(Message::ExtensionType::STATUS_REQUEST)
|
247
|
+
ct = transcript[CT] = gen_certificate(@crt, @chain, ocsp_response)
|
243
248
|
digest = CipherSuite.digest(@cipher_suite)
|
244
249
|
cv = transcript[CV] = gen_certificate_verify(
|
245
250
|
@key,
|
@@ -350,7 +355,7 @@ module TTTLS13
|
|
350
355
|
#
|
351
356
|
# @return [TTTLS13::Message::ServerHello]
|
352
357
|
def send_hello_retry_request(ch1, cipher_suite)
|
353
|
-
exs =
|
358
|
+
exs = Message::Extensions.new
|
354
359
|
# supported_versions
|
355
360
|
exs << Message::Extension::SupportedVersions.new(
|
356
361
|
msg_type: Message::HandshakeType::SERVER_HELLO
|
@@ -372,7 +377,7 @@ module TTTLS13
|
|
372
377
|
random: Message::HRR_RANDOM,
|
373
378
|
legacy_session_id_echo: ch1.legacy_session_id,
|
374
379
|
cipher_suite: cipher_suite,
|
375
|
-
extensions:
|
380
|
+
extensions: exs
|
376
381
|
)
|
377
382
|
send_handshakes(Message::ContentType::HANDSHAKE, [sh],
|
378
383
|
Cryptograph::Passer.new)
|
@@ -404,11 +409,16 @@ module TTTLS13
|
|
404
409
|
|
405
410
|
# @param crt [OpenSSL::X509::Certificate]
|
406
411
|
# @param chain [Array of OpenSSL::X509::Certificate]
|
412
|
+
# @param ocsp_response [OpenSSL::OCSP::Response]
|
407
413
|
#
|
408
414
|
# @return [TTTLS13::Message::Certificate, nil]
|
409
|
-
def gen_certificate(crt, chain = [])
|
410
|
-
|
411
|
-
|
415
|
+
def gen_certificate(crt, chain = [], ocsp_response = nil)
|
416
|
+
exs = Message::Extensions.new
|
417
|
+
# status_request
|
418
|
+
exs << Message::Extension::OCSPResponse.new(ocsp_response) \
|
419
|
+
unless ocsp_response.nil?
|
420
|
+
ces = [Message::CertificateEntry.new(crt, exs)] \
|
421
|
+
+ (chain || []).map { |c| Message::CertificateEntry.new(c) }
|
412
422
|
Message::Certificate.new(certificate_list: ces)
|
413
423
|
end
|
414
424
|
|
@@ -444,7 +454,7 @@ module TTTLS13
|
|
444
454
|
# @return [TTTLS13::Message::Extensions]
|
445
455
|
# @return [OpenSSL::PKey::EC.$Object]
|
446
456
|
def gen_sh_extensions(named_group)
|
447
|
-
exs =
|
457
|
+
exs = Message::Extensions.new
|
448
458
|
# supported_versions: only TLS 1.3
|
449
459
|
exs << Message::Extension::SupportedVersions.new(
|
450
460
|
msg_type: Message::HandshakeType::SERVER_HELLO
|
@@ -455,7 +465,7 @@ module TTTLS13
|
|
455
465
|
= Message::Extension::KeyShare.gen_sh_key_share(named_group)
|
456
466
|
exs << key_share
|
457
467
|
|
458
|
-
[
|
468
|
+
[exs, priv_key]
|
459
469
|
end
|
460
470
|
|
461
471
|
# @param ch [TTTLS13::Message::ClientHello]
|
@@ -464,15 +474,16 @@ module TTTLS13
|
|
464
474
|
#
|
465
475
|
# @return [TTTLS13::Message::Extensions]
|
466
476
|
def gen_ee_extensions(ch, alpn, record_size_limit)
|
467
|
-
exs =
|
477
|
+
exs = Message::Extensions.new
|
468
478
|
|
469
479
|
# server_name
|
470
480
|
exs << Message::Extension::ServerName.new('') \
|
471
481
|
if ch.extensions.include?(Message::ExtensionType::SERVER_NAME)
|
472
482
|
|
473
483
|
# supported_groups
|
474
|
-
exs
|
475
|
-
|
484
|
+
exs << Message::Extension::SupportedGroups.new(
|
485
|
+
@settings[:supported_groups]
|
486
|
+
)
|
476
487
|
|
477
488
|
# alpn
|
478
489
|
exs << Message::Extension::Alpn.new([alpn]) unless alpn.nil?
|
@@ -481,7 +492,7 @@ module TTTLS13
|
|
481
492
|
exs << Message::Extension::RecordSizeLimit.new(record_size_limit) \
|
482
493
|
unless record_size_limit.nil?
|
483
494
|
|
484
|
-
|
495
|
+
exs
|
485
496
|
end
|
486
497
|
|
487
498
|
# @param key [OpenSSL::PKey::PKey]
|
@@ -543,6 +554,11 @@ module TTTLS13
|
|
543
554
|
|
544
555
|
matching_san?(crt, server_name)
|
545
556
|
end
|
557
|
+
|
558
|
+
# @return [OpenSSL::OCSP::Response, nil]
|
559
|
+
def fetch_ocsp_response
|
560
|
+
@settings[:process_ocsp_response]&.call
|
561
|
+
end
|
546
562
|
end
|
547
563
|
# rubocop: enable Metrics/ClassLength
|
548
564
|
end
|
data/lib/tttls1.3/version.rb
CHANGED
data/spec/extensions_spec.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require_relative 'spec_helper'
|
5
|
+
using Refinements
|
5
6
|
|
6
7
|
RSpec.describe Extensions do
|
7
8
|
context 'empty extensions' do
|
@@ -167,4 +168,19 @@ RSpec.describe Extensions do
|
|
167
168
|
expect(extensions).to include ExtensionType::RECORD_SIZE_LIMIT
|
168
169
|
end
|
169
170
|
end
|
171
|
+
|
172
|
+
context 'duplicated extension_type' do
|
173
|
+
let(:server_name) do
|
174
|
+
ServerName.new('example.com')
|
175
|
+
end
|
176
|
+
|
177
|
+
let(:testbinary) do
|
178
|
+
server_name.serialize * 2
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should raise error, if extension_type get duplicated' do
|
182
|
+
expect { Extensions.deserialize(testbinary, HandshakeType::CLIENT_HELLO) }
|
183
|
+
.to raise_error(ErrorAlerts)
|
184
|
+
end
|
185
|
+
end
|
170
186
|
end
|
data/spec/server_hello_spec.rb
CHANGED
@@ -187,7 +187,7 @@ RSpec.describe ServerHello do
|
|
187
187
|
let(:message) do
|
188
188
|
sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
|
189
189
|
extensions = sh.instance_variable_get(:@extensions)
|
190
|
-
extensions
|
190
|
+
extensions.delete(ExtensionType::SUPPORTED_VERSIONS)
|
191
191
|
sh.instance_variable_set(:@extensions, extensions)
|
192
192
|
sh
|
193
193
|
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.
|
4
|
+
version: 0.2.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thekuwayama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-01-
|
11
|
+
date: 2020-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|