sslshake 1.3.0 → 1.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37184978da20c58b2649eba4057122bc1bb2b77c785c7af547973fb2b27302e0
4
- data.tar.gz: 3ebe8a2ea46eb69d5d6161ea51afc6593d6a82a2a142d626feb96ed573108f3b
3
+ metadata.gz: 641256e779df0499064eb598aebf58897dc4b9be47c61ec5dc15990a801f3358
4
+ data.tar.gz: 1f92a00e7c0711d9d7329439f3c59081727631c95e5a5166df044990cdb08046
5
5
  SHA512:
6
- metadata.gz: 2722410eeddb50ebd48bd8bce5b2b0cef95b4d7021782c554e218c20f885b7eb8cdc9395da741c5967b4d9e022bf8d489f4ec591cef38bb9a8ef323f589117c3
7
- data.tar.gz: bcda1b5c82930b8f126d24577794d4c33d241b2744613e5826aa9e06a7a25998b9f166ed3203150044f81ce78df7199272afe0fb77de55f8edb4c44db1b7c66b
6
+ metadata.gz: fdca401dc68dd60345f32bcb091bf3df052552cc217d13d537acb3af41d53317146ea30385dc3d93a32dfb6216abdb638f32da5534604d511db0a30acc0da981
7
+ data.tar.gz: 1894127ce300872c215cf2b7c659c1033273fcebef6556fccba8f0496c506ebad06828d71d4d35f519e41ced377b52d2c2df36ec2b90d5a10ca9a83ea4e71dfa
@@ -69,7 +69,6 @@ module SSLShake
69
69
  sprintf('%04x', opts[:servername].length) +
70
70
  opts[:servername].unpack('H*')[0]
71
71
  end
72
-
73
72
  cur_socket.send(ssl.hello(protocol, opts[:ciphers], sni), 0)
74
73
  end
75
74
 
@@ -166,6 +166,12 @@ module SSLShake # rubocop:disable Metrics/ModuleLength
166
166
  '00C4' => 'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256',
167
167
  '00C5' => 'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256',
168
168
  '00FF' => 'TLS_EMPTY_RENEGOTIATION_INFO_SCSV',
169
+ # See https://tools.ietf.org/html/rfc8446#appendix-B.4
170
+ "1301" => "TLS_AES_128_GCM_SHA256",
171
+ "1302" => "TLS_AES_256_GCM_SHA384",
172
+ "1303" => "TLS_CHACHA20_POLY1305_SHA256",
173
+ "1304" => "TLS_AES_128_CCM_SHA256",
174
+ "1305" => "TLS_AES_128_CCM_8_SHA256",
169
175
  'C001' => 'TLS_ECDH_ECDSA_WITH_NULL_SHA',
170
176
  'C002' => 'TLS_ECDH_ECDSA_WITH_RC4_128_SHA',
171
177
  'C003' => 'TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA',
@@ -14,6 +14,16 @@ module SSLShake
14
14
  'tls1.0' => '0301',
15
15
  'tls1.1' => '0302',
16
16
  'tls1.2' => '0303',
17
+ # NOTE(ssd) 2020-03-21: RFC 8446 4.1.2:
18
+ #
19
+ # In TLS 1.3, the client indicates its version preferences in the
20
+ # "supported_versions" extension (Section 4.2.1) and the
21
+ # legacy_version field MUST be set to 0x0303, which is the version
22
+ # number for TLS 1.2. TLS 1.3 ClientHellos are identified as having
23
+ # a legacy_version of 0x0303 and a supported_versions extension
24
+ # present with 0x0304 as the highest version indicated therein.
25
+ #
26
+ 'tls1.3' => '0303',
17
27
  }.freeze
18
28
 
19
29
  CONTENT_TYPES = {
@@ -38,10 +48,54 @@ module SSLShake
38
48
  'Finished' => '20',
39
49
  }.freeze
40
50
 
