tttls1.3 0.2.2 → 0.2.3

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: 356ce310f2323bede1cdfd21f6c18050d2ce9aca6da4c8ed67b439b597c92ba0
4
- data.tar.gz: d1bcb99ae830df4c8c40688d85e5c7efcda76e0c608ef0707b5201862a5baff8
3
+ metadata.gz: 9b99157535ca4f2b06f4fc6d374116fbc6e496a7807184c56b31be11852d6e5f
4
+ data.tar.gz: 33ff8b94d80529bcabd7c4b3d8fe5ea9ee6513d1d90f4efe307f4edf7bbfb1ac
5
5
  SHA512:
6
- metadata.gz: ae23baf431d2908aceae8e411deb2b8ebf33f8696e67602081c3f07b2d9dad523f8a21a251d5333243e2f44405e8efa0e6595e0af7a744c9fda05c026a824346
7
- data.tar.gz: '0978b73204cc49a3fac033904c98c17eb05f45a2793a5f326298414db09599d065ab599ce34e4cc73bbd928abed9cb988a35ef7248ec9af1ff8a121f6378da61'
6
+ metadata.gz: 29f4cd4e505e33ef0b6f03265a3ecdc8e988a32a965a9079b8c92ee57e50a6ad7e7864fb24d07a14b0ec956fce6ce1c85d9d8072e908e202393c1bd73ad54c1f
7
+ data.tar.gz: c5ed00504bbdb7ee0b051a3534ab2c51bbfdbadbd703ca761fb06367b85798217b04ba7b7d1a8003aeff756d3e9b8e7b6f7c375872250de4139e7400760608d4
data/.travis.yml CHANGED
@@ -1,8 +1,14 @@
1
1
  sudo: false
2
+
2
3
  language: ruby
4
+
3
5
  rvm:
4
6
  - 2.6.1
7
+ - 2.6.2
8
+ - 2.6.3
9
+
5
10
  before_install:
6
11
  - gem install bundler -v 2.0.1
7
12
  - bundle install
13
+
8
14
  script: bundle exec rake
data/Rakefile CHANGED
@@ -128,4 +128,18 @@ end
128
128
 
129
129
  RuboCop::RakeTask.new
130
130
  RSpec::Core::RakeTask.new(:spec)
131
+
132
+ desc 'interoperability test: TTTLS13::Client'
133
+ RSpec::Core::RakeTask.new(:interop_client) do |t|
134
+ t.pattern = Dir.glob('interop/client_spec.rb')
135
+ end
136
+
137
+ desc 'interoperability test: TTTLS13::Server'
138
+ RSpec::Core::RakeTask.new(:interop_server) do |t|
139
+ t.pattern = Dir.glob('interop/server_spec.rb')
140
+ end
141
+
142
+ desc 'interoperability test between openssl'
143
+ task interop: %i[interop_client interop_server]
144
+
131
145
  task default: %i[rubocop spec]
data/interop/Dockerfile CHANGED
@@ -1,6 +1,6 @@
1
1
  FROM ubuntu:18.04
2
2
 
3
- ARG version="1.1.1b"
3
+ ARG version="1.1.1c"
4
4
 
5
5
  RUN apt-get update && apt-get install -y --no-install-recommends \
6
6
  autoconf \
@@ -4,6 +4,7 @@
4
4
  require_relative 'helper'
5
5
 
6
6
  FIXTURES_DIR = __dir__ + '/../spec/fixtures'
7
+ PORT = 4433
7
8
 
8
9
  RSpec.describe Client do
9
10
  # testcases
@@ -147,28 +148,37 @@ RSpec.describe Client do
147
148
  'rsa_rsa.crt',
148
149
  'rsa_rsa.key',
149
150
  key_share_groups: []
151
+ ],
152
+ [
153
+ true,
154
+ '-alpn http/1.1',
155
+ 'rsa_rsa.crt',
156
+ 'rsa_rsa.key',
157
+ alpn: ['http/1.1']
150
158
  ]
