tttls1.3 0.1.4 → 0.2.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.
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