51
+ ALERT_SEVERITY = {
52
+ "WARNING" => "01",
53
+ "FATAL" => "02"
54
+ }.freeze
55
+
56
+ # https://tools.ietf.org/html/rfc5246#appendix-A.3
57
+ # https://tools.ietf.org/html/rfc8446#appendix-B.2
58
+ ALERT_DESCRIPTIONS = {
59
+ "CLOSE_NOTIFY" => "00",
60
+ "UNEXPECTED_MESSAGE" => "0A",
61
+ "BAD_RECORD_MAC" => "14",
62
+ "DECRYPTION_FAILED_RESERVED" => "15",
63
+ "RECORD_OVERFLOW" => "16",
64
+ "DECOMPRESSION_FAILURE" => "1E",
65
+ "HANDSHAKE_FAILURE" => "28",
66
+ "NO_CERTIFICATE_RESERVED" => "29",
67
+ "BAD_CERTIFICATE" => "2A",
68
+ "UNSUPPORTED_CERTIFICATE" => "2B",
69
+ "CERTIFICATE_REVOKED" => "2C",
70
+ "CERTIFICATE_EXPIRED" => "2D",
71
+ "CERTIFICATE_UNKNOWN" => "2D",
72
+ "ILLEGAL_PARAMETER" => "2E",
73
+ "UNKNOWN_CA" => "2F",
74
+ "ACCESS_DENIED" => "30",
75
+ "DECODE_ERROR" => "31",
76
+ "DECRYPT_ERROR" => "32",
77
+ "EXPORT_RESTRICTION_RESERVED" => "3C",
78
+ "PROTOCOL_VERSION" => "46",
79
+ "INSUFFICIENT_SECURITY" => "47",
80
+ "INTERNAL_ERROR" => "50",
81
+ "USER_CANCELED" => "5A",
82
+ "NO_RENEGOTIATION" => "64",
83
+ "MISSING_EXTENSION" => "6D",
84
+ "UNSUPPORTED_EXTENSION" => "6E",
85
+ "CERTIFICATE_UNOBTAINABLE_RESERVED" => "6F",
86
+ "UNRECOGNIZED_NAME" => "70",
87
+ "BAD_CERTIFICATE_STATUS_RESPONSE" => "71",
88
+ "BAD_CERTIFICATE_HASH_VALUE_RESERVED" => "72",
89
+ "UNKNOWN_PSK_IDENTITY" => "73",
90
+ "CERTIFICATE_REQUIRED" => "74",
91
+ "NO_APPLICATION_PROTOCOL" => "78",
92
+ }.freeze
93
+
41
94
  # https://tools.ietf.org/html/rfc6101#appendix-A.6
42
95
  SSL3_CIPHERS = ::SSLShake::CIPHERS.select { |_, v| v.length == 4 }
43
96
  TLS_CIPHERS = ::SSLShake::CIPHERS.select { |k, _| k.start_with? 'TLS_' }
44
97
  TLS10_CIPHERS = TLS_CIPHERS.select { |_, v| v[0] == '0' && v[1] == '0' }
98
+ TLS13_CIPHERS = TLS_CIPHERS.select { |_, v| v[0] == '1' && v[1] == '3' }
45
99
 
46
100
  # Additional collection of ciphers used by different apps and versions
47
101
  OPENSSL_1_0_2_TLS10_CIPHERS = 'c014c00ac022c021c02000390038003700360088008700860085c00fc00500350084c013c009c01fc01ec01d00330032008000810082008300310030009a0099009800970045004400430042c00ec004002f009600410007c011c0070066c00cc00200050004c012c008c01cc01bc01a001600130010000dc00dc003000a006300150012000f000c006200090065006400140011000e000b00080006000300ff'.freeze
@@ -77,6 +131,26 @@ module SSLShake
77
131
  extensions << '000d00140012040308040401050308050501080606010201' # add signature_algorithms
78
132
  extensions << '000b00020100' # add ec_points_format
79
133
  extensions << '000a000a0008fafa001d00170018' # add elliptic_curve
134
+ when 'tls1.3'
135
+ ciphers = cipher_string(TLS13_CIPHERS, cipher_search)
136
+ (extensions ||= '') << '002b0003020304' # TLSv1.3 Supported Versions extension
137
+ extensions << '000d00140012040308040401050308050501080606010201' # add signature_algorithms
138
+ extensions << '000a00080006001d00170018' # Supported Groups extension
139
+ # This is a pre-generated public/private key pair using the x25519 curve:
140
+ # It was generated from the command line with:
141
+ #
142
+ # > openssl-1.1.1e/apps/openssl genpkey -algorithm x25519 > pkey
143
+ # > openssl-1.1.1e/apps/openssl pkey -noout -text < pkey
144
+ # priv:
145
+ # 30:90:f3:89:f4:9e:52:59:3c:ba:e9:f4:78:84:a0:
146
+ # 23:86:73:5e:f5:c9:46:6c:3a:c3:4e:ec:56:57:81:
147
+ # 5d:62
148
+ # pub:
149
+ # e7:08:71:36:d0:81:e0:16:19:3a:cb:67:ca:b8:28:
150
+ # d9:45:92:16:ff:36:63:0d:0d:5a:3d:9d:47:ce:3e:
151
+ # cd:7e
152
+ public_key= 'e7087136d081e016193acb67cab828d9459216ff36630d0d5a3d9d47ce3ecd7e'
153
+ extensions << '003300260024001d0020' + public_key
80
154
  else
81
155
  fail UserError, "This version is not supported: #{version.inspect}"
82
156
  end
@@ -85,10 +159,17 @@ module SSLShake
85
159
 
86
160
  def parse_hello(socket, opts) # rubocop:disable Meterics/AbcSize
87
161
  raw = socket_read(socket, 5, opts[:timeout], opts[:retries])
88
- .unpack('H*')[0].upcase.scan(/../)
162
+ .unpack('H*')[0].upcase.scan(/../)
89
163
  type = raw.shift
90
164
  if type == CONTENT_TYPES['Alert']
91
- return { 'error' => 'SSL Alert.' }
165
+ raw.shift(2) # Shift off version
166
+ len = raw.shift(2).join.to_i(16)
167
+ raw_alert = socket_read(socket, len, opts[:timeout], opts[:retries])
168
+ .unpack('H*')[0].upcase.scan(/../)
169
+ severity = ALERT_SEVERITY.key(raw_alert.shift)
170
+ desc_raw = raw_alert.shift
171
+ description = ALERT_DESCRIPTIONS.key(desc_raw)
172
+ return { 'error' => "SSL Alert: #{severity} #{description || desc_raw}" }
92
173
  end
93
174
  unless type == CONTENT_TYPES['Handshake']
94
175
  return { 'error' => 'Failed to parse response. It is not an SSL handshake.' }
@@ -119,9 +200,24 @@ module SSLShake
119
200
  end
120
201
  res['cipher_suite'] = ciphers.key(raw.shift(2).join(''))
121
202
  res['compression_method'] = raw.shift
203
+
204
+ #
205
+ # TLS 1.3 pretends to be TLS 1.2 in the preceeding headers for
206
+ # compatibility. To correctly identify it, we have to look at
207
+ # any Supported Versions extensions that the server sent us.
208
+ #
209
+ all_ext_len = raw.shift(2).join.to_i(16)
210
+ all_ext_data = raw.shift(all_ext_len)
211
+ while all_ext_data.length > 0
212
+ ext_type = all_ext_data.shift(2).join
213
+ ext_len = all_ext_data.shift(2).join.to_i(16)
214
+ ext_data = all_ext_data.shift(ext_len)
215
+ if ext_type == '002B' && ext_data.join == '0304' # Supported Versions
216
+ res['version'] = 'tls1.3'
217
+ end
218
+ end
122
219
  res['success'] = true
123
220
  res['success'] = (res['version'] == opts[:protocol]) unless opts[:protocol].nil?
124
-
125
221
  res
126
222
  rescue SystemCallError, Alert => _
127
223
  return { 'error' => 'Failed to parse response. The connection was terminated.' }
@@ -3,5 +3,5 @@
3
3
  # license: MPLv2
4
4
 
5
5
  module SSLShake
6
- VERSION = '1.3.0'.freeze
6
+ VERSION = '1.3.1'.freeze
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sslshake
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-21 00:00:00.000000000 Z
11
+ date: 2020-06-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This is a library to simulate SSL and TLS handshake from SSLv2, SSLv3,
14
14
  to TLS 1.0-1.2. It does not rely on OpenSSL and is not designed as a replacement
@@ -37,7 +37,7 @@ homepage: https://github.com/arlimus/sslshake
37
37
  licenses:
38
38
  - MPL-2.0
39
39
  metadata: {}
40
- post_install_message:
40
+ post_install_message:
41
41
  rdoc_options: []
42
42
  require_paths:
43
43
  - lib
@@ -52,9 +52,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
54
  requirements: []
55
- rubyforge_project:
56
- rubygems_version: 2.7.7
57
- signing_key:
55
+ rubygems_version: 3.1.3
56
+ signing_key:
58
57
  specification_version: 4
59
58
  summary: Ruby library for pure SSL/TLS handshake testing.
60
59
  test_files: []