151
159
  # rubocop: enable Metrics/LineLength
152
160
  ].each do |normal, opt, crt, key, settings|
153
161
  context 'client interop' do
154
162
  before do
155
- cmd = "docker run -v #{FIXTURES_DIR}:/tmp -p 4433:4433 -it openssl " \
156
- + 'openssl s_server ' \
163
+ cmd = 'openssl s_server ' \
157
164
  + "-cert /tmp/#{crt} " \
158
165
  + "-key /tmp/#{key} " \
159
166
  + '-tls1_3 ' \
160
167
  + '-www ' \
161
168
  + '-quiet ' \
162
169
  + opt
163
- pid = spawn(cmd)
170
+ pid = spawn('docker run ' \
171
+ + "--volume #{FIXTURES_DIR}:/tmp " \
172
+ + "--publish #{PORT}:#{PORT} " \
173
+ + 'openssl ' + cmd)
164
174
  Process.detach(pid)
165
175
 
166
- sleep(2.5) # waiting for openssl s_server
176
+ wait_to_listen(PORT)
167
177
  end
168
178
 
169
179
  let(:client) do
170
180
  hostname = 'localhost'
171
- @socket = TCPSocket.new(hostname, 4433)
181
+ @socket = TCPSocket.new(hostname, PORT)
172
182
  settings[:ca_file] = FIXTURES_DIR + '/rsa_ca.crt'
173
183
  Client.new(@socket, hostname, settings)
174
184
  end
data/interop/helper.rb CHANGED
@@ -11,3 +11,7 @@ include TTTLS13::SignatureScheme
11
11
  include TTTLS13::Message::Extension
12
12
  include TTTLS13::Error
13
13
  # rubocop: enable Style/MixinUsage
14
+
15
+ def wait_to_listen(port)
16
+ sleep(0.2) while `lsof -ni :#{port}`.empty?
17
+ end
@@ -4,7 +4,9 @@
4
4
  require_relative 'helper'
5
5
 
6
6
  FIXTURES_DIR = __dir__ + '/../spec/fixtures'
7
- tcpserver = TCPServer.open(4433)
7
+ PORT = 4433
8
+
9
+ tcpserver = TCPServer.open(PORT)
8
10
 
9
11
  RSpec.describe Server do
10
12
  # testcases
@@ -141,6 +143,20 @@ RSpec.describe Server do
141
143
  FIXTURES_DIR + '/rsa_rsa.crt',
142
144
  FIXTURES_DIR + '/rsa_rsa.key',
143
145
  {}
146
+ ],
147
+ [
148
+ true,
149
+ '-groups P-256:P-384:P-521 -alpn http/1.1',
150
+ FIXTURES_DIR + '/rsa_rsa.crt',
151
+ FIXTURES_DIR + '/rsa_rsa.key',
152
+ alpn: 'http/1.1'
153
+ ],
154
+ [
155
+ false,
156
+ '-groups P-256:P-384:P-521 -alpn foo',
157
+ FIXTURES_DIR + '/rsa_rsa.crt',
158
+ FIXTURES_DIR + '/rsa_rsa.key',
159
+ alpn: 'http/1.1'
144
160
  ]
145
161
  # rubocop: enable Metrics/LineLength
146
162
  ].each do |normal, opt, crt, key, settings|
@@ -153,15 +169,18 @@ RSpec.describe Server do
153
169
  end
154
170
 
155
171
  let(:client) do
172
+ wait_to_listen(PORT)
173
+
156
174
  ip = Socket.ip_address_list.find(&:ipv4_private?).ip_address
157
175
  cmd = 'echo -n ping | openssl s_client ' \
158
- + '-connect local:4433 ' \
176
+ + "-connect local:#{PORT} " \
159
177
  + '-tls1_3 ' \
160
178
  + '-CAfile /tmp/rsa_ca.crt ' \
161
179
  + '-servername localhost ' \
162
180
  + '-quiet ' \
163
181
  + opt
