tttls1.3 0.2.12 → 0.2.13
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 +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
|