tttls1.3 0.2.15 → 0.2.18
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/ci.yml +6 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +5 -1
- data/.ruby-version +1 -0
- data/Gemfile +3 -1
- data/README.md +6 -2
- data/example/https_client.rb +2 -1
- data/example/https_server.rb +3 -2
- data/lib/tttls1.3/client.rb +116 -42
- data/lib/tttls1.3/connection.rb +24 -19
- data/lib/tttls1.3/message/client_hello.rb +1 -0
- data/lib/tttls1.3/message/compressed_certificate.rb +82 -0
- data/lib/tttls1.3/message/end_of_early_data.rb +8 -1
- data/lib/tttls1.3/message/extension/alpn.rb +5 -2
- data/lib/tttls1.3/message/extension/compress_certificate.rb +58 -0
- data/lib/tttls1.3/message/extension/signature_algorithms.rb +2 -2
- data/lib/tttls1.3/message/extension/supported_groups.rb +2 -2
- data/lib/tttls1.3/message/extensions.rb +4 -0
- data/lib/tttls1.3/message/record.rb +28 -16
- data/lib/tttls1.3/message.rb +22 -20
- data/lib/tttls1.3/server.rb +89 -27
- data/lib/tttls1.3/sslkeylogfile.rb +87 -0
- data/lib/tttls1.3/transcript.rb +3 -7
- data/lib/tttls1.3/version.rb +1 -1
- data/lib/tttls1.3.rb +1 -0
- data/spec/client_spec.rb +28 -19
- data/spec/compress_certificate_spec.rb +54 -0
- data/spec/connection_spec.rb +22 -15
- data/spec/end_of_early_data_spec.rb +28 -0
- data/spec/key_schedule_spec.rb +48 -25
- data/spec/record_spec.rb +2 -2
- data/spec/server_spec.rb +23 -11
- data/spec/spec_helper.rb +4 -0
- data/spec/transcript_spec.rb +34 -20
- data/tttls1.3.gemspec +1 -1
- metadata +12 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a07aded25aecad8bd61ff9fd49a70df15c8abf356d4747891486dd81386b68d
|
4
|
+
data.tar.gz: 4637b3288dab22caae951cc43c283057fd3ed215fc5fa86e318becc3369ac7b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 621a8f82c99e21e964cfb6defe14e2f8864f1c42cc94c9af725de2ff73929226d99a694c893ada3fc44c5224be70ec87bfcb291eceab271b33e4759c6c900cd8
|
7
|
+
data.tar.gz: 9088db06f998013577eb647d064e97035047a2cef7799010bc91f18384787bdf158357fd33c296b92ec1bc07a2ad1b307c98d0217735dfef5c6acf565f3c9433
|
data/.github/workflows/ci.yml
CHANGED
@@ -3,7 +3,7 @@ name: CI
|
|
3
3
|
on:
|
4
4
|
push:
|
5
5
|
branches:
|
6
|
-
-
|
6
|
+
- main
|
7
7
|
pull_request:
|
8
8
|
branches:
|
9
9
|
- '*'
|
@@ -13,12 +13,14 @@ jobs:
|
|
13
13
|
runs-on: ubuntu-latest
|
14
14
|
strategy:
|
15
15
|
matrix:
|
16
|
-
ruby-version: ['2.
|
16
|
+
ruby-version: ['2.7.x', '3.0.x', '3.1.x']
|
17
17
|
steps:
|
18
|
+
- uses: actions/checkout@v3
|
18
19
|
- uses: docker://thekuwayama/openssl:latest
|
19
20
|
- name: Set up Ruby
|
20
|
-
uses:
|
21
|
-
|
21
|
+
uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
ruby-version: ${{ matrix.ruby }}
|
22
24
|
- name: Install dependencies
|
23
25
|
run: |
|
24
26
|
gem --version
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
AllCops:
|
2
|
-
TargetRubyVersion: 2.
|
2
|
+
TargetRubyVersion: 2.7
|
3
3
|
|
4
4
|
Style/ConditionalAssignment:
|
5
5
|
Enabled: false
|
@@ -28,3 +28,7 @@ Metrics/BlockLength:
|
|
28
28
|
Layout/LineLength:
|
29
29
|
Exclude:
|
30
30
|
- 'tttls1.3.gemspec'
|
31
|
+
|
32
|
+
# https://github.com/rubocop/rubocop/issues/10258
|
33
|
+
Layout/BlockAlignment:
|
34
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.1.2
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/tttls1.3)
|
4
4
|
[](https://github.com/thekuwayama/tttls1.3/actions?workflow=CI)
|
5
|
-
[](https://codeclimate.com/github/thekuwayama/tttls1.3/maintainability)
|
6
6
|
|
7
7
|
tttls1.3 is Ruby implementation of [TLS 1.3](https://tools.ietf.org/html/rfc8446) protocol.
|
8
8
|
|
@@ -74,7 +74,7 @@ server.write(YOUR_MESSAGE)
|
|
74
74
|
server.close
|
75
75
|
```
|
76
76
|
|
77
|
-
[Here](https://github.com/thekuwayama/tttls1.3/tree/
|
77
|
+
[Here](https://github.com/thekuwayama/tttls1.3/tree/main/example) are some examples of HTTPS.
|
78
78
|
|
79
79
|
|
80
80
|
## Settings
|
@@ -102,7 +102,9 @@ tttls1.3 client is configurable using keyword arguments.
|
|
102
102
|
| `:record_size_limit` | Integer | nil | The record\_size\_limit offerd in ClientHello extensions. If not needed to be present, set nil. |
|
103
103
|
| `:check_certificate_status` | Boolean | false | If needed to check certificate status, set true. |
|
104
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. |
|
105
|
+
| `:compress_certificate_algorithms` | Array of TTTLS13::Message::Extension::CertificateCompressionAlgorithm constant | `ZLIB` | The compression algorithms are supported for compressing the Certificate message. |
|
105
106
|
| `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
|
107
|
+
| `:sslkeylogfile` | String | nil | If needed to log SSLKEYLOGFILE, set the file path. |
|
106
108
|
| `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
|
107
109
|
|
108
110
|
|
@@ -120,7 +122,9 @@ tttls1.3 server is configurable using keyword arguments.
|
|
120
122
|
| `:supported_groups` | Array of TTTLS13::NamedGroup constant | `SECP256R1`, `SECP384R1`, `SECP521R1` | List of supported named groups. |
|
121
123
|
| `:alpn` | Array of String | nil | List of supported application protocols. If not needed to check this extension, set nil. |
|
122
124
|
| `:process_ocsp_response` | Proc | nil | Proc that gets OpenSSL::OCSP::Response. If not needed to staple OCSP::Response, set nil. |
|
125
|
+
| `:compress_certificate_algorithms` | Array of TTTLS13::Message::Extension::CertificateCompressionAlgorithm constant | `ZLIB` | The compression algorithms are supported for compressing the Certificate message. |
|
123
126
|
| `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
|
127
|
+
| `:sslkeylogfile` | String | nil | If needed to log SSLKEYLOGFILE, set the file path. |
|
124
128
|
| `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
|
125
129
|
|
126
130
|
|
data/example/https_client.rb
CHANGED
@@ -10,7 +10,8 @@ req = simple_http_request(hostname)
|
|
10
10
|
socket = TCPSocket.new(hostname, port)
|
11
11
|
settings = {
|
12
12
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
13
|
-
alpn: ['http/1.1']
|
13
|
+
alpn: ['http/1.1'],
|
14
|
+
sslkeylogfile: '/tmp/sslkeylogfile.log'
|
14
15
|
}
|
15
16
|
client = TTTLS13::Client.new(socket, hostname, **settings)
|
16
17
|
client.connect
|
data/example/https_server.rb
CHANGED
@@ -12,7 +12,8 @@ settings = {
|
|
12
12
|
crt_file: __dir__ + '/../tmp/server.crt',
|
13
13
|
chain_files: [__dir__ + '/../tmp/intermediate.crt'],
|
14
14
|
key_file: __dir__ + '/../tmp/server.key',
|
15
|
-
alpn: ['http/1.1']
|
15
|
+
alpn: ['http/1.1'],
|
16
|
+
sslkeylogfile: '/tmp/sslkeylogfile.log'
|
16
17
|
}
|
17
18
|
|
18
19
|
q = Queue.new
|
@@ -49,7 +50,7 @@ Etc.nprocessors.times do
|
|
49
50
|
rescue Timeout::Error
|
50
51
|
logger.warn 'Timeout'
|
51
52
|
ensure
|
52
|
-
s
|
53
|
+
s&.close
|
53
54
|
end
|
54
55
|
end
|
55
56
|
end
|
data/lib/tttls1.3/client.rb
CHANGED
@@ -43,6 +43,11 @@ module TTTLS13
|
|
43
43
|
].freeze
|
44
44
|
private_constant :DEFAULT_CH_NAMED_GROUP_LIST
|
45
45
|
|
46
|
+
DEFALUT_CH_COMPRESS_CERTIFICATE_ALGORITHMS = [
|
47
|
+
Message::Extension::CertificateCompressionAlgorithm::ZLIB
|
48
|
+
].freeze
|
49
|
+
private_constant :DEFALUT_CH_COMPRESS_CERTIFICATE_ALGORITHMS
|
50
|
+
|
46
51
|
DEFAULT_CLIENT_SETTINGS = {
|
47
52
|
ca_file: nil,
|
48
53
|
cipher_suites: DEFAULT_CH_CIPHER_SUITES,
|
@@ -61,7 +66,9 @@ module TTTLS13
|
|
61
66
|
record_size_limit: nil,
|
62
67
|
check_certificate_status: false,
|
63
68
|
process_certificate_status: nil,
|
69
|
+
compress_certificate_algorithms: DEFALUT_CH_COMPRESS_CERTIFICATE_ALGORITHMS,
|
64
70
|
compatibility_mode: true,
|
71
|
+
sslkeylogfile: nil,
|
65
72
|
loglevel: Logger::WARN
|
66
73
|
}.freeze
|
67
74
|
private_constant :DEFAULT_CLIENT_SETTINGS
|
@@ -145,6 +152,15 @@ module TTTLS13
|
|
145
152
|
hs_wcipher = nil # TTTLS13::Cryptograph::$Object
|
146
153
|
hs_rcipher = nil # TTTLS13::Cryptograph::$Object
|
147
154
|
e_wcipher = nil # TTTLS13::Cryptograph::$Object
|
155
|
+
sslkeylogfile = nil # TTTLS13::SslKeyLogFile::Writer
|
156
|
+
unless @settings[:sslkeylogfile].nil?
|
157
|
+
begin
|
158
|
+
sslkeylogfile = SslKeyLogFile::Writer.new(@settings[:sslkeylogfile])
|
159
|
+
rescue SystemCallError => e
|
160
|
+
msg = "\"#{@settings[:sslkeylogfile]}\" file can NOT open: #{e}"
|
161
|
+
logger.warn(msg)
|
162
|
+
end
|
163
|
+
end
|
148
164
|
|
149
165
|
@state = ClientState::START
|
150
166
|
loop do
|
@@ -154,8 +170,8 @@ module TTTLS13
|
|
154
170
|
|
155
171
|
extensions, priv_keys = gen_ch_extensions
|
156
172
|
binder_key = (use_psk? ? key_schedule.binder_key_res : nil)
|
157
|
-
|
158
|
-
|
173
|
+
ch = send_client_hello(extensions, binder_key)
|
174
|
+
transcript[CH] = [ch, ch.serialize]
|
159
175
|
send_ccs if @settings[:compatibility_mode]
|
160
176
|
if use_early_data?
|
161
177
|
e_wcipher = gen_cipher(
|
@@ -163,6 +179,10 @@ module TTTLS13
|
|
163
179
|
key_schedule.early_data_write_key,
|
164
180
|
key_schedule.early_data_write_iv
|
165
181
|
)
|
182
|
+
sslkeylogfile&.write_client_early_traffic_secret(
|
183
|
+
transcript[CH].first.random,
|
184
|
+
key_schedule.client_early_traffic_secret
|
185
|
+
)
|
166
186
|
send_early_data(e_wcipher)
|
167
187
|
end
|
168
188
|
|
@@ -170,7 +190,7 @@ module TTTLS13
|
|
170
190
|
when ClientState::WAIT_SH
|
171
191
|
logger.debug('ClientState::WAIT_SH')
|
172
192
|
|
173
|
-
sh = transcript[SH] = recv_server_hello
|
193
|
+
sh, = transcript[SH] = recv_server_hello
|
174
194
|
|
175
195
|
# downgrade protection
|
176
196
|
if !sh.negotiated_tls_1_3? && sh.downgraded?
|
@@ -187,7 +207,7 @@ module TTTLS13
|
|
187
207
|
unless sh.legacy_compression_method == "\x00"
|
188
208
|
|
189
209
|
# validate sh using ch
|
190
|
-
ch = transcript[CH]
|
210
|
+
ch, = transcript[CH]
|
191
211
|
terminate(:illegal_parameter) \
|
192
212
|
unless sh.legacy_version == ch.legacy_version
|
193
213
|
terminate(:illegal_parameter) \
|
@@ -199,7 +219,7 @@ module TTTLS13
|
|
199
219
|
|
200
220
|
# validate sh using hrr
|
201
221
|
if transcript.include?(HRR)
|
202
|
-
hrr = transcript[HRR]
|
222
|
+
hrr, = transcript[HRR]
|
203
223
|
terminate(:illegal_parameter) \
|
204
224
|
unless sh.cipher_suite == hrr.cipher_suite
|
205
225
|
|
@@ -212,8 +232,9 @@ module TTTLS13
|
|
212
232
|
# handling HRR
|
213
233
|
if sh.hrr?
|
214
234
|
terminate(:unexpected_message) if transcript.include?(HRR)
|
215
|
-
|
216
|
-
|
235
|
+
|
236
|
+
ch1, = transcript[CH1] = transcript.delete(CH)
|
237
|
+
hrr, = transcript[HRR] = transcript.delete(SH)
|
217
238
|
|
218
239
|
# validate cookie
|
219
240
|
diff_sets = sh.extensions.keys - ch1.extensions.keys
|
@@ -235,8 +256,9 @@ module TTTLS13
|
|
235
256
|
extensions, pk = gen_newch_extensions(ch1, hrr)
|
236
257
|
priv_keys = pk.merge(priv_keys)
|
237
258
|
binder_key = (use_psk? ? key_schedule.binder_key_res : nil)
|
238
|
-
|
239
|
-
|
259
|
+
ch = send_new_client_hello(ch1, hrr, extensions, binder_key)
|
260
|
+
transcript[CH] = [ch, ch.serialize]
|
261
|
+
|
240
262
|
@state = ClientState::WAIT_SH
|
241
263
|
next
|
242
264
|
end
|
@@ -268,46 +290,63 @@ module TTTLS13
|
|
268
290
|
key_schedule.client_handshake_write_key,
|
269
291
|
key_schedule.client_handshake_write_iv
|
270
292
|
)
|
293
|
+
sslkeylogfile&.write_client_handshake_traffic_secret(
|
294
|
+
transcript[CH].first.random,
|
295
|
+
key_schedule.client_handshake_traffic_secret
|
296
|
+
)
|
271
297
|
hs_rcipher = gen_cipher(
|
272
298
|
@cipher_suite,
|
273
299
|
key_schedule.server_handshake_write_key,
|
274
300
|
key_schedule.server_handshake_write_iv
|
275
301
|
)
|
302
|
+
sslkeylogfile&.write_server_handshake_traffic_secret(
|
303
|
+
transcript[CH].first.random,
|
304
|
+
key_schedule.server_handshake_traffic_secret
|
305
|
+
)
|
276
306
|
@state = ClientState::WAIT_EE
|
277
307
|
when ClientState::WAIT_EE
|
278
308
|
logger.debug('ClientState::WAIT_EE')
|
279
309
|
|
280
|
-
ee = transcript[EE] = recv_encrypted_extensions(hs_rcipher)
|
310
|
+
ee, = transcript[EE] = recv_encrypted_extensions(hs_rcipher)
|
281
311
|
terminate(:illegal_parameter) unless ee.appearable_extensions?
|
282
312
|
|
283
|
-
ch = transcript[CH]
|
313
|
+
ch, = transcript[CH]
|
284
314
|
terminate(:unsupported_extension) \
|
285
315
|
unless (ee.extensions.keys - ch.extensions.keys).empty?
|
286
316
|
|
287
317
|
rsl = ee.extensions[Message::ExtensionType::RECORD_SIZE_LIMIT]
|
288
318
|
@recv_record_size = rsl.record_size_limit unless rsl.nil?
|
289
|
-
|
290
319
|
@succeed_early_data = true \
|
291
320
|
if ee.extensions.include?(Message::ExtensionType::EARLY_DATA)
|
292
|
-
|
293
321
|
@alpn = ee.extensions[
|
294
322
|
Message::ExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION
|
295
323
|
]&.protocol_name_list&.first
|
296
|
-
|
297
324
|
@state = ClientState::WAIT_CERT_CR
|
298
325
|
@state = ClientState::WAIT_FINISHED unless psk.nil?
|
299
326
|
when ClientState::WAIT_CERT_CR
|
300
327
|
logger.debug('ClientState::WAIT_CERT_CR')
|
301
328
|
|
302
|
-
message = recv_message(
|
303
|
-
|
304
|
-
|
305
|
-
|
329
|
+
message, orig_msg = recv_message(
|
330
|
+
receivable_ccs: true,
|
331
|
+
cipher: hs_rcipher
|
332
|
+
)
|
333
|
+
case message.msg_type
|
334
|
+
when Message::HandshakeType::CERTIFICATE,
|
335
|
+
Message::HandshakeType::COMPRESSED_CERTIFICATE
|
336
|
+
ct, = transcript[CT] = [message, orig_msg]
|
337
|
+
terminate(:bad_certificate) \
|
338
|
+
if ct.is_a?(Message::CompressedCertificate) &&
|
339
|
+
!@settings[:compress_certificate_algorithms]
|
340
|
+
.include?(ct.algorithm)
|
341
|
+
|
342
|
+
ct = ct.certificate_message \
|
343
|
+
if ct.is_a?(Message::CompressedCertificate)
|
344
|
+
alert = check_invalid_certificate(ct, transcript[CH].first)
|
306
345
|
terminate(alert) unless alert.nil?
|
307
346
|
|
308
347
|
@state = ClientState::WAIT_CV
|
309
|
-
|
310
|
-
transcript[CR] = message
|
348
|
+
when Message::HandshakeType::CERTIFICATE_REQUEST
|
349
|
+
transcript[CR] = [message, orig_msg]
|
311
350
|
# TODO: client authentication
|
312
351
|
@state = ClientState::WAIT_CERT
|
313
352
|
else
|
@@ -316,56 +355,74 @@ module TTTLS13
|
|
316
355
|
when ClientState::WAIT_CERT
|
317
356
|
logger.debug('ClientState::WAIT_CERT')
|
318
357
|
|
319
|
-
ct = transcript[CT] = recv_certificate(hs_rcipher)
|
320
|
-
|
358
|
+
ct, = transcript[CT] = recv_certificate(hs_rcipher)
|
359
|
+
if ct.is_a?(Message::CompressedCertificate) &&
|
360
|
+
!@settings[:compress_certificate_algorithms].include?(ct.algorithm)
|
361
|
+
terminate(:bad_certificate)
|
362
|
+
elsif ct.is_a?(Message::CompressedCertificate)
|
363
|
+
ct = ct.certificate_message
|
364
|
+
end
|
365
|
+
|
366
|
+
alert = check_invalid_certificate(ct, transcript[CH].first)
|
321
367
|
terminate(alert) unless alert.nil?
|
322
368
|
|
323
369
|
@state = ClientState::WAIT_CV
|
324
370
|
when ClientState::WAIT_CV
|
325
371
|
logger.debug('ClientState::WAIT_CV')
|
326
372
|
|
327
|
-
cv = transcript[CV] = recv_certificate_verify(hs_rcipher)
|
373
|
+
cv, = transcript[CV] = recv_certificate_verify(hs_rcipher)
|
328
374
|
digest = CipherSuite.digest(@cipher_suite)
|
329
375
|
hash = transcript.hash(digest, CT)
|
376
|
+
ct, = transcript[CT]
|
377
|
+
ct = ct.certificate_message \
|
378
|
+
if ct.is_a?(Message::CompressedCertificate)
|
330
379
|
terminate(:decrypt_error) \
|
331
|
-
unless verified_certificate_verify?(
|
380
|
+
unless verified_certificate_verify?(ct, cv, hash)
|
332
381
|
|
333
382
|
@signature_scheme = cv.signature_scheme
|
334
|
-
|
335
383
|
@state = ClientState::WAIT_FINISHED
|
336
384
|
when ClientState::WAIT_FINISHED
|
337
385
|
logger.debug('ClientState::WAIT_FINISHED')
|
338
386
|
|
339
|
-
sf = transcript[SF] = recv_finished(hs_rcipher)
|
387
|
+
sf, = transcript[SF] = recv_finished(hs_rcipher)
|
340
388
|
digest = CipherSuite.digest(@cipher_suite)
|
341
|
-
|
389
|
+
terminate(:decrypt_error) unless verified_finished?(
|
342
390
|
finished: sf,
|
343
391
|
digest: digest,
|
344
392
|
finished_key: key_schedule.server_finished_key,
|
345
393
|
hash: transcript.hash(digest, CV)
|
346
394
|
)
|
347
|
-
terminate(:decrypt_error) unless verified
|
348
|
-
|
349
|
-
transcript[EOED] = send_eoed(e_wcipher) \
|
350
|
-
if use_early_data? && succeed_early_data?
|
351
395
|
|
396
|
+
if use_early_data? && succeed_early_data?
|
397
|
+
eoed = send_eoed(e_wcipher)
|
398
|
+
transcript[EOED] = [eoed, eoed.serialize]
|
399
|
+
end
|
352
400
|
# TODO: Send Certificate [+ CertificateVerify]
|
353
401
|
signature = sign_finished(
|
354
402
|
digest: digest,
|
355
403
|
finished_key: key_schedule.client_finished_key,
|
356
404
|
hash: transcript.hash(digest, EOED)
|
357
405
|
)
|
358
|
-
|
406
|
+
cf = send_finished(signature, hs_wcipher)
|
407
|
+
transcript[CF] = [cf, cf.serialize]
|
359
408
|
@alert_wcipher = @ap_wcipher = gen_cipher(
|
360
409
|
@cipher_suite,
|
361
410
|
key_schedule.client_application_write_key,
|
362
411
|
key_schedule.client_application_write_iv
|
363
412
|
)
|
413
|
+
sslkeylogfile&.write_client_traffic_secret_0(
|
414
|
+
transcript[CH].first.random,
|
415
|
+
key_schedule.client_application_traffic_secret
|
416
|
+
)
|
364
417
|
@ap_rcipher = gen_cipher(
|
365
418
|
@cipher_suite,
|
366
419
|
key_schedule.server_application_write_key,
|
367
420
|
key_schedule.server_application_write_iv
|
368
421
|
)
|
422
|
+
sslkeylogfile&.write_server_traffic_secret_0(
|
423
|
+
transcript[CH].first.random,
|
424
|
+
key_schedule.server_application_traffic_secret
|
425
|
+
)
|
369
426
|
@exporter_master_secret = key_schedule.exporter_master_secret
|
370
427
|
@resumption_master_secret = key_schedule.resumption_master_secret
|
371
428
|
@state = ClientState::CONNECTED
|
@@ -375,6 +432,7 @@ module TTTLS13
|
|
375
432
|
break
|
376
433
|
end
|
377
434
|
end
|
435
|
+
sslkeylogfile&.close
|
378
436
|
end
|
379
437
|
# rubocop: enable Metrics/AbcSize
|
380
438
|
# rubocop: enable Metrics/BlockLength
|
@@ -578,6 +636,14 @@ module TTTLS13
|
|
578
636
|
exs << Message::Extension::OCSPStatusRequest.new \
|
579
637
|
if @settings[:check_certificate_status]
|
580
638
|
|
639
|
+
# compress_certificate
|
640
|
+
if !@settings[:compress_certificate_algorithms].nil? &&
|
641
|
+
!@settings[:compress_certificate_algorithms].empty?
|
642
|
+
exs << Message::Extension::CompressCertificate.new(
|
643
|
+
@settings[:compress_certificate_algorithms]
|
644
|
+
)
|
645
|
+
end
|
646
|
+
|
581
647
|
[exs, priv_keys]
|
582
648
|
end
|
583
649
|
# rubocop: enable Metrics/AbcSize
|
@@ -735,11 +801,15 @@ module TTTLS13
|
|
735
801
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
736
802
|
#
|
737
803
|
# @return [TTTLS13::Message::ServerHello]
|
804
|
+
# @return [String]
|
738
805
|
def recv_server_hello
|
739
|
-
sh = recv_message(
|
806
|
+
sh, orig_msg = recv_message(
|
807
|
+
receivable_ccs: true,
|
808
|
+
cipher: Cryptograph::Passer.new
|
809
|
+
)
|
740
810
|
terminate(:unexpected_message) unless sh.is_a?(Message::ServerHello)
|
741
811
|
|
742
|
-
sh
|
812
|
+
[sh, orig_msg]
|
743
813
|
end
|
744
814
|
|
745
815
|
# @param cipher [TTTLS13::Cryptograph::Aead]
|
@@ -747,12 +817,13 @@ module TTTLS13
|
|
747
817
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
748
818
|
#
|
749
819
|
# @return [TTTLS13::Message::EncryptedExtensions]
|
820
|
+
# @return [String]
|
750
821
|
def recv_encrypted_extensions(cipher)
|
751
|
-
ee = recv_message(receivable_ccs: true, cipher: cipher)
|
822
|
+
ee, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
|
752
823
|
terminate(:unexpected_message) \
|
753
824
|
unless ee.is_a?(Message::EncryptedExtensions)
|
754
825
|
|
755
|
-
ee
|
826
|
+
[ee, orig_msg]
|
756
827
|
end
|
757
828
|
|
758
829
|
# @param cipher [TTTLS13::Cryptograph::Aead]
|
@@ -760,11 +831,12 @@ module TTTLS13
|
|
760
831
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
761
832
|
#
|
762
833
|
# @return [TTTLS13::Message::Certificate]
|
834
|
+
# @return [String]
|
763
835
|
def recv_certificate(cipher)
|
764
|
-
ct = recv_message(receivable_ccs: true, cipher: cipher)
|
836
|
+
ct, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
|
765
837
|
terminate(:unexpected_message) unless ct.is_a?(Message::Certificate)
|
766
838
|
|
767
|
-
ct
|
839
|
+
[ct, orig_msg]
|
768
840
|
end
|
769
841
|
|
770
842
|
# @param cipher [TTTLS13::Cryptograph::Aead]
|
@@ -772,11 +844,12 @@ module TTTLS13
|
|
772
844
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
773
845
|
#
|
774
846
|
# @return [TTTLS13::Message::CertificateVerify]
|
847
|
+
# @return [String]
|
775
848
|
def recv_certificate_verify(cipher)
|
776
|
-
cv = recv_message(receivable_ccs: true, cipher: cipher)
|
849
|
+
cv, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
|
777
850
|
terminate(:unexpected_message) unless cv.is_a?(Message::CertificateVerify)
|
778
851
|
|
779
|
-
cv
|
852
|
+
[cv, orig_msg]
|
780
853
|
end
|
781
854
|
|
782
855
|
# @param cipher [TTTLS13::Cryptograph::Aead]
|
@@ -784,11 +857,12 @@ module TTTLS13
|
|
784
857
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
785
858
|
#
|
786
859
|
# @return [TTTLS13::Message::Finished]
|
860
|
+
# @return [String]
|
787
861
|
def recv_finished(cipher)
|
788
|
-
sf = recv_message(receivable_ccs: true, cipher: cipher)
|
862
|
+
sf, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
|
789
863
|
terminate(:unexpected_message) unless sf.is_a?(Message::Finished)
|
790
864
|
|
791
|
-
sf
|
865
|
+
[sf, orig_msg]
|
792
866
|
end
|
793
867
|
|
794
868
|
# @param cipher [TTTLS13::Cryptograph::Aead]
|
data/lib/tttls1.3/connection.rb
CHANGED
@@ -16,7 +16,7 @@ module TTTLS13
|
|
16
16
|
@ap_wcipher = Cryptograph::Passer.new
|
17
17
|
@ap_rcipher = Cryptograph::Passer.new
|
18
18
|
@alert_wcipher = Cryptograph::Passer.new
|
19
|
-
@message_queue = [] # Array of TTTLS13::Message::$Object
|
19
|
+
@message_queue = [] # Array of [TTTLS13::Message::$Object, String]
|
20
20
|
@binary_buffer = '' # deposit Record.surplus_binary
|
21
21
|
@cipher_suite = nil # TTTLS13::CipherSuite
|
22
22
|
@named_group = nil # TTTLS13::NamedGroup
|
@@ -42,7 +42,7 @@ module TTTLS13
|
|
42
42
|
|
43
43
|
message = nil
|
44
44
|
loop do
|
45
|
-
message = recv_message(receivable_ccs: false, cipher: @ap_rcipher)
|
45
|
+
message, = recv_message(receivable_ccs: false, cipher: @ap_rcipher)
|
46
46
|
# At any time after the server has received the client Finished
|
47
47
|
# message, it MAY send a NewSessionTicket message.
|
48
48
|
break unless message.is_a?(Message::NewSessionTicket)
|
@@ -220,13 +220,15 @@ module TTTLS13
|
|
220
220
|
# @raise [TTTLS13::Error::ErrorAlerts
|
221
221
|
#
|
222
222
|
# @return [TTTLS13::Message::$Object]
|
223
|
+
# @return [String]
|
223
224
|
# rubocop: disable Metrics/CyclomaticComplexity
|
224
225
|
def recv_message(receivable_ccs:, cipher:)
|
225
226
|
return @message_queue.shift unless @message_queue.empty?
|
226
227
|
|
227
228
|
messages = nil
|
229
|
+
orig_msgs = []
|
228
230
|
loop do
|
229
|
-
record = recv_record(cipher)
|
231
|
+
record, orig_msgs = recv_record(cipher)
|
230
232
|
case record.type
|
231
233
|
when Message::ContentType::HANDSHAKE,
|
232
234
|
Message::ContentType::APPLICATION_DATA
|
@@ -243,20 +245,22 @@ module TTTLS13
|
|
243
245
|
end
|
244
246
|
end
|
245
247
|
|
246
|
-
@message_queue += messages[1..]
|
248
|
+
@message_queue += messages[1..].zip(orig_msgs[1..])
|
247
249
|
message = messages.first
|
250
|
+
orig_msg = orig_msgs.first
|
248
251
|
if message.is_a?(Message::Alert)
|
249
252
|
handle_received_alert(message)
|
250
253
|
return nil
|
251
254
|
end
|
252
255
|
|
253
|
-
message
|
256
|
+
[message, orig_msg]
|
254
257
|
end
|
255
258
|
# rubocop: enable Metrics/CyclomaticComplexity
|
256
259
|
|
257
260
|
# @param cipher [TTTLS13::Cryptograph::Aead, Passer]
|
258
261
|
#
|
259
262
|
# @return [TTTLS13::Message::Record]
|
263
|
+
# @return [Array of String]
|
260
264
|
def recv_record(cipher)
|
261
265
|
binary = @socket.read(5)
|
262
266
|
record_len = Convert.bin2i(binary.slice(3, 2))
|
@@ -264,9 +268,13 @@ module TTTLS13
|
|
264
268
|
|
265
269
|
begin
|
266
270
|
buffer = @binary_buffer
|
267
|
-
record = Message::Record.deserialize(
|
268
|
-
|
269
|
-
|
271
|
+
record, orig_msgs, surplus_binary = Message::Record.deserialize(
|
272
|
+
binary,
|
273
|
+
cipher,
|
274
|
+
buffer,
|
275
|
+
@recv_record_size
|
276
|
+
)
|
277
|
+
@binary_buffer = surplus_binary
|
270
278
|
rescue Error::ErrorAlerts => e
|
271
279
|
terminate(e.message.to_sym)
|
272
280
|
end
|
@@ -278,7 +286,7 @@ module TTTLS13
|
|
278
286
|
end
|
279
287
|
|
280
288
|
logger.debug("receive \n" + record.pretty_inspect)
|
281
|
-
record
|
289
|
+
[record, orig_msgs]
|
282
290
|
end
|
283
291
|
|
284
292
|
# @param ch1 [TTTLS13::Message::ClientHello]
|
@@ -292,11 +300,9 @@ module TTTLS13
|
|
292
300
|
# TODO: ext binder
|
293
301
|
hash_len = OpenSSL::Digest.new(digest).digest_length
|
294
302
|
tt = Transcript.new
|
295
|
-
tt.
|
296
|
-
|
297
|
-
|
298
|
-
CH => ch
|
299
|
-
)
|
303
|
+
tt[CH1] = [ch1, ch1.serialize] unless ch1.nil?
|
304
|
+
tt[HRR] = [hrr, hrr.serialize] unless hrr.nil?
|
305
|
+
tt[CH] = [ch, ch.serialize]
|
300
306
|
# transcript-hash (CH1 + HRR +) truncated-CH
|
301
307
|
hash = tt.truncate_hash(digest, CH, hash_len + 3)
|
302
308
|
OpenSSL::HMAC.digest(digest, binder_key, hash)
|
@@ -500,11 +506,10 @@ module TTTLS13
|
|
500
506
|
return false if san.nil?
|
501
507
|
|
502
508
|
ostr = OpenSSL::ASN1.decode(san.to_der).value.last
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
matching
|
509
|
+
OpenSSL::ASN1.decode(ostr.value)
|
510
|
+
.map(&:value)
|
511
|
+
.map { |s| s.gsub('.', '\.').gsub('*', '.*') }
|
512
|
+
.any? { |s| name.match(/#{s}/) }
|
508
513
|
end
|
509
514
|
|
510
515
|
# @param signature_algorithms [Array of SignatureAlgorithms]
|
@@ -18,6 +18,7 @@ module TTTLS13
|
|
18
18
|
ExtensionType::CLIENT_CERTIFICATE_TYPE,
|
19
19
|
ExtensionType::SERVER_CERTIFICATE_TYPE,
|
20
20
|
ExtensionType::PADDING,
|
21
|
+
ExtensionType::COMPRESS_CERTIFICATE,
|
21
22
|
ExtensionType::RECORD_SIZE_LIMIT,
|
22
23
|
ExtensionType::PWD_PROTECT,
|
23
24
|
ExtensionType::PWD_CLEAR,
|