164
- "docker run -v #{FIXTURES_DIR}:/tmp " \
182
+ 'docker run ' \
183
+ + "--volume #{FIXTURES_DIR}:/tmp " \
165
184
  + "--add-host=local:#{ip} -it openssl " \
166
185
  + "sh -c \"#{cmd}\" 2>&1 >/dev/null"
167
186
  end
@@ -173,7 +192,7 @@ RSpec.describe Server do
173
192
 
174
193
  if normal
175
194
  it "should accept request from openssl s_client ...#{opt}" do
176
- spawn('sleep 2; ' + client)
195
+ spawn(client)
177
196
  expect { server.accept }.to_not raise_error
178
197
  expect(server.read).to include 'ping'
179
198
  expect { server.write('pong') }.to_not raise_error
@@ -181,7 +200,7 @@ RSpec.describe Server do
181
200
  end
182
201
  else # exceptions scenarios
183
202
  it "should NOT accept request from openssl s_client ...#{opt}" do
184
- spawn('sleep 2; ' + client)
203
+ spawn(client)
185
204
  expect { server.accept }.to raise_error ErrorAlerts
186
205
  end
187
206
  end
@@ -50,6 +50,7 @@ module TTTLS13
50
50
  signature_algorithms_cert: nil,
51
51
  supported_groups: DEFAULT_CH_NAMED_GROUP_LIST,
52
52
  key_share_groups: nil,
53
+ alpn: nil,
53
54
  process_new_session_ticket: nil,
54
55
  ticket: nil,
55
56
  resumption_master_secret: nil,
@@ -280,6 +281,10 @@ module TTTLS13
280
281
  @succeed_early_data = true \
281
282
  if ee.extensions.include?(Message::ExtensionType::EARLY_DATA)
282
283
 
284
+ @alpn = ee.extensions[
285
+ Message::ExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION
286
+ ]&.protocol_name_list&.first
287
+
283
288
  @state = ClientState::WAIT_CERT_CR
284
289
  @state = ClientState::WAIT_FINISHED unless psk.nil?
285
290
  when ClientState::WAIT_CERT_CR
@@ -397,6 +402,11 @@ module TTTLS13
397
402
  @succeed_early_data
398
403
  end
399
404
 
405
+ # @return [String]
406
+ def negotiated_alpn
407
+ @alpn
408
+ end
409
+
400
410
  private
401
411
 
402
412
  # @return [Boolean]
@@ -471,6 +481,8 @@ module TTTLS13
471
481
 
472
482
  # @return [TTTLS13::Message::Extensions]
473
483
  # @return [Hash of NamedGroup => OpenSSL::PKey::EC.$Object]
484
+ # rubocop: disable Metrics/AbcSize
485
+ # rubocop: disable Metrics/CyclomaticComplexity
474
486
  def gen_ch_extensions
475
487
  exs = []
476
488
  # supported_versions: only TLS 1.3
@@ -507,8 +519,14 @@ module TTTLS13
507
519
  # early_data
508
520
  exs << Message::Extension::EarlyDataIndication.new if use_early_data?
509
521
 
522
+ # alpn
523
+ exs << Message::Extension::Alpn.new(@settings[:alpn].reject(&:empty?)) \
524
+ if !@settings[:alpn].nil? && !@settings[:alpn].empty?
525
+
510
526
  [Message::Extensions.new(exs), priv_keys]
511
527
  end
528
+ # rubocop: enable Metrics/AbcSize
529
+ # rubocop: enable Metrics/CyclomaticComplexity
512
530
 
513
531
  # @param extensions [TTTLS13::Message::Extensions]
514
532
  # @param binder_key [String, nil]
@@ -50,6 +50,7 @@ module TTTLS13
50
50
  cipher_suites: DEFAULT_SP_CIPHER_SUITES,
51
51
  signature_algorithms: DEFAULT_SP_SIGNATURE_ALGORITHMS,
52
52
  supported_groups: DEFAULT_SP_NAMED_GROUP_LIST,
