tttls1.3 0.1.0
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 +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.rubocop.yml +16 -0
- data/.travis.yml +8 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +52 -0
- data/Rakefile +133 -0
- data/example/helper.rb +17 -0
- data/example/https_client.rb +32 -0
- data/example/https_client_using_0rtt.rb +64 -0
- data/example/https_client_using_hrr.rb +35 -0
- data/example/https_client_using_ticket.rb +56 -0
- data/lib/tttls1.3/cipher_suites.rb +102 -0
- data/lib/tttls1.3/client.rb +745 -0
- data/lib/tttls1.3/connection.rb +380 -0
- data/lib/tttls1.3/cryptograph/aead.rb +118 -0
- data/lib/tttls1.3/cryptograph/passer.rb +22 -0
- data/lib/tttls1.3/cryptograph.rb +3 -0
- data/lib/tttls1.3/error.rb +22 -0
- data/lib/tttls1.3/key_schedule.rb +242 -0
- data/lib/tttls1.3/message/alert.rb +86 -0
- data/lib/tttls1.3/message/application_data.rb +27 -0
- data/lib/tttls1.3/message/certificate.rb +121 -0
- data/lib/tttls1.3/message/certificate_verify.rb +59 -0
- data/lib/tttls1.3/message/change_cipher_spec.rb +26 -0
- data/lib/tttls1.3/message/client_hello.rb +100 -0
- data/lib/tttls1.3/message/encrypted_extensions.rb +65 -0
- data/lib/tttls1.3/message/end_of_early_data.rb +29 -0
- data/lib/tttls1.3/message/extension/alpn.rb +70 -0
- data/lib/tttls1.3/message/extension/cookie.rb +47 -0
- data/lib/tttls1.3/message/extension/early_data_indication.rb +58 -0
- data/lib/tttls1.3/message/extension/key_share.rb +236 -0
- data/lib/tttls1.3/message/extension/pre_shared_key.rb +205 -0
- data/lib/tttls1.3/message/extension/psk_key_exchange_modes.rb +54 -0
- data/lib/tttls1.3/message/extension/record_size_limit.rb +46 -0
- data/lib/tttls1.3/message/extension/server_name.rb +91 -0
- data/lib/tttls1.3/message/extension/signature_algorithms.rb +69 -0
- data/lib/tttls1.3/message/extension/signature_algorithms_cert.rb +25 -0
- data/lib/tttls1.3/message/extension/status_request.rb +106 -0
- data/lib/tttls1.3/message/extension/supported_groups.rb +145 -0
- data/lib/tttls1.3/message/extension/supported_versions.rb +98 -0
- data/lib/tttls1.3/message/extension/unknown_extension.rb +38 -0
- data/lib/tttls1.3/message/extensions.rb +173 -0
- data/lib/tttls1.3/message/finished.rb +44 -0
- data/lib/tttls1.3/message/new_session_ticket.rb +89 -0
- data/lib/tttls1.3/message/record.rb +232 -0
- data/lib/tttls1.3/message/server_hello.rb +116 -0
- data/lib/tttls1.3/message.rb +48 -0
- data/lib/tttls1.3/sequence_number.rb +31 -0
- data/lib/tttls1.3/signature_scheme.rb +31 -0
- data/lib/tttls1.3/transcript.rb +69 -0
- data/lib/tttls1.3/utils.rb +91 -0
- data/lib/tttls1.3/version.rb +5 -0
- data/lib/tttls1.3.rb +16 -0
- data/spec/aead_spec.rb +95 -0
- data/spec/alert_spec.rb +54 -0
- data/spec/alpn_spec.rb +55 -0
- data/spec/application_data_spec.rb +26 -0
- data/spec/certificate_spec.rb +55 -0
- data/spec/certificate_verify_spec.rb +51 -0
- data/spec/change_cipher_spec_spec.rb +26 -0
- data/spec/cipher_suites_spec.rb +39 -0
- data/spec/client_hello_spec.rb +83 -0
- data/spec/client_spec.rb +319 -0
- data/spec/connection_spec.rb +114 -0
- data/spec/cookie_spec.rb +98 -0
- data/spec/early_data_indication_spec.rb +64 -0
- data/spec/encrypted_extensions_spec.rb +94 -0
- data/spec/error_spec.rb +18 -0
- data/spec/extensions_spec.rb +170 -0
- data/spec/finished_spec.rb +55 -0
- data/spec/key_schedule_spec.rb +198 -0
- data/spec/key_share_spec.rb +199 -0
- data/spec/new_session_ticket_spec.rb +80 -0
- data/spec/pre_shared_key_spec.rb +167 -0
- data/spec/psk_key_exchange_modes_spec.rb +45 -0
- data/spec/record_size_limit_spec.rb +61 -0
- data/spec/record_spec.rb +105 -0
- data/spec/server_hello_spec.rb +101 -0
- data/spec/server_name_spec.rb +110 -0
- data/spec/signature_algorithms_cert_spec.rb +73 -0
- data/spec/signature_algorithms_spec.rb +100 -0
- data/spec/spec_helper.rb +872 -0
- data/spec/status_request_spec.rb +73 -0
- data/spec/supported_groups_spec.rb +79 -0
- data/spec/supported_versions_spec.rb +136 -0
- data/spec/transcript_spec.rb +69 -0
- data/spec/unknown_extension_spec.rb +90 -0
- data/spec/utils_spec.rb +215 -0
- data/tttls1.3.gemspec +25 -0
- metadata +197 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module TTTLS13
|
5
|
+
using Refinements
|
6
|
+
module Message
|
7
|
+
module Extension
|
8
|
+
# NOTE:
|
9
|
+
# struct {
|
10
|
+
# select (Handshake.msg_type) {
|
11
|
+
# case client_hello: OfferedPsks;
|
12
|
+
# case server_hello: uint16 selected_identity;
|
13
|
+
# };
|
14
|
+
# } PreSharedKeyExtension;
|
15
|
+
class PreSharedKey
|
16
|
+
attr_reader :extension_type
|
17
|
+
attr_reader :msg_type
|
18
|
+
attr_reader :offered_psks
|
19
|
+
attr_reader :selected_identity
|
20
|
+
|
21
|
+
# @param msg_type [TTTLS13::Message::ContentType]
|
22
|
+
# @param offered_psks [TTTLS13::Message::Extension::OfferedPsks]
|
23
|
+
# @param selected_identity [String]
|
24
|
+
#
|
25
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
26
|
+
def initialize(msg_type:, offered_psks: nil, selected_identity: '')
|
27
|
+
@extension_type = ExtensionType::PRE_SHARED_KEY
|
28
|
+
@msg_type = msg_type
|
29
|
+
case @msg_type
|
30
|
+
when HandshakeType::CLIENT_HELLO
|
31
|
+
@offered_psks = offered_psks
|
32
|
+
when HandshakeType::SERVER_HELLO
|
33
|
+
@selected_identity = selected_identity || ''
|
34
|
+
raise Error::ErrorAlerts, :internal_error \
|
35
|
+
unless @selected_identity.length == 2
|
36
|
+
else
|
37
|
+
raise Error::ErrorAlerts, :internal_error
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
42
|
+
#
|
43
|
+
# @return [String]
|
44
|
+
def serialize
|
45
|
+
binary = ''
|
46
|
+
case @msg_type
|
47
|
+
when HandshakeType::CLIENT_HELLO
|
48
|
+
binary += @offered_psks.serialize
|
49
|
+
when HandshakeType::SERVER_HELLO
|
50
|
+
binary += @selected_identity
|
51
|
+
else
|
52
|
+
raise Error::ErrorAlerts, :internal_error
|
53
|
+
end
|
54
|
+
|
55
|
+
@extension_type + binary.prefix_uint16_length
|
56
|
+
end
|
57
|
+
|
58
|
+
# @param binary [String]
|
59
|
+
# @param msg_type [TTTLS13::Message::ContentType]
|
60
|
+
#
|
61
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
62
|
+
#
|
63
|
+
# @return [TTTLS13::Message::Extensions::PreSharedKey, nil]
|
64
|
+
def self.deserialize(binary, msg_type)
|
65
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
66
|
+
|
67
|
+
case msg_type
|
68
|
+
when HandshakeType::CLIENT_HELLO
|
69
|
+
offered_psks = OfferedPsks.deserialize(binary)
|
70
|
+
return nil if offered_psks.nil?
|
71
|
+
|
72
|
+
PreSharedKey.new(msg_type: HandshakeType::CLIENT_HELLO,
|
73
|
+
offered_psks: offered_psks)
|
74
|
+
when HandshakeType::SERVER_HELLO
|
75
|
+
return nil unless binary.length == 2
|
76
|
+
|
77
|
+
selected_identity = binary
|
78
|
+
PreSharedKey.new(msg_type: HandshakeType::SERVER_HELLO,
|
79
|
+
selected_identity: selected_identity)
|
80
|
+
else
|
81
|
+
raise Error::ErrorAlerts, :internal_error
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# NOTE:
|
87
|
+
# opaque PskBinderEntry<32..255>;
|
88
|
+
#
|
89
|
+
# struct {
|
90
|
+
# PskIdentity identities<7..2^16-1>;
|
91
|
+
# PskBinderEntry binders<33..2^16-1>;
|
92
|
+
# } OfferedPsks;
|
93
|
+
class OfferedPsks
|
94
|
+
attr_reader :identities
|
95
|
+
attr_reader :binders
|
96
|
+
|
97
|
+
# @param identities [Array of PskIdentity]
|
98
|
+
# @param binders [Array of String]
|
99
|
+
#
|
100
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
101
|
+
def initialize(identities: [], binders: [])
|
102
|
+
@identities = identities || []
|
103
|
+
@binders = binders || []
|
104
|
+
raise Error::ErrorAlerts, :internal_error \
|
105
|
+
if @identities.empty? || @binders.empty?
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [String]
|
109
|
+
def serialize
|
110
|
+
binary = @identities.map(&:serialize).join
|
111
|
+
identities_bin = binary.prefix_uint16_length
|
112
|
+
|
113
|
+
binary = @binders.map(&:prefix_uint8_length).join
|
114
|
+
binders_bin = binary.prefix_uint16_length
|
115
|
+
|
116
|
+
identities_bin + binders_bin
|
117
|
+
end
|
118
|
+
|
119
|
+
# @param binary [String]
|
120
|
+
#
|
121
|
+
# @return [TTTLS13::Message::Extensions::OfferedPsks, nil]
|
122
|
+
# rubocop: disable Metrics/AbcSize
|
123
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
124
|
+
# rubocop: disable Metrics/MethodLength
|
125
|
+
# rubocop: disable Metrics/PerceivedComplexity
|
126
|
+
def self.deserialize(binary)
|
127
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
128
|
+
return nil if binary.length < 2
|
129
|
+
|
130
|
+
pskids_len = Convert.bin2i(binary.slice(0, 2))
|
131
|
+
i = 2
|
132
|
+
identities = [] # Array of PskIdentity
|
133
|
+
while i < pskids_len + 2
|
134
|
+
return nil if i + 2 > binary.length
|
135
|
+
|
136
|
+
id_len = Convert.bin2i(binary.slice(i, 2))
|
137
|
+
return nil if id_len.zero?
|
138
|
+
|
139
|
+
i += 2
|
140
|
+
identity = binary.slice(i, id_len)
|
141
|
+
i += id_len
|
142
|
+
|
143
|
+
return nil if i + 4 > binary.length
|
144
|
+
|
145
|
+
obfuscated_ticket_age = Convert.bin2i(binary.slice(i, 4))
|
146
|
+
i += 4
|
147
|
+
identities << PskIdentity.new(
|
148
|
+
identity: identity,
|
149
|
+
obfuscated_ticket_age: obfuscated_ticket_age
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
i += 2
|
154
|
+
binders = [] # Array of String
|
155
|
+
while i < binary.length
|
156
|
+
return nil if i > binary.length
|
157
|
+
|
158
|
+
pbe_len = Convert.bin2i(binary[i])
|
159
|
+
return nil if pbe_len < 32
|
160
|
+
|
161
|
+
i += 1
|
162
|
+
binders << binary.slice(i, pbe_len)
|
163
|
+
i += pbe_len
|
164
|
+
end
|
165
|
+
return nil unless i == binary.length
|
166
|
+
|
167
|
+
OfferedPsks.new(identities: identities, binders: binders)
|
168
|
+
end
|
169
|
+
# rubocop: enable Metrics/AbcSize
|
170
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
171
|
+
# rubocop: enable Metrics/MethodLength
|
172
|
+
# rubocop: enable Metrics/PerceivedComplexity
|
173
|
+
end
|
174
|
+
|
175
|
+
# NOTE:
|
176
|
+
# struct {
|
177
|
+
# opaque identity<1..2^16-1>;
|
178
|
+
# uint32 obfuscated_ticket_age;
|
179
|
+
# } PskIdentity;
|
180
|
+
class PskIdentity
|
181
|
+
attr_reader :identity
|
182
|
+
attr_reader :obfuscated_ticket_age
|
183
|
+
|
184
|
+
# @param identity [String]
|
185
|
+
# @param obfuscated_ticket_age [Integer]
|
186
|
+
#
|
187
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
188
|
+
def initialize(identity: '', obfuscated_ticket_age: 0)
|
189
|
+
@identity = identity || ''
|
190
|
+
@obfuscated_ticket_age = obfuscated_ticket_age
|
191
|
+
raise Error::ErrorAlerts, :internal_error \
|
192
|
+
if @identity.empty? || @obfuscated_ticket_age.negative?
|
193
|
+
end
|
194
|
+
|
195
|
+
# @return [String]
|
196
|
+
def serialize
|
197
|
+
binary = ''
|
198
|
+
binary += @identity.prefix_uint16_length
|
199
|
+
binary += @obfuscated_ticket_age.to_uint32
|
200
|
+
binary
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module TTTLS13
|
5
|
+
using Refinements
|
6
|
+
module Message
|
7
|
+
module Extension
|
8
|
+
module PskKeyExchangeMode
|
9
|
+
PSK_KE = "\x00"
|
10
|
+
PSK_DHE_KE = "\x01"
|
11
|
+
end
|
12
|
+
|
13
|
+
class PskKeyExchangeModes
|
14
|
+
attr_reader :extension_type
|
15
|
+
attr_reader :ke_modes
|
16
|
+
|
17
|
+
# @param ke_modes [Array of PskKeyExchangeMode]
|
18
|
+
def initialize(ke_modes = [])
|
19
|
+
@extension_type = ExtensionType::PSK_KEY_EXCHANGE_MODES
|
20
|
+
@ke_modes = ke_modes || []
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [String]
|
24
|
+
def serialize
|
25
|
+
binary = @ke_modes.join.prefix_uint8_length
|
26
|
+
|
27
|
+
@extension_type + binary.prefix_uint16_length
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param binary [String]
|
31
|
+
#
|
32
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
33
|
+
#
|
34
|
+
# @return [TTTLS13::Message::Extensions::PskKeyExchangeModes, nil]
|
35
|
+
def self.deserialize(binary)
|
36
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
37
|
+
|
38
|
+
return nil if binary.empty?
|
39
|
+
|
40
|
+
kem_len = Convert.bin2i(binary[0])
|
41
|
+
ke_modes = []
|
42
|
+
i = 1
|
43
|
+
while i < kem_len + 1
|
44
|
+
ke_modes << binary[i]
|
45
|
+
i += 1
|
46
|
+
end
|
47
|
+
return nil unless kem_len + 1 == binary.length
|
48
|
+
|
49
|
+
PskKeyExchangeModes.new(ke_modes)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module TTTLS13
|
5
|
+
using Refinements
|
6
|
+
module Message
|
7
|
+
module Extension
|
8
|
+
class RecordSizeLimit
|
9
|
+
attr_reader :extension_type
|
10
|
+
attr_reader :record_size_limit
|
11
|
+
|
12
|
+
# @param record_size_limit [Integer]
|
13
|
+
#
|
14
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
15
|
+
def initialize(record_size_limit)
|
16
|
+
@extension_type = ExtensionType::RECORD_SIZE_LIMIT
|
17
|
+
@record_size_limit = record_size_limit
|
18
|
+
raise Error::ErrorAlerts, :internal_error if @record_size_limit < 64
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String]
|
22
|
+
def serialize
|
23
|
+
binary = @record_size_limit.to_uint16
|
24
|
+
|
25
|
+
@extension_type + binary.prefix_uint16_length
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param binary [String]
|
29
|
+
#
|
30
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
31
|
+
#
|
32
|
+
# @return [TTTLS13::Message::Extensions::RecordSizeLimit, nil]
|
33
|
+
def self.deserialize(binary)
|
34
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
35
|
+
|
36
|
+
return nil if binary.length != 2
|
37
|
+
|
38
|
+
record_size_limit = Convert.bin2i(binary)
|
39
|
+
raise Error::ErrorAlerts, :illegal_parameter if record_size_limit < 64
|
40
|
+
|
41
|
+
RecordSizeLimit.new(record_size_limit)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module TTTLS13
|
5
|
+
using Refinements
|
6
|
+
module Message
|
7
|
+
module Extension
|
8
|
+
module NameType
|
9
|
+
HOST_NAME = "\x00"
|
10
|
+
end
|
11
|
+
|
12
|
+
# NOTE:
|
13
|
+
# The extension_data field SHALL be empty when @server_name is empty.
|
14
|
+
# Then, serialized extension_data is
|
15
|
+
#
|
16
|
+
# 00 00 00 00
|
17
|
+
#
|
18
|
+
# https://tools.ietf.org/html/rfc6066#section-3
|
19
|
+
class ServerName
|
20
|
+
attr_reader :extension_type
|
21
|
+
attr_reader :server_name
|
22
|
+
|
23
|
+
# @param server_name [String]
|
24
|
+
#
|
25
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# ServerName.new('example.com')
|
29
|
+
def initialize(server_name)
|
30
|
+
@extension_type = ExtensionType::SERVER_NAME
|
31
|
+
@server_name = server_name || ''
|
32
|
+
raise Error::ErrorAlerts, :internal_error \
|
33
|
+
if @server_name.length > 2**16 - 5
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [String]
|
37
|
+
def serialize
|
38
|
+
return "\x00\x00\x00\x00" if @server_name.empty?
|
39
|
+
|
40
|
+
sn_len = @server_name.length
|
41
|
+
binary = ''
|
42
|
+
binary += @extension_type
|
43
|
+
binary += (sn_len + 5).to_uint16
|
44
|
+
binary += (sn_len + 3).to_uint16
|
45
|
+
binary += NameType::HOST_NAME
|
46
|
+
binary += sn_len.to_uint16
|
47
|
+
binary += @server_name
|
48
|
+
binary
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param binary [String]
|
52
|
+
#
|
53
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
54
|
+
#
|
55
|
+
# @return [TTTLS13::Message::Extension::ServerName, nil]
|
56
|
+
def self.deserialize(binary)
|
57
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
58
|
+
|
59
|
+
return nil if binary.length == 1
|
60
|
+
return ServerName.new('') if binary.empty?
|
61
|
+
|
62
|
+
deserialize_host_name(binary)
|
63
|
+
end
|
64
|
+
|
65
|
+
class << self
|
66
|
+
private
|
67
|
+
|
68
|
+
# @param binary [String]
|
69
|
+
#
|
70
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
71
|
+
#
|
72
|
+
# @return [TTTLS13::Message::Extension::ServerName, nil]
|
73
|
+
def deserialize_host_name(binary)
|
74
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
75
|
+
|
76
|
+
return nil unless binary.length > 5 &&
|
77
|
+
binary[2] == NameType::HOST_NAME
|
78
|
+
|
79
|
+
snlist_len = Convert.bin2i(binary.slice(0, 2))
|
80
|
+
sn_len = Convert.bin2i(binary.slice(3, 2))
|
81
|
+
server_name = binary.slice(5, sn_len)
|
82
|
+
return nil unless snlist_len + 2 == binary.length &&
|
83
|
+
sn_len + 5 == binary.length
|
84
|
+
|
85
|
+
ServerName.new(server_name)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module TTTLS13
|
5
|
+
using Refinements
|
6
|
+
module Message
|
7
|
+
module Extension
|
8
|
+
class SignatureAlgorithms
|
9
|
+
DEFAULT_SIGNATURE_ALGORITHMS = [
|
10
|
+
SignatureScheme::ECDSA_SECP256R1_SHA256,
|
11
|
+
SignatureScheme::ECDSA_SECP384R1_SHA384,
|
12
|
+
SignatureScheme::ECDSA_SECP521R1_SHA512,
|
13
|
+
SignatureScheme::RSA_PSS_PSS_SHA256,
|
14
|
+
SignatureScheme::RSA_PSS_PSS_SHA384,
|
15
|
+
SignatureScheme::RSA_PSS_PSS_SHA512,
|
16
|
+
SignatureScheme::RSA_PSS_RSAE_SHA256,
|
17
|
+
SignatureScheme::RSA_PSS_RSAE_SHA384,
|
18
|
+
SignatureScheme::RSA_PSS_RSAE_SHA512,
|
19
|
+
SignatureScheme::RSA_PKCS1_SHA256,
|
20
|
+
SignatureScheme::RSA_PKCS1_SHA384,
|
21
|
+
SignatureScheme::RSA_PKCS1_SHA512
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
attr_accessor :extension_type # for signature_algorithms_cert getter
|
25
|
+
attr_reader :supported_signature_algorithms
|
26
|
+
|
27
|
+
# @param supported_signature_algorithms [Array of SignatureScheme]
|
28
|
+
def initialize(supported_signature_algorithms)
|
29
|
+
@extension_type = ExtensionType::SIGNATURE_ALGORITHMS
|
30
|
+
@supported_signature_algorithms = supported_signature_algorithms || []
|
31
|
+
raise Error::ErrorAlerts, :internal_error \
|
32
|
+
if @supported_signature_algorithms.empty? ||
|
33
|
+
@supported_signature_algorithms.length * 2 > 2**16 - 3
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [String]
|
37
|
+
def serialize
|
38
|
+
binary = @supported_signature_algorithms.join
|
39
|
+
|
40
|
+
@extension_type + binary.prefix_uint16_length.prefix_uint16_length
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param binary [String]
|
44
|
+
#
|
45
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
46
|
+
#
|
47
|
+
# @return [TTTLS13::Message::Extensions::SignatureAlgorithms, nil]
|
48
|
+
def self.deserialize(binary)
|
49
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
50
|
+
|
51
|
+
return nil if binary.length < 2
|
52
|
+
|
53
|
+
ssa_len = Convert.bin2i(binary.slice(0, 2))
|
54
|
+
i = 2
|
55
|
+
supported_signature_algorithms = []
|
56
|
+
while i < ssa_len + 2
|
57
|
+
return nil if i + 2 > binary.length
|
58
|
+
|
59
|
+
supported_signature_algorithms << binary.slice(i, 2)
|
60
|
+
i += 2
|
61
|
+
end
|
62
|
+
return nil unless ssa_len + 2 == binary.length
|
63
|
+
|
64
|
+
SignatureAlgorithms.new(supported_signature_algorithms)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module TTTLS13
|
5
|
+
module Message
|
6
|
+
module Extension
|
7
|
+
class SignatureAlgorithmsCert < SignatureAlgorithms
|
8
|
+
# @param versions [Array of SignatureScheme]
|
9
|
+
def initialize(supported_signature_algorithms)
|
10
|
+
super(supported_signature_algorithms)
|
11
|
+
@extension_type = ExtensionType::SIGNATURE_ALGORITHMS_CERT
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param binary [String]
|
15
|
+
#
|
16
|
+
# @return [TTTLS13::Message::Extensions::SignatureAlgorithmsCert]
|
17
|
+
def self.deserialize(binary)
|
18
|
+
extension = SignatureAlgorithms.deserialize(binary)
|
19
|
+
extension.extension_type = ExtensionType::SIGNATURE_ALGORITHMS_CERT
|
20
|
+
extension
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module TTTLS13
|
5
|
+
using Refinements
|
6
|
+
module Message
|
7
|
+
module Extension
|
8
|
+
module CertificateStatusType
|
9
|
+
OCSP = "\x01"
|
10
|
+
end
|
11
|
+
|
12
|
+
class StatusRequest
|
13
|
+
attr_reader :extension_type
|
14
|
+
attr_reader :responder_id_list
|
15
|
+
attr_reader :request_extensions
|
16
|
+
|
17
|
+
# @param responder_id_list [Array of String]
|
18
|
+
# @param request_extensions [String]
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# StatusRequest.new(
|
22
|
+
# responder_id_list: [],
|
23
|
+
# request_extensions: []
|
24
|
+
# )
|
25
|
+
def initialize(responder_id_list: [], request_extensions: '')
|
26
|
+
@extension_type = ExtensionType::STATUS_REQUEST
|
27
|
+
@responder_id_list = responder_id_list || []
|
28
|
+
@request_extensions = request_extensions || ''
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String]
|
32
|
+
def serialize
|
33
|
+
binary = ''
|
34
|
+
binary += CertificateStatusType::OCSP
|
35
|
+
binary += @responder_id_list.length.to_uint16
|
36
|
+
binary += @responder_id_list.map do |id|
|
37
|
+
id.length.to_uint16 + id
|
38
|
+
end.join
|
39
|
+
binary += @request_extensions.prefix_uint16_length
|
40
|
+
|
41
|
+
@extension_type + binary.prefix_uint16_length
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param binary [String]
|
45
|
+
#
|
46
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
47
|
+
#
|
48
|
+
# @return [TTTLS13::Message::Extension::StatusRequest, nil]
|
49
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
50
|
+
def self.deserialize(binary)
|
51
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
52
|
+
return nil if binary.length < 5 ||
|
53
|
+
binary[0] != CertificateStatusType::OCSP
|
54
|
+
|
55
|
+
ril_len = Convert.bin2i(binary.slice(1, 2))
|
56
|
+
i = 3
|
57
|
+
responder_id_list =
|
58
|
+
deserialize_request_ids(binary.slice(i, ril_len))
|
59
|
+
# unparsable responder_id_list
|
60
|
+
return nil if responder_id_list.nil?
|
61
|
+
|
62
|
+
i += ril_len
|
63
|
+
return nil if i + 2 > binary.length
|
64
|
+
|
65
|
+
re_len = Convert.bin2i(binary.slice(i, 2))
|
66
|
+
i += 2
|
67
|
+
request_extensions = binary.slice(i, re_len)
|
68
|
+
i += re_len
|
69
|
+
return nil unless i == binary.length
|
70
|
+
|
71
|
+
StatusRequest.new(responder_id_list: responder_id_list,
|
72
|
+
request_extensions: request_extensions)
|
73
|
+
end
|
74
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
75
|
+
|
76
|
+
class << self
|
77
|
+
private
|
78
|
+
|
79
|
+
# @param binary [String]
|
80
|
+
#
|
81
|
+
# @raise [TTTLS13::Error::ErrorAlerts]
|
82
|
+
#
|
83
|
+
# @return [Array of String, nil] received unparsable binary, nil
|
84
|
+
def deserialize_request_ids(binary)
|
85
|
+
raise Error::ErrorAlerts, :internal_error if binary.nil?
|
86
|
+
|
87
|
+
i = 0
|
88
|
+
request_ids = []
|
89
|
+
while i < binary.length
|
90
|
+
return nil if i + 2 > binary.length
|
91
|
+
|
92
|
+
id_len = Convert.bin2i(binary.slice(i, 2))
|
93
|
+
i += 2
|
94
|
+
id = binary.slice(i, id_len)
|
95
|
+
request_ids += id
|
96
|
+
i += id_len
|
97
|
+
end
|
98
|
+
return nil if i != binary.length
|
99
|
+
|
100
|
+
request_ids
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|