tttls1.3 0.2.15 → 0.2.18
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/tttls1.3.svg)](https://badge.fury.io/rb/tttls1.3)
|
4
4
|
[![Actions Status](https://github.com/thekuwayama/tttls1.3/workflows/CI/badge.svg)](https://github.com/thekuwayama/tttls1.3/actions?workflow=CI)
|
5
|
-
[![Maintainability](https://api.codeclimate.com/v1/badges/
|
5
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/b5ae1b3a43828142d2fa/maintainability)](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,
|