tttls1.3 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/README.md +35 -13
  4. data/Rakefile +2 -4
  5. data/example/helper.rb +30 -7
  6. data/example/https_client.rb +3 -20
  7. data/example/https_client_using_0rtt.rb +10 -24
  8. data/example/https_client_using_hrr.rb +3 -20
  9. data/example/https_client_using_ticket.rb +3 -20
  10. data/example/https_server.rb +43 -0
  11. data/interop/client_spec.rb +111 -22
  12. data/interop/helper.rb +1 -0
  13. data/interop/server_spec.rb +182 -0
  14. data/lib/tttls1.3/client.rb +115 -98
  15. data/lib/tttls1.3/connection.rb +119 -32
  16. data/lib/tttls1.3/message/certificate.rb +18 -0
  17. data/lib/tttls1.3/message/client_hello.rb +38 -0
  18. data/lib/tttls1.3/message/encrypted_extensions.rb +20 -16
  19. data/lib/tttls1.3/message/extension/key_share.rb +24 -2
  20. data/lib/tttls1.3/message/extension/supported_groups.rb +0 -87
  21. data/lib/tttls1.3/message/extensions.rb +1 -27
  22. data/lib/tttls1.3/message/new_session_ticket.rb +14 -0
  23. data/lib/tttls1.3/message/record.rb +23 -20
  24. data/lib/tttls1.3/message/server_hello.rb +27 -0
  25. data/lib/tttls1.3/message.rb +35 -2
  26. data/lib/tttls1.3/named_group.rb +89 -0
  27. data/lib/tttls1.3/server.rb +439 -0
  28. data/lib/tttls1.3/transcript.rb +6 -0
  29. data/lib/tttls1.3/version.rb +1 -1
  30. data/lib/tttls1.3.rb +3 -0
  31. data/spec/certificate_spec.rb +28 -1
  32. data/spec/client_spec.rb +14 -10
  33. data/spec/connection_spec.rb +43 -13
  34. data/spec/encrypted_extensions_spec.rb +4 -4
  35. data/spec/fixtures/rsa_ca.crt +29 -0
  36. data/spec/fixtures/rsa_ca.key +51 -0
  37. data/spec/fixtures/rsa_rsa.crt +23 -0
  38. data/spec/fixtures/rsa_rsa.key +27 -0
  39. data/spec/fixtures/rsa_secp256r1.crt +19 -0
  40. data/spec/fixtures/rsa_secp256r1.key +5 -0
  41. data/spec/fixtures/rsa_secp384r1.crt +19 -0
  42. data/spec/fixtures/rsa_secp384r1.key +6 -0
  43. data/spec/fixtures/rsa_secp521r1.crt +20 -0
  44. data/spec/fixtures/rsa_secp521r1.key +7 -0
  45. data/spec/server_spec.rb +186 -0
  46. data/spec/spec_helper.rb +43 -0
  47. metadata +28 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5e95ca87bc146cc9021a42dc44ed5daef30a5d8fc7040ab4531c77045077e82
4
- data.tar.gz: cae31fb5ec83ac405142d7c67b1b9298d2d0880dbd053e37e7edfd888e70cf9e
3
+ metadata.gz: 39cf5b4e5fd508981bdefedc27502ac14b984699983d44160d9a836b2ab2aa2b
4
+ data.tar.gz: 0250c8ad97ef5bef6a52d7b6e22c990b842ce66a8ab6e2d3abc0c6ef90a4eb13
5
5
  SHA512:
6
- metadata.gz: 32080b68a237890982c9407491e754df789460550e7b68a87d1f77a01749da79a7bc463dbb8b53659eb27aa1fc990e168454754fc7b1636ac474e43c61fecd1f
7
- data.tar.gz: 5a43785680db1cda38f704ac0df711ff10c0d2cded4fc2620c7c5ad8ee15d4f682672983642ce50f4b371cddd93760d06d98839d6c7811323482add07fe7fbc9
6
+ metadata.gz: e8ef15683ceabb9396eb51e5831f3dc48ed9c4df11871f10458160804891107fe3bff2d0c1810ad294134c8bec4d63534b2aee7cc6c8bff5f7ae07462bf753ef
7
+ data.tar.gz: 7baf720c22742962380449ad01372264634e878113858643cdc8a0db55e0f0cf07e0bd45cd80ad461cab9a337c89c7e0ad9c0e0057e02cbcda77a0765f10bdb9
data/.rubocop.yml CHANGED
@@ -10,6 +10,9 @@ Metrics/AbcSize:
10
10
  Metrics/MethodLength:
11
11
  Max: 30
12
12
 
13
+ Naming/UncommunicativeMethodParamName:
14
+ MinNameLength: 1
15
+
13
16
  Metrics/BlockLength:
14
17
  Exclude:
15
18
  - 'Rakefile'
data/README.md CHANGED
@@ -12,29 +12,18 @@ Backward compatibility and performance are not an objective.
12
12
  This gem should not be used for production software.
13
13
 
14
14
 
15
- ## Features
16
-
17
- tttls1.3 provides client API with the following features:
18
-
19
- * Simple 1-RTT Handshake
20
- * HelloRetryRequest
21
- * Resumed 0-RTT Handshake (with PSK from ticket)
22
-
23
- NOT supports X25519, X448, FFDHE, AES-CCM, Client Authentication, Post-Handshake Authentication, KeyUpdate, external PSKs.
24
-
25
-
26
15
  ## Getting started
27
16
 
28
17
  tttls1.3 gem is available at [rubygems.org](https://rubygems.org/gems/tttls1.3). You can install with:
29
18
 
30
- ```
19
+ ```bash
31
20
  $ gem install tttls1.3
32
21
  ```
33
22
 
34
23
  This implementation provides only minimal API, so your code is responsible for application layer.
35
24
  Roughly, this works as follows:
36
25
 
37
- ```
26
+ ```ruby
38
27
  require 'tttls1.3'
39
28
 
40
29
  socket = YourTransport.new
@@ -46,9 +35,42 @@ client.read
46
35
  client.close
47
36
  ```
48
37
 
38
+ ```ruby
39
+ require 'tttls1.3'
40
+
41
+ socket = YourTransport.new
42
+ server = TTTLS13::Server.new(socket.accept)
43
+ server.accept
44
+
45
+ server.read
46
+ server.write(YOUR_MESSAGE)
47
+ server.close
48
+ ```
49
+
49
50
  HTTPS examples are [here](https://github.com/thekuwayama/tttls1.3/tree/master/example).
50
51
 
51
52
 
53
+ ## Features
54
+
55
+ ### Client
56
+
57
+ tttls1.3 provides client API with the following features:
58
+
59
+ * Simple 1-RTT Handshake
60
+ * HelloRetryRequest
61
+ * Resumed 0-RTT Handshake (with PSK from ticket)
62
+
63
+ **NOT supports** certificate with OID RSASSA-PSS, X25519, X448, FFDHE, AES-CCM, Client Authentication, Post-Handshake Authentication, KeyUpdate, external PSKs.
64
+
65
+ ### Server
66
+
67
+ tttls1.3 provides server API with the following features:
68
+
69
+ * Simple 1-RTT Handshake
70
+
71
+ **NOT supports** certificate with OID RSASSA-PSS, X25519, X448, FFDHE, AES-CCM, Client Authentication, Post-Handshake Authentication, KeyUpdate, external PSKs.
72
+
73
+
52
74
  ## License
53
75
 
54
76
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -6,8 +6,6 @@ require 'rspec/core/rake_task'
6
6
  require 'openssl'
7
7
  require 'fileutils'
8
8
 
9
- RuboCop::RakeTask.new
10
-
11
9
  TMP_DIR = __dir__ + '/tmp'
12
10
  CA_KEY = TMP_DIR + '/ca.key'
13
11
  CA_CRT = TMP_DIR + '/ca.crt'
@@ -128,6 +126,6 @@ task :del_certs do
128
126
  end
129
127
  end
130
128
 
131
- RSpec::Core::RakeTask.new(spec: :gen_certs)
132
-
129
+ RuboCop::RakeTask.new
130
+ RSpec::Core::RakeTask.new(:spec)
133
131
  task default: %i[rubocop spec]
data/example/helper.rb CHANGED
@@ -4,13 +4,36 @@ $LOAD_PATH << __dir__ + '/../lib'
4
4
 
5
5
  require 'socket'
6
6
  require 'tttls1.3'
7
+ require 'webrick'
8
+
9
+ def simple_http_request(hostname)
10
+ s = <<~BIN
11
+ GET / HTTP/1.1
12
+ Host: #{hostname}
13
+ User-Agent: https_client
14
+ Accept: */*
7
15
 
8
- def http_get(hostname)
9
- <<~BIN
10
- GET / HTTP/1.1\r
11
- Host: #{hostname}\r
12
- User-Agent: https_client\r
13
- Accept: */*\r
14
- \r
15
16
  BIN
17
+ s.gsub("\n", "\r\n")
18
+ end
19
+
20
+ def recv_http_response(client)
21
+ # status line, header
22
+ buf = ''
23
+ buf += client.read until buf.include?(WEBrick::CRLF * 2)
24
+ header = buf.split(WEBrick::CRLF * 2).first
25
+ # header; Content-Length
26
+ cl_line = header.split(WEBrick::CRLF).find { |s| s.match(/Content-Length:/i) }
27
+
28
+ # body
29
+ unless cl_line.nil?
30
+ cl = cl_line.split(':').last.to_i
31
+ buf = buf.split(WEBrick::CRLF * 2)[1..].join
32
+ while buf.length < cl
33
+ s = client.read
34
+ buf += s
35
+ end
36
+ end
37
+
38
+ header + WEBrick::CRLF * 2 + buf
16
39
  end
@@ -4,29 +4,12 @@
4
4
  require_relative 'helper'
5
5
 
6
6
  hostname, port = (ARGV[0] || 'localhost:4433').split(':')
7
- http_get = http_get(hostname)
7
+ req = simple_http_request(hostname)
8
8
 
9
9
  socket = TCPSocket.new(hostname, port)
10
10
  settings = { ca_file: __dir__ + '/../tmp/ca.crt' }
11
11
  client = TTTLS13::Client.new(socket, hostname, settings)
12
12
  client.connect
13
- client.write(http_get)
14
-
15
- # status line, header
16
- buffer = ''
17
- buffer += client.read until buffer.include?("\r\n\r\n")
18
- print header = buffer.split("\r\n\r\n").first
19
- # header; Content-Length
20
- cl_line = header.split("\r\n").find { |s| s.match(/Content-Length:/i) }
21
-
22
- # body
23
- unless cl_line.nil?
24
- cl = cl_line.split(':').last.to_i
25
- print buffer = buffer.split("\r\n\r\n")[1..].join
26
- while buffer.length < cl
27
- print s = client.read
28
- buffer += s
29
- end
30
- end
31
-
13
+ client.write(req)
14
+ print recv_http_response(client)
32
15
  client.close
@@ -4,7 +4,7 @@
4
4
  require_relative 'helper'
5
5
 
6
6
  hostname, port = (ARGV[0] || 'localhost:4433').split(':')
7
- http_get = http_get(hostname)
7
+ req = simple_http_request(hostname)
8
8
 
9
9
  settings_2nd = {
10
10
  ca_file: __dir__ + '/../tmp/ca.crt'
@@ -23,7 +23,9 @@ settings_1st = {
23
23
  ca_file: __dir__ + '/../tmp/ca.crt',
24
24
  process_new_session_ticket: process_new_session_ticket
25
25
  }
26
- accepted_early_data = false
26
+
27
+ succeed_early_data = false
28
+
27
29
  [
28
30
  # Initial Handshake:
29
31
  settings_1st,
@@ -34,31 +36,15 @@ accepted_early_data = false
34
36
  client = TTTLS13::Client.new(socket, hostname, settings)
35
37
 
36
38
  # send message using early data; 0-RTT
37
- client.early_data(http_get) if i == 1 && settings.include?(:ticket)
39
+ client.early_data(req) if i == 1 && settings.include?(:ticket)
38
40
  client.connect
39
41
  # send message after Simple 1-RTT Handshake
40
- client.write(http_get) if i.zero? || !client.accepted_early_data?
41
-
42
- # status line, header
43
- buffer = ''
44
- buffer += client.read until buffer.include?("\r\n\r\n")
45
- print header = buffer.split("\r\n\r\n").first
46
- # header; Content-Length
47
- cl_line = header.split("\r\n").find { |s| s.match(/Content-Length:/i) }
48
-
49
- # body
50
- unless cl_line.nil?
51
- cl = cl_line.split(':').last.to_i
52
- print buffer = buffer.split("\r\n\r\n")[1..].join
53
- while buffer.length < cl
54
- print s = client.read
55
- buffer += s
56
- end
57
- end
58
-
42
+ client.write(req) if i.zero? || !client.succeed_early_data?
43
+ print recv_http_response(client)
59
44
  client.close
60
- accepted_early_data = client.accepted_early_data?
45
+
46
+ succeed_early_data = client.succeed_early_data?
61
47
  end
62
48
 
63
49
  puts "\n" + '-' * 10
64
- puts "early data of 2nd handshake: #{accepted_early_data}"
50
+ puts "early data of 2nd handshake: #{succeed_early_data}"
@@ -4,7 +4,7 @@
4
4
  require_relative 'helper'
5
5
 
6
6
  hostname, port = (ARGV[0] || 'localhost:4433').split(':')
7
- http_get = http_get(hostname)
7
+ req = simple_http_request(hostname)
8
8
 
9
9
  socket = TCPSocket.new(hostname, port)
10
10
  settings = {
@@ -13,23 +13,6 @@ settings = {
13
13
  }
14
14
  client = TTTLS13::Client.new(socket, hostname, settings)
15
15
  client.connect
16
- client.write(http_get)
17
-
18
- # status line, header
19
- buffer = ''
20
- buffer += client.read until buffer.include?("\r\n\r\n")
21
- print header = buffer.split("\r\n\r\n").first
22
- # header; Content-Length
23
- cl_line = header.split("\r\n").find { |s| s.match(/Content-Length:/i) }
24
-
25
- # body
26
- unless cl_line.nil?
27
- cl = cl_line.split(':').last.to_i
28
- print buffer = buffer.split("\r\n\r\n")[1..].join
29
- while buffer.length < cl
30
- print s = client.read
31
- buffer += s
32
- end
33
- end
34
-
16
+ client.write(req)
17
+ print recv_http_response(client)
35
18
  client.close
@@ -4,7 +4,7 @@
4
4
  require_relative 'helper'
5
5
 
6
6
  hostname, port = (ARGV[0] || 'localhost:4433').split(':')
7
- http_get = http_get(hostname)
7
+ req = simple_http_request(hostname)
8
8
 
9
9
  settings_2nd = {
10
10
  ca_file: __dir__ + '/../tmp/ca.crt'
@@ -33,24 +33,7 @@ settings_1st = {
33
33
  socket = TCPSocket.new(hostname, port)
34
34
  client = TTTLS13::Client.new(socket, hostname, settings)
35
35
  client.connect
36
- client.write(http_get)
37
-
38
- # status line, header
39
- buffer = ''
40
- buffer += client.read until buffer.include?("\r\n\r\n")
41
- print header = buffer.split("\r\n\r\n").first
42
- # header; Content-Length
43
- cl_line = header.split("\r\n").find { |s| s.match(/Content-Length:/i) }
44
-
45
- # body
46
- unless cl_line.nil?
47
- cl = cl_line.split(':').last.to_i
48
- print buffer = buffer.split("\r\n\r\n")[1..].join
49
- while buffer.length < cl
50
- print s = client.read
51
- buffer += s
52
- end
53
- end
54
-
36
+ client.write(req)
37
+ print recv_http_response(client)
55
38
  client.close
56
39
  end
@@ -0,0 +1,43 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'helper'
5
+
6
+ port = ARGV[0] || 4433
7
+
8
+ tcpserver = TCPServer.open(port)
9
+ settings = { crt_file: __dir__ + '/../tmp/server.crt',
10
+ key_file: __dir__ + '/../tmp/server.key' }
11
+
12
+ # rubocop: disable Metrics/BlockLength
13
+ loop do
14
+ socket = tcpserver.accept
15
+ Thread.start(socket) do |s|
16
+ Timeout.timeout(5) do
17
+ server = TTTLS13::Server.new(s, settings)
18
+ server.accept
19
+ buffer = ''
20
+ buffer += server.read until buffer.include?(WEBrick::CRLF * 2)
21
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
22
+ req.parse(StringIO.new(buffer))
23
+ puts req.to_s
24
+ res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
25
+ res.status = 200
26
+ res.body = 'Hello'
27
+ res.content_length = 5
28
+ res.content_type = 'text/html'
29
+ server.write(
30
+ res.status_line \
31
+ + res.header.map { |k, v| k + ': ' + v }.join(WEBrick::CRLF) \
32
+ + WEBrick::CRLF * 2 \
33
+ + res.body
34
+ )
35
+ server.close
36
+ end
37
+ rescue Timeout::Error => e
38
+ puts e.to_s + "\n\n"
39
+ ensure
40
+ s.close
41
+ end
42
+ end
43
+ # rubocop: enable Metrics/BlockLength
@@ -3,61 +3,144 @@
3
3
 
4
4
  require_relative 'helper'
5
5
 
6
- TMP_DIR = __dir__ + '/../tmp'
6
+ FIXTURES_DIR = __dir__ + '/../spec/fixtures'
7
7
 
8
8
  RSpec.describe Client do
9
9
  # testcases
10
+ # normal [Boolean] Is this nominal scenarios?
11
+ # opt [String] openssl s_server options
12
+ # crt [String] server crt file path
13
+ # key [String] server key file path
14
+ # settings [Hash] TTTLS13::Server settings
10
15
  [
16
+ # rubocop: disable Metrics/LineLength
11
17
  [
12
- ' -ciphersuites TLS_AES_256_GCM_SHA384',
18
+ true,
19
+ '-ciphersuites TLS_AES_256_GCM_SHA384',
20
+ 'rsa_rsa.crt',
21
+ 'rsa_rsa.key',
13
22
  cipher_suites: [CipherSuite::TLS_AES_256_GCM_SHA384]
14
23
  ],
15
24
  [
16
- ' -ciphersuites TLS_CHACHA20_POLY1305_SHA256',
25
+ true,
26
+ '-ciphersuites TLS_CHACHA20_POLY1305_SHA256',
27
+ 'rsa_rsa.crt',
28
+ 'rsa_rsa.key',
17
29
  cipher_suites: [CipherSuite::TLS_CHACHA20_POLY1305_SHA256]
18
30
  ],
19
31
  [
20
- ' -ciphersuites TLS_AES_128_GCM_SHA256',
32
+ true,
33
+ '-ciphersuites TLS_AES_128_GCM_SHA256',
34
+ 'rsa_rsa.crt',
35
+ 'rsa_rsa.key',
21
36
  cipher_suites: [CipherSuite::TLS_AES_128_GCM_SHA256]
22
37
  ],
23
38
  [
24
- ' -groups P-256',
39
+ false,
40
+ '-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256',
41
+ 'rsa_rsa.crt',
42
+ 'rsa_rsa.key',
43
+ cipher_suites: [CipherSuite::TLS_AES_128_GCM_SHA256]
44
+ ],
45
+ [
46
+ true,
47
+ '-groups P-256',
48
+ 'rsa_rsa.crt',
49
+ 'rsa_rsa.key',
25
50
  supported_groups: [NamedGroup::SECP256R1]
26
51
  ],
27
52
  [
28
- ' -groups P-384',
53
+ true,
54
+ '-groups P-384',
55
+ 'rsa_rsa.crt',
56
+ 'rsa_rsa.key',
29
57
  supported_groups: [NamedGroup::SECP384R1]
30
58
  ],
31
59
  [
32
- ' -groups P-521',
60
+ true,
61
+ '-groups P-521',
62
+ 'rsa_rsa.crt',
63
+ 'rsa_rsa.key',
33
64
  supported_groups: [NamedGroup::SECP521R1]
34
65
  ],
35
66
  [
36
- ' -sigalgs RSA-PSS+SHA256',
67
+ false,
68
+ '-groups P-256:P-384',
69
+ 'rsa_rsa.crt',
70
+ 'rsa_rsa.key',
71
+ supported_groups: [NamedGroup::SECP521R1]
72
+ ],
73
+ [
74
+ true,
75
+ '-sigalgs RSA-PSS+SHA256',
76
+ 'rsa_rsa.crt',
77
+ 'rsa_rsa.key',
37
78
  signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
38
79
  signature_algorithms: [SignatureScheme::RSA_PSS_RSAE_SHA256]
39
80
  ],
40
81
  [
41
- ' -sigalgs RSA-PSS+SHA384',
82
+ true,
83
+ '-sigalgs RSA-PSS+SHA384',
84
+ 'rsa_rsa.crt',
85
+ 'rsa_rsa.key',
42
86
  signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
43
87
  signature_algorithms: [SignatureScheme::RSA_PSS_RSAE_SHA384]
44
88
  ],
45
89
  [
46
- ' -sigalgs RSA-PSS+SHA512',
90
+ true,
91
+ '-sigalgs RSA-PSS+SHA512',
92
+ 'rsa_rsa.crt',
93
+ 'rsa_rsa.key',
47
94
  signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
48
95
  signature_algorithms: [SignatureScheme::RSA_PSS_RSAE_SHA512]
49
96
  ],
50
97
  [
51
- ' -record_padding 8446',
98
+ true,
99
+ '-sigalgs ECDSA+SHA256',
100
+ 'rsa_secp256r1.crt',
101
+ 'rsa_secp256r1.key',
102
+ signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
103
+ signature_algorithms: [SignatureScheme::ECDSA_SECP256R1_SHA256]
104
+ ],
105
+ [
106
+ true,
107
+ '-sigalgs ECDSA+SHA384',
108
+ 'rsa_secp384r1.crt',
109
+ 'rsa_secp384r1.key',
110
+ signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
111
+ signature_algorithms: [SignatureScheme::ECDSA_SECP384R1_SHA384]
112
+ ],
113
+ [
114
+ true,
115
+ '-sigalgs ECDSA+SHA512',
116
+ 'rsa_secp521r1.crt',
117
+ 'rsa_secp521r1.key',
118
+ signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
119
+ signature_algorithms: [SignatureScheme::ECDSA_SECP521R1_SHA512]
120
+ ],
121
+ [
122
+ false,
123
+ '-sigalgs ECDSA+SHA256:ECDSA+SHA384:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256',
124
+ 'rsa_secp521r1.crt',
125
+ 'rsa_secp521r1.key',
126
+ signature_algorithms_cert: [SignatureScheme::RSA_PKCS1_SHA256],
127
+ signature_algorithms: [SignatureScheme::ECDSA_SECP521R1_SHA512]
128
+ ],
129
+ [
130
+ true,
131
+ '-record_padding 8446',
132
+ 'rsa_rsa.crt',
133
+ 'rsa_rsa.key',
52
134
  {}
53
135
  ]
54
- ].each do |opt, settings|
136
+ # rubocop: enable Metrics/LineLength
137
+ ].each do |normal, opt, crt, key, settings|
55
138
  context 'client interop' do
56
139
  before do
57
- cmd = "docker run -v #{TMP_DIR}:/tmp -p 4433:4433 -it openssl " \
140
+ cmd = "docker run -v #{FIXTURES_DIR}:/tmp -p 4433:4433 -it openssl " \
58
141
  + 'openssl s_server ' \
59
- + '-cert /tmp/server.crt ' \
60
- + '-key /tmp/server.key ' \
142
+ + "-cert /tmp/#{crt} " \
143
+ + "-key /tmp/#{key} " \
61
144
  + '-tls1_3 ' \
62
145
  + '-www ' \
63
146
  + '-quiet ' \
@@ -65,13 +148,13 @@ RSpec.describe Client do
65
148
  pid = spawn(cmd)
66
149
  Process.detach(pid)
67
150
 
68
- sleep(2) # waiting for openssl s_server
151
+ sleep(2.5) # waiting for openssl s_server
69
152
  end
70
153
 
71
154
  let(:client) do
72
155
  hostname = 'localhost'
73
156
  @socket = TCPSocket.new(hostname, 4433)
74
- settings[:ca_file] = TMP_DIR + '/ca.crt'
157
+ settings[:ca_file] = FIXTURES_DIR + '/rsa_ca.crt'
75
158
  Client.new(@socket, hostname, settings)
76
159
  end
77
160
 
@@ -80,11 +163,17 @@ RSpec.describe Client do
80
163
  `docker ps -ql | xargs docker stop`
81
164
  end
82
165
 
83
- it "should connect with openssl s_server ...#{opt}" do
84
- expect { client.connect }.to_not raise_error
85
- expect { client.write("GET / HTTP/1.0\r\n\r\n") }.to_not raise_error
86
- expect(client.read).to include "HTTP/1.0 200 ok\r\n"
87
- expect { client.close }.to_not raise_error
166
+ if normal
167
+ it "should connect with openssl s_server ...#{opt}" do
168
+ expect { client.connect }.to_not raise_error
169
+ expect { client.write("GET / HTTP/1.0\r\n\r\n") }.to_not raise_error
170
+ expect(client.read).to include "HTTP/1.0 200 ok\r\n"
171
+ expect { client.close }.to_not raise_error
172
+ end
173
+ else # exceptions scenarios
174
+ it "should NOT connect with openssl s_server ...#{opt}" do
175
+ expect { client.connect }.to raise_error ErrorAlerts
176
+ end
88
177
  end
89
178
  end
90
179
  end
data/interop/helper.rb CHANGED
@@ -9,4 +9,5 @@ include TTTLS13
9
9
  include TTTLS13::CipherSuite
10
10
  include TTTLS13::SignatureScheme
11
11
  include TTTLS13::Message::Extension
12
+ include TTTLS13::Error
12
13
  # rubocop: enable Style/MixinUsage