tttls1.3 0.2.14 → 0.2.17
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 +2 -2
- data/.rubocop.yml +5 -1
- data/Gemfile +2 -3
- data/README.md +3 -1
- data/lib/tttls1.3/client.rb +85 -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 +15 -5
- data/lib/tttls1.3/message/extension/signature_algorithms_cert.rb +5 -4
- 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 +61 -26
- data/lib/tttls1.3/transcript.rb +3 -7
- data/lib/tttls1.3/version.rb +1 -1
- 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/signature_algorithms_cert_spec.rb +4 -0
- data/spec/signature_algorithms_spec.rb +4 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/transcript_spec.rb +34 -20
- data/tttls1.3.gemspec +1 -2
- metadata +10 -4
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module TTTLS13
|
5
|
+
using Refinements
|
6
|
+
module Message
|
7
|
+
module Extension
|
8
|
+
module CertificateCompressionAlgorithm
|
9
|
+
ZLIB = "\x00\x01"
|
10
|
+
# BROTLI = "\x00\x02" # UNSUPPORTED
|
11
|
+
# ZSTD = "\x00\x03" # UNSUPPORTED
|
12
|
+
end
|
13
|
+
|
14
|
+
# https://tools.ietf.org/html/rfc8879
|
15
|
+
class CompressCertificate
|
16
|
+
attr_reader :extension_type
|
17
|
+
attr_reader :algorithms
|
18
|
+
|
19
|
+
# @param algorithms [Array of CertificateCompressionAlgorithm]
|
20
|
+
#
|
21
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# CompressCertificate([CertificateCompressionAlgorithm::ZLIB])
|
25
|
+
def initialize(algorithms)
|
26
|
+
@extension_type = ExtensionType::COMPRESS_CERTIFICATE
|
27
|
+
@algorithms = algorithms || []
|
28
|
+
raise Error::ErrorAlerts, :internal_error \
|
29
|
+
if @algorithms.join.length < 2 ||
|
30
|
+
@algorithms.join.length > 2**8 - 2
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [String]
|
34
|
+
def serialize
|
35
|
+
binary = @algorithms.join.prefix_uint8_length
|
36
|
+
|
37
|
+
@extension_type + binary.prefix_uint16_length
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param binary [String]
|
41
|
+
#
|
42
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
43
|
+
#
|
44
|
+
# @return [TTTLS13::Message::Extension::CompressCertificate, nil]
|
45
|
+
def self.deserialize(binary)
|
46
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
47
|
+
|
48
|
+
return nil if binary.length < 3
|
49
|
+
|
50
|
+
al_len = Convert.bin2i(binary.slice(0, 1))
|
51
|
+
return nil if binary.length != al_len + 1
|
52
|
+
|
53
|
+
CompressCertificate.new(binary.slice(1, al_len + 1).scan(/.{2}/m))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -35,17 +35,17 @@ module TTTLS13
|
|
35
35
|
|
36
36
|
# @return [String]
|
37
37
|
def serialize
|
38
|
-
binary = @supported_signature_algorithms.join
|
38
|
+
binary = @supported_signature_algorithms.join.prefix_uint16_length
|
39
39
|
|
40
|
-
@extension_type + binary.prefix_uint16_length
|
40
|
+
@extension_type + binary.prefix_uint16_length
|
41
41
|
end
|
42
42
|
|
43
43
|
# @param binary [String]
|
44
44
|
#
|
45
45
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
46
46
|
#
|
47
|
-
# @return [
|
48
|
-
def self.
|
47
|
+
# @return [Array of SignatureScheme]
|
48
|
+
def self.deserialize_supported_signature_algorithms(binary)
|
49
49
|
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
50
50
|
|
51
51
|
return nil if binary.length < 2
|
@@ -61,7 +61,17 @@ module TTTLS13
|
|
61
61
|
end
|
62
62
|
return nil unless ssa_len + 2 == binary.length
|
63
63
|
|
64
|
-
|
64
|
+
supported_signature_algorithms
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param binary [String]
|
68
|
+
#
|
69
|
+
# @return [TTTLS13::Message::Extensions::SignatureAlgorithms, nil]
|
70
|
+
def self.deserialize(binary)
|
71
|
+
ssa = deserialize_supported_signature_algorithms(binary)
|
72
|
+
return nil if ssa.nil?
|
73
|
+
|
74
|
+
SignatureAlgorithms.new(ssa)
|
65
75
|
end
|
66
76
|
end
|
67
77
|
end
|
@@ -13,11 +13,12 @@ module TTTLS13
|
|
13
13
|
|
14
14
|
# @param binary [String]
|
15
15
|
#
|
16
|
-
# @return [TTTLS13::Message::Extensions::SignatureAlgorithmsCert]
|
16
|
+
# @return [TTTLS13::Message::Extensions::SignatureAlgorithmsCert, nil]
|
17
17
|
def self.deserialize(binary)
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
ssa = deserialize_supported_signature_algorithms(binary)
|
19
|
+
return nil if ssa.nil?
|
20
|
+
|
21
|
+
SignatureAlgorithmsCert.new(ssa)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
@@ -21,9 +21,9 @@ module TTTLS13
|
|
21
21
|
|
22
22
|
# @return [String]
|
23
23
|
def serialize
|
24
|
-
binary = @named_group_list.join
|
24
|
+
binary = @named_group_list.join.prefix_uint16_length
|
25
25
|
|
26
|
-
@extension_type + binary.prefix_uint16_length
|
26
|
+
@extension_type + binary.prefix_uint16_length
|
27
27
|
end
|
28
28
|
|
29
29
|
# @param binary [String]
|
@@ -121,6 +121,7 @@ module TTTLS13
|
|
121
121
|
# @return [TTTLS13::Message::Extension::$Object, nil]
|
122
122
|
# rubocop: disable Metrics/CyclomaticComplexity
|
123
123
|
# rubocop: disable Metrics/MethodLength
|
124
|
+
# rubocop: disable Metrics/PerceivedComplexity
|
124
125
|
def deserialize_extension(binary, extension_type, msg_type)
|
125
126
|
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
126
127
|
|
@@ -143,6 +144,8 @@ module TTTLS13
|
|
143
144
|
Extension::SignatureAlgorithms.deserialize(binary)
|
144
145
|
when ExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION
|
145
146
|
Extension::Alpn.deserialize(binary)
|
147
|
+
when ExtensionType::COMPRESS_CERTIFICATE
|
148
|
+
Extension::CompressCertificate.deserialize(binary)
|
146
149
|
when ExtensionType::RECORD_SIZE_LIMIT
|
147
150
|
Extension::RecordSizeLimit.deserialize(binary)
|
148
151
|
when ExtensionType::PRE_SHARED_KEY
|
@@ -165,6 +168,7 @@ module TTTLS13
|
|
165
168
|
end
|
166
169
|
# rubocop: enable Metrics/CyclomaticComplexity
|
167
170
|
# rubocop: enable Metrics/MethodLength
|
171
|
+
# rubocop: enable Metrics/PerceivedComplexity
|
168
172
|
end
|
169
173
|
end
|
170
174
|
end
|
@@ -11,23 +11,19 @@ module TTTLS13
|
|
11
11
|
attr_reader :type
|
12
12
|
attr_reader :legacy_record_version
|
13
13
|
attr_reader :messages
|
14
|
-
attr_reader :surplus_binary
|
15
14
|
attr_reader :cipher
|
16
15
|
|
17
16
|
# @param type [TTTLS13::Message::ContentType]
|
18
17
|
# @param legacy_record_version [TTTLS13::Message::ProtocolVersion]
|
19
18
|
# @param messages [Array of TTTLS13::Message::$Object]
|
20
|
-
# @param surplus_binary [String]
|
21
19
|
# @param cipher [TTTLS13::Cryptograph::$Object]
|
22
20
|
def initialize(type:,
|
23
21
|
legacy_record_version: ProtocolVersion::TLS_1_2,
|
24
22
|
messages:,
|
25
|
-
surplus_binary: '',
|
26
23
|
cipher:)
|
27
24
|
@type = type
|
28
25
|
@legacy_record_version = legacy_record_version
|
29
26
|
@messages = messages
|
30
|
-
@surplus_binary = surplus_binary
|
31
27
|
@cipher = cipher
|
32
28
|
end
|
33
29
|
|
@@ -40,7 +36,7 @@ module TTTLS13
|
|
40
36
|
#
|
41
37
|
# @return [String]
|
42
38
|
def serialize(record_size_limit = DEFAULT_RECORD_SIZE_LIMIT)
|
43
|
-
tlsplaintext = @messages.map(&:serialize).join
|
39
|
+
tlsplaintext = @messages.map(&:serialize).join
|
44
40
|
if @cipher.is_a?(Cryptograph::Aead)
|
45
41
|
max = @cipher.tlsplaintext_length_limit(record_size_limit)
|
46
42
|
fragments = tlsplaintext.scan(/.{1,#{max}}/m)
|
@@ -66,6 +62,8 @@ module TTTLS13
|
|
66
62
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
67
63
|
#
|
68
64
|
# @return [TTTLS13::Message::Record]
|
65
|
+
# @return [Array of String]
|
66
|
+
# @return [String]
|
69
67
|
# rubocop: disable Metrics/AbcSize
|
70
68
|
# rubocop: disable Metrics/CyclomaticComplexity
|
71
69
|
# rubocop: disable Metrics/PerceivedComplexity
|
@@ -93,13 +91,17 @@ module TTTLS13
|
|
93
91
|
fragment, inner_type = cipher.decrypt(fragment, binary.slice(0, 5))
|
94
92
|
end
|
95
93
|
|
96
|
-
messages, surplus_binary = deserialize_fragment(
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
94
|
+
messages, orig_msgs, surplus_binary = deserialize_fragment(
|
95
|
+
buffered + fragment,
|
96
|
+
inner_type || type
|
97
|
+
)
|
98
|
+
record = Record.new(
|
99
|
+
type: type,
|
100
|
+
legacy_record_version: legacy_record_version,
|
101
|
+
messages: messages,
|
102
|
+
cipher: cipher
|
103
|
+
)
|
104
|
+
[record, orig_msgs, surplus_binary]
|
103
105
|
end
|
104
106
|
# rubocop: enable Metrics/AbcSize
|
105
107
|
# rubocop: enable Metrics/CyclomaticComplexity
|
@@ -116,6 +118,7 @@ module TTTLS13
|
|
116
118
|
Message::ServerHello,
|
117
119
|
Message::EncryptedExtensions,
|
118
120
|
Message::Certificate,
|
121
|
+
Message::CompressedCertificate,
|
119
122
|
Message::CertificateVerify,
|
120
123
|
Message::Finished,
|
121
124
|
Message::EndOfEarlyData,
|
@@ -152,20 +155,24 @@ module TTTLS13
|
|
152
155
|
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
153
156
|
|
154
157
|
surplus_binary = ''
|
158
|
+
orig_msgs = []
|
155
159
|
case type
|
156
160
|
when ContentType::HANDSHAKE
|
157
|
-
messages, surplus_binary = deserialize_handshake(binary)
|
161
|
+
messages, orig_msgs, surplus_binary = deserialize_handshake(binary)
|
158
162
|
when ContentType::CCS
|
159
163
|
messages = [ChangeCipherSpec.deserialize(binary)]
|
164
|
+
orig_msgs = [binary]
|
160
165
|
when ContentType::APPLICATION_DATA
|
161
166
|
messages = [ApplicationData.deserialize(binary)]
|
167
|
+
orig_msgs = [binary]
|
162
168
|
when ContentType::ALERT
|
163
169
|
messages = [Alert.deserialize(binary)]
|
170
|
+
orig_msgs = [binary]
|
164
171
|
else
|
165
172
|
raise Error::ErrorAlerts, :unexpected_message
|
166
173
|
end
|
167
174
|
|
168
|
-
[messages, surplus_binary]
|
175
|
+
[messages, orig_msgs, surplus_binary]
|
169
176
|
end
|
170
177
|
|
171
178
|
# @param binary [String]
|
@@ -173,11 +180,13 @@ module TTTLS13
|
|
173
180
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
174
181
|
#
|
175
182
|
# @return [Array of TTTLS13::Message::$Object]
|
183
|
+
# @return [Array of String]
|
176
184
|
# @return [String]
|
177
185
|
def deserialize_handshake(binary)
|
178
186
|
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
179
187
|
|
180
188
|
handshakes = []
|
189
|
+
orig_msgs = []
|
181
190
|
i = 0
|
182
191
|
while i < binary.length
|
183
192
|
# Handshake.length is kind of uint24 and Record.length is kind of
|
@@ -185,18 +194,19 @@ module TTTLS13
|
|
185
194
|
if binary.length < 4 + i ||
|
186
195
|
binary.length < 4 + i + Convert.bin2i(binary.slice(i + 1, 3))
|
187
196
|
surplus_binary = binary[i..]
|
188
|
-
return [handshakes, surplus_binary]
|
197
|
+
return [handshakes, orig_msgs, surplus_binary]
|
189
198
|
end
|
190
199
|
|
191
200
|
msg_len = Convert.bin2i(binary.slice(i + 1, 3))
|
192
201
|
msg_bin = binary.slice(i, msg_len + 4)
|
202
|
+
orig_msgs << msg_bin
|
193
203
|
message = do_deserialize_handshake(msg_bin)
|
194
204
|
i += msg_len + 4
|
195
205
|
handshakes << message
|
196
206
|
end
|
197
207
|
|
198
208
|
surplus_binary = binary[i..]
|
199
|
-
[handshakes, surplus_binary]
|
209
|
+
[handshakes, orig_msgs, surplus_binary]
|
200
210
|
end
|
201
211
|
|
202
212
|
# @param binary [String]
|
@@ -226,6 +236,8 @@ module TTTLS13
|
|
226
236
|
NewSessionTicket.deserialize(binary)
|
227
237
|
when HandshakeType::END_OF_EARLY_DATA
|
228
238
|
EndOfEarlyData.deserialize(binary)
|
239
|
+
when HandshakeType::COMPRESSED_CERTIFICATE
|
240
|
+
CompressedCertificate.deserialize(binary)
|
229
241
|
else
|
230
242
|
raise Error::ErrorAlerts, :unexpected_message
|
231
243
|
end
|
data/lib/tttls1.3/message.rb
CHANGED
@@ -21,26 +21,27 @@ module TTTLS13
|
|
21
21
|
DEFAULT_VERSIONS = [ProtocolVersion::TLS_1_3].freeze
|
22
22
|
|
23
23
|
module HandshakeType
|
24
|
-
HELLO_REQUEST
|
25
|
-
CLIENT_HELLO
|
26
|
-
SERVER_HELLO
|
27
|
-
HELLO_VERIFY_REQUEST
|
28
|
-
NEW_SESSION_TICKET
|
29
|
-
END_OF_EARLY_DATA
|
30
|
-
HELLO_RETRY_REQUEST
|
31
|
-
ENCRYPTED_EXTENSIONS
|
32
|
-
CERTIFICATE
|
33
|
-
SERVER_KEY_EXCHANGE
|
34
|
-
CERTIFICATE_REQUEST
|
35
|
-
SERVER_HELLO_DONE
|
36
|
-
CERTIFICATE_VERIFY
|
37
|
-
CLIENT_KEY_EXCHANGE
|
38
|
-
FINISHED
|
39
|
-
CERTIFICATE_URL
|
40
|
-
CERTIFICATE_STATUS
|
41
|
-
SUPPLEMENTAL_DATA
|
42
|
-
KEY_UPDATE
|
43
|
-
|
24
|
+
HELLO_REQUEST = "\x00" # RESERVED
|
25
|
+
CLIENT_HELLO = "\x01"
|
26
|
+
SERVER_HELLO = "\x02"
|
27
|
+
HELLO_VERIFY_REQUEST = "\x03" # RESERVED
|
28
|
+
NEW_SESSION_TICKET = "\x04"
|
29
|
+
END_OF_EARLY_DATA = "\x05"
|
30
|
+
HELLO_RETRY_REQUEST = "\x06" # RESERVED
|
31
|
+
ENCRYPTED_EXTENSIONS = "\x08"
|
32
|
+
CERTIFICATE = "\x0b"
|
33
|
+
SERVER_KEY_EXCHANGE = "\x0c" # RESERVED
|
34
|
+
CERTIFICATE_REQUEST = "\x0d"
|
35
|
+
SERVER_HELLO_DONE = "\x0e" # RESERVED
|
36
|
+
CERTIFICATE_VERIFY = "\x0f"
|
37
|
+
CLIENT_KEY_EXCHANGE = "\x10" # RESERVED
|
38
|
+
FINISHED = "\x14"
|
39
|
+
CERTIFICATE_URL = "\x15" # RESERVED
|
40
|
+
CERTIFICATE_STATUS = "\x16" # RESERVED
|
41
|
+
SUPPLEMENTAL_DATA = "\x17" # RESERVED
|
42
|
+
KEY_UPDATE = "\x18"
|
43
|
+
COMPRESSED_CERTIFICATE = "\x19"
|
44
|
+
MESSAGE_HASH = "\xfe"
|
44
45
|
end
|
45
46
|
|
46
47
|
module ExtensionType
|
@@ -56,6 +57,7 @@ module TTTLS13
|
|
56
57
|
CLIENT_CERTIFICATE_TYPE = "\x00\x13"
|
57
58
|
SERVER_CERTIFICATE_TYPE = "\x00\x14"
|
58
59
|
PADDING = "\x00\x15"
|
60
|
+
COMPRESS_CERTIFICATE = "\x00\x1b"
|
59
61
|
RECORD_SIZE_LIMIT = "\x00\x1c"
|
60
62
|
PWD_PROTECT = "\x00\x1d"
|
61
63
|
PWD_CLEAR = "\x00\x1e"
|
data/lib/tttls1.3/server.rb
CHANGED
@@ -44,6 +44,11 @@ module TTTLS13
|
|
44
44
|
].freeze
|
45
45
|
private_constant :DEFAULT_SP_NAMED_GROUP_LIST
|
46
46
|
|
47
|
+
DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS = [
|
48
|
+
Message::Extension::CertificateCompressionAlgorithm::ZLIB
|
49
|
+
].freeze
|
50
|
+
private_constant :DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS
|
51
|
+
|
47
52
|
DEFAULT_SERVER_SETTINGS = {
|
48
53
|
crt_file: nil,
|
49
54
|
chain_files: nil,
|
@@ -53,6 +58,7 @@ module TTTLS13
|
|
53
58
|
supported_groups: DEFAULT_SP_NAMED_GROUP_LIST,
|
54
59
|
alpn: nil,
|
55
60
|
process_ocsp_response: nil,
|
61
|
+
compress_certificate_algorithms: DEFAULT_SP_COMPRESS_CERTIFICATE_ALGORITHMS,
|
56
62
|
compatibility_mode: true,
|
57
63
|
loglevel: Logger::WARN
|
58
64
|
}.freeze
|
@@ -140,7 +146,6 @@ module TTTLS13
|
|
140
146
|
transcript = Transcript.new
|
141
147
|
key_schedule = nil # TTTLS13::KeySchedule
|
142
148
|
priv_key = nil # OpenSSL::PKey::$Object
|
143
|
-
|
144
149
|
hs_wcipher = nil # TTTLS13::Cryptograph::$Object
|
145
150
|
hs_rcipher = nil # TTTLS13::Cryptograph::$Object
|
146
151
|
|
@@ -151,7 +156,7 @@ module TTTLS13
|
|
151
156
|
logger.debug('ServerState::START')
|
152
157
|
|
153
158
|
receivable_ccs = transcript.include?(CH1)
|
154
|
-
ch = transcript[CH] = recv_client_hello(receivable_ccs)
|
159
|
+
ch, = transcript[CH] = recv_client_hello(receivable_ccs)
|
155
160
|
|
156
161
|
# support only TLS 1.3
|
157
162
|
terminate(:protocol_version) unless ch.negotiated_tls_1_3?
|
@@ -183,7 +188,7 @@ module TTTLS13
|
|
183
188
|
logger.debug('ServerState::RECVD_CH')
|
184
189
|
|
185
190
|
# select parameters
|
186
|
-
ch = transcript[CH]
|
191
|
+
ch, = transcript[CH]
|
187
192
|
@cipher_suite = select_cipher_suite(ch)
|
188
193
|
@named_group = select_named_group(ch)
|
189
194
|
@signature_scheme = select_signature_scheme(ch, @crt)
|
@@ -192,8 +197,9 @@ module TTTLS13
|
|
192
197
|
|
193
198
|
# send HRR
|
194
199
|
if @named_group.nil?
|
195
|
-
ch1 = transcript[CH1] = transcript.delete(CH)
|
196
|
-
|
200
|
+
ch1, = transcript[CH1] = transcript.delete(CH)
|
201
|
+
hrr = send_hello_retry_request(ch1, @cipher_suite)
|
202
|
+
transcript[HRR] = [hrr, hrr.serialize]
|
197
203
|
@state = ServerState::START
|
198
204
|
next
|
199
205
|
end
|
@@ -201,10 +207,14 @@ module TTTLS13
|
|
201
207
|
when ServerState::NEGOTIATED
|
202
208
|
logger.debug('ServerState::NEGOTIATED')
|
203
209
|
|
204
|
-
ch = transcript[CH]
|
210
|
+
ch, = transcript[CH]
|
205
211
|
extensions, priv_key = gen_sh_extensions(@named_group)
|
206
|
-
|
207
|
-
|
212
|
+
sh = send_server_hello(
|
213
|
+
extensions,
|
214
|
+
@cipher_suite,
|
215
|
+
ch.legacy_session_id
|
216
|
+
)
|
217
|
+
transcript[SH] = [sh, sh.serialize]
|
208
218
|
send_ccs if @settings[:compatibility_mode]
|
209
219
|
|
210
220
|
# generate shared secret
|
@@ -235,29 +245,30 @@ module TTTLS13
|
|
235
245
|
when ServerState::WAIT_FLIGHT2
|
236
246
|
logger.debug('ServerState::WAIT_FLIGHT2')
|
237
247
|
|
238
|
-
ch = transcript[CH]
|
248
|
+
ch, = transcript[CH]
|
239
249
|
rsl = @send_record_size \
|
240
250
|
if ch.extensions.include?(Message::ExtensionType::RECORD_SIZE_LIMIT)
|
241
|
-
ee =
|
251
|
+
ee = gen_encrypted_extensions(ch, @alpn, rsl)
|
252
|
+
transcript[EE] = [ee, ee.serialize]
|
242
253
|
# TODO: [Send CertificateRequest]
|
243
254
|
|
244
255
|
# status_request
|
245
256
|
ocsp_response = fetch_ocsp_response \
|
246
257
|
if ch.extensions.include?(Message::ExtensionType::STATUS_REQUEST)
|
247
|
-
ct =
|
258
|
+
ct = gen_certificate(@crt, ch, @chain, ocsp_response)
|
259
|
+
transcript[CT] = [ct, ct.serialize]
|
248
260
|
digest = CipherSuite.digest(@cipher_suite)
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
transcript.hash(digest, CT)
|
253
|
-
)
|
261
|
+
hash = transcript.hash(digest, CT)
|
262
|
+
cv = gen_certificate_verify(@key, @signature_scheme, hash)
|
263
|
+
transcript[CV] = [cv, cv.serialize]
|
254
264
|
finished_key = key_schedule.server_finished_key
|
255
265
|
signature = sign_finished(
|
256
266
|
digest: digest,
|
257
267
|
finished_key: finished_key,
|
258
268
|
hash: transcript.hash(digest, CV)
|
259
269
|
)
|
260
|
-
sf =
|
270
|
+
sf = Message::Finished.new(signature)
|
271
|
+
transcript[SF] = [sf, sf.serialize]
|
261
272
|
send_server_parameters([ee, ct, cv, sf], hs_wcipher)
|
262
273
|
@state = ServerState::WAIT_FINISHED
|
263
274
|
when ServerState::WAIT_CERT
|
@@ -267,7 +278,7 @@ module TTTLS13
|
|
267
278
|
when ServerState::WAIT_FINISHED
|
268
279
|
logger.debug('ServerState::WAIT_FINISHED')
|
269
280
|
|
270
|
-
cf = transcript[CF] = recv_finished(hs_rcipher)
|
281
|
+
cf, = transcript[CF] = recv_finished(hs_rcipher)
|
271
282
|
digest = CipherSuite.digest(@cipher_suite)
|
272
283
|
verified = verified_finished?(
|
273
284
|
finished: cf,
|
@@ -325,12 +336,15 @@ module TTTLS13
|
|
325
336
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
326
337
|
#
|
327
338
|
# @return [TTTLS13::Message::ClientHello]
|
339
|
+
# @return [String]
|
328
340
|
def recv_client_hello(receivable_ccs)
|
329
|
-
ch = recv_message(
|
330
|
-
|
341
|
+
ch, orig_msg = recv_message(
|
342
|
+
receivable_ccs: receivable_ccs,
|
343
|
+
cipher: Cryptograph::Passer.new
|
344
|
+
)
|
331
345
|
terminate(:unexpected_message) unless ch.is_a?(Message::ClientHello)
|
332
346
|
|
333
|
-
ch
|
347
|
+
[ch, orig_msg]
|
334
348
|
end
|
335
349
|
|
336
350
|
# @param extensions [TTTLS13::Message::Extensions]
|
@@ -408,19 +422,39 @@ module TTTLS13
|
|
408
422
|
end
|
409
423
|
|
410
424
|
# @param crt [OpenSSL::X509::Certificate]
|
425
|
+
# @param ch [TTTLS13::Message::ClientHell]
|
411
426
|
# @param chain [Array of OpenSSL::X509::Certificate]
|
412
427
|
# @param ocsp_response [OpenSSL::OCSP::Response]
|
413
428
|
#
|
414
|
-
# @return [TTTLS13::Message::Certificate, nil]
|
415
|
-
|
429
|
+
# @return [TTTLS13::Message::Certificate, CompressedCertificate, nil]
|
430
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
431
|
+
def gen_certificate(crt, ch, chain = [], ocsp_response = nil)
|
416
432
|
exs = Message::Extensions.new
|
417
433
|
# status_request
|
418
434
|
exs << Message::Extension::OCSPResponse.new(ocsp_response) \
|
419
435
|
unless ocsp_response.nil?
|
420
436
|
ces = [Message::CertificateEntry.new(crt, exs)] \
|
421
437
|
+ (chain || []).map { |c| Message::CertificateEntry.new(c) }
|
422
|
-
Message::Certificate.new(certificate_list: ces)
|
438
|
+
ct = Message::Certificate.new(certificate_list: ces)
|
439
|
+
|
440
|
+
# compress_certificate
|
441
|
+
cc = ch.extensions[Message::ExtensionType::COMPRESS_CERTIFICATE]
|
442
|
+
if !cc.nil? && !cc.algorithms.empty?
|
443
|
+
cca = (@settings[:compress_certificate_algorithms] || []).find do |a|
|
444
|
+
cc.algorithms.include?(a)
|
445
|
+
end
|
446
|
+
|
447
|
+
unless cca.nil?
|
448
|
+
ct = Message::CompressedCertificate.new(
|
449
|
+
certificate_message: ct,
|
450
|
+
algorithm: cca
|
451
|
+
)
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
ct
|
423
456
|
end
|
457
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
424
458
|
|
425
459
|
# @param key [OpenSSL::PKey::PKey]
|
426
460
|
# @param signature_scheme [TTTLS13::SignatureScheme]
|
@@ -442,11 +476,12 @@ module TTTLS13
|
|
442
476
|
# @raise [TTTLS13::Error::ErrorAlerts]
|
443
477
|
#
|
444
478
|
# @return [TTTLS13::Message::Finished]
|
479
|
+
# @return [String]
|
445
480
|
def recv_finished(cipher)
|
446
|
-
cf = recv_message(receivable_ccs: true, cipher: cipher)
|
481
|
+
cf, orig_msg = recv_message(receivable_ccs: true, cipher: cipher)
|
447
482
|
terminate(:unexpected_message) unless cf.is_a?(Message::Finished)
|
448
483
|
|
449
|
-
cf
|
484
|
+
[cf, orig_msg]
|
450
485
|
end
|
451
486
|
|
452
487
|
# @param named_group [TTTLS13::NamedGroup]
|
data/lib/tttls1.3/transcript.rb
CHANGED
@@ -19,10 +19,6 @@ module TTTLS13
|
|
19
19
|
CF = 12
|
20
20
|
|
21
21
|
class Transcript < Hash
|
22
|
-
def initialize
|
23
|
-
super
|
24
|
-
end
|
25
|
-
|
26
22
|
alias super_include? include?
|
27
23
|
|
28
24
|
# @param digest [String] name of digest algorithm
|
@@ -62,12 +58,12 @@ module TTTLS13
|
|
62
58
|
exc_prefix = Message::HandshakeType::MESSAGE_HASH \
|
63
59
|
+ "\x00\x00" \
|
64
60
|
+ OpenSSL::Digest.new(digest).digest_length.to_uint8 \
|
65
|
-
+ OpenSSL::Digest.digest(digest, self[CH1].
|
66
|
-
+ self[HRR].
|
61
|
+
+ OpenSSL::Digest.digest(digest, self[CH1].last) \
|
62
|
+
+ self[HRR].last
|
67
63
|
end
|
68
64
|
|
69
65
|
messages = (CH..end_index).to_a.map do |m|
|
70
|
-
include?(m) ? self[m].
|
66
|
+
include?(m) ? self[m].last : ''
|
71
67
|
end
|
72
68
|
exc_prefix + messages.join
|
73
69
|
end
|
data/lib/tttls1.3/version.rb
CHANGED