53
+ alpn: nil,
53
54
  loglevel: Logger::WARN
54
55
  }.freeze
55
56
  private_constant :DEFAULT_SERVER_SETTINGS
@@ -151,6 +152,16 @@ module TTTLS13
151
152
  terminate(:illegal_parameter) unless ch.valid_key_share?
152
153
  terminate(:unrecognized_name) unless recognized_server_name?(ch, @crt)
153
154
 
155
+ # alpn
156
+ if !@settings[:alpn].nil? && !@settings[:alpn].empty?
157
+ pnl = ch.extensions[
158
+ Message::ExtensionType::APPLICATION_LAYER_PROTOCOL_NEGOTIATION
159
+ ]&.protocol_name_list || []
160
+ @alpn = pnl.find { |p| @settings[:alpn].include?(p) }
161
+
162
+ terminate(:no_application_protocol) if @alpn.nil?
163
+ end
164
+
154
165
  @state = ServerState::RECVD_CH
155
166
  when ServerState::RECVD_CH
156
167
  logger.debug('ServerState::RECVD_CH')
@@ -209,7 +220,7 @@ module TTTLS13
209
220
  logger.debug('ServerState::WAIT_FLIGHT2')
210
221
 
211
222
  ch = transcript[CH]
212
- ee = transcript[EE] = gen_encrypted_extensions(ch)
223
+ ee = transcript[EE] = gen_encrypted_extensions(ch, @alpn)
213
224
  # TODO: [Send CertificateRequest]
214
225
  ct = transcript[CT] = gen_certificate(@crt)
215
226
  digest = CipherSuite.digest(@cipher_suite)
@@ -335,9 +346,9 @@ module TTTLS13
335
346
  ksg = sp_groups.find do |g|
336
347
  !ks_groups.include?(g) && @settings[:supported_groups].include?(g)
337
348
  end
349
+ exs << Message::Extension::KeyShare.gen_hrr_key_share(ksg)
338
350
 
339
351
  # TODO: cookie
340
- exs << Message::Extension::KeyShare.gen_hrr_key_share(ksg)
341
352
 
342
353
  sh = Message::ServerHello.new(
343
354
  random: Message::HRR_RANDOM,
@@ -363,10 +374,11 @@ module TTTLS13
363
374
  end
364
375
 
365
376
  # @param ch [TTTLS13::Message::ClientHello]
377
+ # @param alpn [String]
366
378
  #
367
379
  # @return [TTTLS13::Message::EncryptedExtensions]
368
- def gen_encrypted_extensions(ch)
369
- Message::EncryptedExtensions.new(gen_ee_extensions(ch))
380
+ def gen_encrypted_extensions(ch, alpn = nil)
381
+ Message::EncryptedExtensions.new(gen_ee_extensions(ch, alpn))
370
382
  end
371
383
 
372
384
  # @param crt [OpenSSL::X509::Certificate]
@@ -424,9 +436,10 @@ module TTTLS13
424
436
  end
425
437
 
426
438
  # @param ch [TTTLS13::Message::ClientHello]
439
+ # @param alpn [String]
427
440
  #
428
441
  # @return [TTTLS13::Message::Extensions]
429
- def gen_ee_extensions(ch)
442
+ def gen_ee_extensions(ch, alpn)
430
443
  exs = []
431
444
 
432
445
  # server_name
@@ -437,6 +450,9 @@ module TTTLS13
437
450
  exs \
438
451
  << Message::Extension::SupportedGroups.new(@settings[:supported_groups])
439
452
 
453
+ # alpn
454
+ exs << Message::Extension::Alpn.new([alpn]) unless alpn.nil?
455
+
440
456
  Message::Extensions.new(exs)
441
457
  end
442
458
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTTLS13
4
- VERSION = '0.2.2'
4
+ VERSION = '0.2.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tttls1.3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - thekuwayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-29 00:00:00.000000000 Z
11
+ date: 2019-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler