codtls 0.0.1.alpha

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 (48) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +12 -0
  3. data/.yardopts +4 -0
  4. data/Gemfile +12 -0
  5. data/LICENSE +21 -0
  6. data/README.md +78 -0
  7. data/Rakefile +29 -0
  8. data/lib/codtls.rb +186 -0
  9. data/lib/codtls/abstract_session.rb +179 -0
  10. data/lib/codtls/alert.rb +64 -0
  11. data/lib/codtls/decrypt.rb +72 -0
  12. data/lib/codtls/ecc.rb +26 -0
  13. data/lib/codtls/encrypt.rb +29 -0
  14. data/lib/codtls/h_changecipherspec.rb +25 -0
  15. data/lib/codtls/h_chello.rb +79 -0
  16. data/lib/codtls/h_content.rb +57 -0
  17. data/lib/codtls/h_finished.rb +30 -0
  18. data/lib/codtls/h_keyexchange.rb +131 -0
  19. data/lib/codtls/h_shello.rb +51 -0
  20. data/lib/codtls/h_shellodone.rb +22 -0
  21. data/lib/codtls/h_type.rb +22 -0
  22. data/lib/codtls/h_verify.rb +30 -0
  23. data/lib/codtls/handshake.rb +173 -0
  24. data/lib/codtls/models/codtls_connection.rb +3 -0
  25. data/lib/codtls/models/codtls_device.rb +3 -0
  26. data/lib/codtls/prf.rb +40 -0
  27. data/lib/codtls/pskdb.rb +104 -0
  28. data/lib/codtls/ram_session.rb +214 -0
  29. data/lib/codtls/rampskdb.rb +87 -0
  30. data/lib/codtls/record.rb +202 -0
  31. data/lib/codtls/session.rb +284 -0
  32. data/lib/codtls/version.rb +3 -0
  33. data/lib/generators/codtls/codtls_generator.rb +56 -0
  34. data/lib/generators/codtls/templates/create_codtls_connections.rb +15 -0
  35. data/lib/generators/codtls/templates/create_codtls_devices.rb +11 -0
  36. data/test/test_codtls.rb +75 -0
  37. data/test/test_ecc.rb +44 -0
  38. data/test/test_h_chello.rb +40 -0
  39. data/test/test_h_content.rb +59 -0
  40. data/test/test_h_keyexchange.rb +36 -0
  41. data/test/test_helper.rb +3 -0
  42. data/test/test_pskdb.rb +37 -0
  43. data/test/test_ram_session.rb +131 -0
  44. data/test/test_rampskdb.rb +26 -0
  45. data/test/test_record.rb +128 -0
  46. data/test/test_send_recv.rb +178 -0
  47. data/test/test_session.rb +164 -0
  48. metadata +303 -0
data/test/test_ecc.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'test_helper'
2
+ require 'codtls/ecc'
3
+
4
+ # Testclass with Test Vectors from
5
+ # http://www.nsa.gov/ia/_files/nist-routines.pdf
6
+ class ECCTest < Minitest::Test
7
+ BP_X = ['6b17d1f2e12c4247f8bce6e563a440f2' \
8
+ '77037d812deb33a0f4a13945d898c296'].pack('H*')
9
+ BP_Y = ['4fe342e2fe1a7f9b8ee7eb4a7c0f9e16' \
10
+ '2bce33576b315ececbb6406837bf51f5'].pack('H*')
11
+
12
+ S_X = ['de2444bebc8d36e682edd27e0f271508' \
13
+ '617519b3221a8fa0b77cab3989da97c9'].pack('H*')
14
+ S_Y = ['c093ae7ff36e5380fc01a5aad1e66659' \
15
+ '702de80f53cec576b6350b243042a256'].pack('H*')
16
+
17
+ KEY = ['c51e4753afdec1e6b6c6a5b992f43f8d' \
18
+ 'd0c7a8933072708b6522468b2ffb06fd'].pack('H*')
19
+
20
+ R_X = '51d08d5f2d4278882946d88d83c97d11' \
21
+ 'e62becc3cfc18bedacc89ba34eeca03f'
22
+ R_Y = '75ee68eb8bf626aa5b673ab51f6e744e' \
23
+ '06f8fcf8a6c0cf3035beca956a7b41d5'
24
+
25
+ KEY2 = ['00000000000000000000000000000000' \
26
+ '00000000000000000000000000000002'].pack('H*')
27
+
28
+ R2_X = '7669e6901606ee3ba1a8eef1e0024c33' \
29
+ 'df6c22f3b17481b82a860ffcdb6127b0'
30
+ R2_Y = 'fa878162187a54f6c39f6ee0072f33de' \
31
+ '389ef3eecd03023de10ca2c1db61d0c7'
32
+
33
+ def test_ecc
34
+ r = CoDTLS::ECC.mult(KEY, "\x04" + S_X + S_Y)
35
+ assert_equal('04' + R_X + R_Y, r.unpack('H*')[0])
36
+
37
+ r = CoDTLS::ECC.mult(KEY2, "\x04" + S_X + S_Y)
38
+ assert_equal('04' + R2_X + R2_Y, r.unpack('H*')[0])
39
+
40
+ r1 = CoDTLS::ECC.mult(KEY, "\x04" + BP_X + BP_Y)
41
+ r2 = CoDTLS::ECC.mult(KEY)
42
+ assert_equal(r1.unpack('H*')[0], r2.unpack('H*')[0])
43
+ end
44
+ end
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+ require 'codtls'
3
+
4
+ # Testclass
5
+ class ClientHelloTest < Minitest::Test
6
+ RANDOM = 'ABCDEFGHIJKLMNOPQRSTUVWXYZAB'
7
+ COOKIE = 'ABCDEFGH'
8
+ APPENDIX = "\x00\x02\xFF\x01\x01\x00\x00\x0E\x00\x0A\x00" \
9
+ "\x04\x00\x02\x00\x23\x00\x0B\x00\x02\x01\x00"
10
+
11
+ # [fails?, time, random, cookie, wire]
12
+ V = [
13
+ [0, 42, RANDOM, COOKIE,
14
+ "\xFE\xFD\x00\x00\x00\x2A" + RANDOM + "\x08" + COOKIE + APPENDIX],
15
+ [0, 24, RANDOM, nil,
16
+ "\xFE\xFD\x00\x00\x00\x18" + RANDOM + "\x00" + APPENDIX],
17
+ [0, 0xFFFFFFFF, RANDOM, nil,
18
+ "\xFE\xFD\xFF\xFF\xFF\xFF" + RANDOM + "\x00" + APPENDIX],
19
+ [1, nil, RANDOM, COOKIE, 'T1'],
20
+ [1, 0x1FFFFFFFF, RANDOM, COOKIE, 'T2'],
21
+ [1, 42, '', COOKIE, 'T3'],
22
+ [1, 42, nil, COOKIE, 'T4'],
23
+ [1, 42, RANDOM[0..26], COOKIE, 'T5'],
24
+ [1, 42, RANDOM + 'C', COOKIE, 'T6'],
25
+ [1, 42, RANDOM, 'A' * 256, 'T7']
26
+ ]
27
+
28
+ def test_clienthello
29
+ V.each do |(f, t, r, c, w)|
30
+ if f == 1
31
+ assert_raises CoDTLS::HandshakeError, w do
32
+ CoDTLS::Handshake::ClientHello.new(t, r, c)
33
+ end
34
+ else
35
+ wire = CoDTLS::Handshake::ClientHello.new(t, r, c).to_wire
36
+ assert_equal(w.b, wire)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+ require 'codtls'
3
+
4
+ # Testclass
5
+ class ContentTest < Minitest::Test
6
+ COOKIE = 'ABCDEFGH'
7
+
8
+ def test_content_get
9
+ 3.times do |i|
10
+ c = ("\x0D\x0B\x03\x03\x08" + COOKIE) * (i + 1)
11
+ o = CoDTLS::Handshake::Content.get_content(c)
12
+ assert_equal(CoDTLS::Handshake::HelloVerifyRequest, o.class)
13
+ assert_equal(COOKIE, o.cookie)
14
+ assert_equal(("\x0D\x0B\x03\x03\x08" + COOKIE) * i, c)
15
+ end
16
+
17
+ c = "\x0D\x0B\x03\x03\x08" + COOKIE + 'A'
18
+ CoDTLS::Handshake::Content.get_content(c)
19
+ assert_equal('A', c)
20
+
21
+ assert_raises CoDTLS::HandshakeError do
22
+ c = "\x0D\x0B\x03\x03\x08" + COOKIE[0...6]
23
+ CoDTLS::Handshake::Content.get_content(c)
24
+ end
25
+
26
+ assert_raises CoDTLS::HandshakeError do
27
+ c = "\xFD\x0B\x03\x03\x08" + COOKIE
28
+ CoDTLS::Handshake::Content.get_content(c)
29
+ end
30
+ end
31
+
32
+ def test_add_content
33
+ c = ''
34
+ f = CoDTLS::Handshake::Finished.new('Hallo Welt!')
35
+ CoDTLS::Handshake::Content.add_content(c, f)
36
+ assert_equal("\x51\x0BHallo Welt!", c)
37
+
38
+ CoDTLS::Handshake::Content.add_content(c, f)
39
+ assert_equal("\x51\x0BHallo Welt!\x51\x0BHallo Welt!", c)
40
+
41
+ c = 'ABC'
42
+ f = CoDTLS::Handshake::Finished.new('Hallo Welt!')
43
+ CoDTLS::Handshake::Content.add_content(c, f)
44
+ assert_equal("ABC\x51\x0BHallo Welt!", c)
45
+
46
+ c = ''
47
+ f = CoDTLS::Handshake::Finished.new('')
48
+ CoDTLS::Handshake::Content.add_content(c, f)
49
+ assert_equal("\x50", c)
50
+
51
+ f = CoDTLS::Handshake::Finished.new('Hallo Welt!')
52
+ CoDTLS::Handshake::Content.add_content(c, f)
53
+ assert_equal("\x50\x51\x0BHallo Welt!", c)
54
+
55
+ f = CoDTLS::Handshake::Finished.new('')
56
+ CoDTLS::Handshake::Content.add_content(c, f)
57
+ assert_equal("\x50\x51\x0BHallo Welt!\x50", c)
58
+ end
59
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+ require 'codtls'
3
+
4
+ # Testclass
5
+ class KeyExchangeTest < Minitest::Test
6
+ PSK_HINT = 'ABCDEFGHIJKLMNOP'
7
+ CURVE = CoDTLS::Handshake::KeyExchange::ECCURVETYPE[:named_curve] +
8
+ CoDTLS::Handshake::KeyExchange::NAMEDCURVE[:secp256r1]
9
+ POINT = CoDTLS::Handshake::KeyExchange::POINTTYPE[:uncompressed] +
10
+ ['6b17d1f2e12c4247f8bce6e563a440f2' \
11
+ '77037d812deb33a0f4a13945d898c296'].pack('H*') +
12
+ ['4fe342e2fe1a7f9b8ee7eb4a7c0f9e16' \
13
+ '2bce33576b315ececbb6406837bf51f5'].pack('H*')
14
+
15
+ # [fails?, psk_hint, curve, point, wire]
16
+ V = [
17
+ [0, PSK_HINT, CURVE, POINT,
18
+ "\x00\x10" + PSK_HINT + CURVE + "\x41" + POINT] # ,
19
+ # [1, nil, RANDOM, COOKIE, 'T1']
20
+ ]
21
+
22
+ def test_keyexchange
23
+ V.each do |(f, psk, c, p, w)|
24
+ if f == 1
25
+ # assert_raises CoDTLS::HandshakeError, w do
26
+ # CoDTLS::Handshake::ClientHello.new(t, r, c)
27
+ # end
28
+ else
29
+ wire = CoDTLS::Handshake::ClientKeyExchange.new(psk, c, p).to_wire
30
+ assert_equal(w.b, wire)
31
+ wire = CoDTLS::Handshake::ServerKeyExchange.new(psk, c, p).to_wire
32
+ assert_equal(w.b, wire)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+ require 'minitest/autorun'
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+ require 'codtls/pskdb'
3
+
4
+ # Testclass
5
+ class CoDTLSPSKDBTest < Minitest::Test
6
+ def setup
7
+ fail CoDTLS::SessionError 'testdatabase already exists' if File.exist?(
8
+ 'testdatabase.sqlite')
9
+ SQLite3::Database.new('testdatabase.sqlite')
10
+ ActiveRecord::Base.establish_connection(
11
+ adapter: 'sqlite3',
12
+ database: 'testdatabase.sqlite')
13
+ ActiveRecord::Base.connection
14
+ ActiveRecord::Migration.verbose = false # debug messages
15
+ ActiveRecord::Migrator.migrate 'db/migrate'
16
+ @session = CoDTLS::Session.new('127.0.0.1')
17
+ end
18
+
19
+ def teardown
20
+ ActiveRecord::Base.remove_connection
21
+ FileUtils.rm('testdatabase.sqlite') if File.exist?('testdatabase.sqlite')
22
+ end
23
+
24
+ # a new uuid gets registered and its psk gets updated.
25
+ # The standard values for the epoch and handshake get checked.
26
+ def test_psk
27
+ assert_equal(nil, CoDTLS::PSKDB.get_psk('UUID'))
28
+ CoDTLS::PSKDB.set_psk('UUID', '')
29
+ assert_equal('', CoDTLS::PSKDB.get_psk('UUID'))
30
+ CoDTLS::PSKDB.set_psk('UUID', 'PSK')
31
+ assert_equal('PSK', CoDTLS::PSKDB.get_psk('UUID'))
32
+ CoDTLS::PSKDB.set_psk('UUID2', 'PSK1')
33
+ assert_equal('PSK1', CoDTLS::PSKDB.get_psk('UUID2'))
34
+ CoDTLS::PSKDB.set_psk('UUID2', 'PSK2')
35
+ assert_equal('PSK2', CoDTLS::PSKDB.get_psk('UUID2'))
36
+ end
37
+ end
@@ -0,0 +1,131 @@
1
+ require 'test_helper'
2
+ require 'codtls/abstract_session'
3
+ require 'codtls/ram_session'
4
+
5
+ # Testclass
6
+ class CoDTLSRAMSessionTest < Minitest::Test
7
+ def setup
8
+ @session = CoDTLS::RAMSession.new('127.0.0.1')
9
+ end
10
+
11
+ def teardown
12
+ CoDTLS::RAMSession.clear_all
13
+ end
14
+
15
+ # check values, set everything, check values, clear, check values,
16
+ # create new session, check values
17
+ def test_clear
18
+ assert_equal(nil, @session.id)
19
+ assert_equal(0, @session.epoch)
20
+ assert_equal(true, @session.check_seq(1))
21
+ assert_equal(1, @session.seq)
22
+ assert_equal(nil, @session.key_block)
23
+ assert_equal(false, @session.handshake?)
24
+
25
+ @session.id = 'ABCDEFGH'
26
+ @session.key_block = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDABCD'
27
+ @session.increase_epoch
28
+ @session.seq = 5
29
+ @session.enable_handshake
30
+
31
+ assert_equal('ABCDEFGH', @session.id)
32
+ assert_equal(1, @session.epoch)
33
+ assert_equal(true, @session.check_seq(6))
34
+ assert_equal(1, @session.seq)
35
+ assert_equal('ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDABCD',
36
+ @session.key_block)
37
+ assert_equal(true, @session.handshake?)
38
+
39
+ @session.clear
40
+ assert_equal(nil, @session.id)
41
+ assert_equal(0, @session.epoch)
42
+ assert_equal(true, @session.check_seq(1))
43
+ assert_equal(1, @session.seq)
44
+ assert_equal(nil, @session.key_block)
45
+ assert_equal(false, @session.handshake?)
46
+ end
47
+
48
+ # get_epoch and increase_epoch test
49
+ def test_epoch
50
+ assert_equal(nil, @session.id)
51
+ assert_equal(0, @session.epoch)
52
+ assert_equal(true, @session.check_seq(1))
53
+ assert_equal(1, @session.seq)
54
+ assert_equal(nil, @session.key_block)
55
+ assert_equal(false, @session.handshake?)
56
+
57
+ @session.seq
58
+ @session.seq
59
+ @session.seq = 50
60
+ assert_raises(CoDTLS::SessionError) { @session.increase_epoch }
61
+
62
+ @session.key_block = 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDABCD'
63
+ assert_equal(nil, @session.key_block)
64
+
65
+ @session.increase_epoch
66
+ assert_equal(1, @session.epoch)
67
+ assert_equal(true, @session.check_seq(1))
68
+ assert_equal(1, @session.seq)
69
+ assert_equal('ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDABCD',
70
+ @session.key_block)
71
+ end
72
+
73
+ # get_key_block and add_key_block tests, testing the overwriting off
74
+ # new keyblocks and switching keyblocks when the epoch is increased
75
+ def test_key_block
76
+ assert_equal(nil, @session.key_block)
77
+ exception = assert_raises(CoDTLS::SessionError) do
78
+ @session.key_block = 'this_key_block_is_too_small'
79
+ end
80
+ assert_equal('key blocks have to be 40 byte long', exception.message)
81
+ @session.key_block = 'key_block_with_fourty_bytes_number_00001'
82
+ assert_equal(nil, @session.key_block)
83
+ @session.increase_epoch
84
+ assert_equal('key_block_with_fourt' \
85
+ 'y_bytes_number_00001', @session.key_block)
86
+ @session.key_block = 'key_block_with_fourty_bytes_number_00002'
87
+ @session.key_block = 'key_block_with_fourty_bytes_number_00003'
88
+ assert_equal('key_block_with_fourt' \
89
+ 'y_bytes_number_00001', @session.key_block)
90
+ @session.increase_epoch
91
+ assert_equal('key_block_with_fourt' \
92
+ 'y_bytes_number_00003', @session.key_block)
93
+ end
94
+
95
+ # enable_handshake and dissable_handshake tests.
96
+ def test_handshake
97
+ assert_equal(false, @session.handshake?)
98
+ @session.enable_handshake
99
+ assert_equal(true, @session.handshake?)
100
+ @session.enable_handshake
101
+ assert_equal(true, @session.handshake?)
102
+ @session.disable_handshake
103
+ assert_equal(false, @session.handshake?)
104
+ end
105
+
106
+ # get_seq and check_seq tests, testing the check_seq ranges and the
107
+ # incrementing of get_seq.
108
+ def test_seq
109
+ assert_equal(1, @session.seq)
110
+ assert_equal(2, @session.seq)
111
+ assert_equal(3, @session.seq)
112
+
113
+ # 1 is expected, so -9 ... 101 are valid values
114
+ assert_equal(false, @session.check_seq(-10))
115
+ assert_equal(false, @session.check_seq(102))
116
+ assert_equal(true, @session.check_seq(-9))
117
+ assert_equal(true, @session.check_seq(-1))
118
+ assert_equal(true, @session.check_seq(0))
119
+ assert_equal(true, @session.check_seq(1))
120
+ assert_equal(true, @session.check_seq(101))
121
+
122
+ @session.seq = 1
123
+ (2..100).each do |n|
124
+ assert_equal(true, @session.check_seq(n))
125
+ @session.seq = n
126
+ end
127
+ # 101 is expected, so max allowed value is 201
128
+ assert_equal(true, @session.check_seq(201))
129
+ assert_equal(false, @session.check_seq(202))
130
+ end
131
+ end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+ require 'codtls/rampskdb'
3
+
4
+ # Testclass
5
+ class CoDTLSRAMPSKDBTest < Minitest::Test
6
+ def setup
7
+ end
8
+
9
+ def teardown
10
+ CoDTLS::RAMPSKDB.clear_all
11
+ end
12
+
13
+ # a new uuid gets registered and its psk gets updated.
14
+ # The standard values for the epoch and handshake get checked.
15
+ def test_psk
16
+ assert_equal(nil, CoDTLS::RAMPSKDB.get_psk('UUID'))
17
+ CoDTLS::RAMPSKDB.set_psk('UUID', '')
18
+ assert_equal('', CoDTLS::RAMPSKDB.get_psk('UUID'))
19
+ CoDTLS::RAMPSKDB.set_psk('UUID', 'PSK')
20
+ assert_equal('PSK', CoDTLS::RAMPSKDB.get_psk('UUID'))
21
+ CoDTLS::RAMPSKDB.set_psk('UUID2', 'PSK1')
22
+ assert_equal('PSK1', CoDTLS::RAMPSKDB.get_psk('UUID2'))
23
+ CoDTLS::RAMPSKDB.set_psk('UUID2', 'PSK2')
24
+ assert_equal('PSK2', CoDTLS::RAMPSKDB.get_psk('UUID2'))
25
+ end
26
+ end
@@ -0,0 +1,128 @@
1
+ require 'test_helper'
2
+ require 'codtls'
3
+
4
+ # Testclass
5
+ class RecordTest < Minitest::Test
6
+ # [fails?, input, header, headeradd]
7
+ V = [[
8
+ # Type
9
+ [0, :alert, 0x2000, ''],
10
+ [0, :handshake, 0x4000, ''],
11
+ [0, :appdata, 0x6000, ''],
12
+ [0, 0, 0x0000, '00'],
13
+ [0, 128, 0x0000, '80'],
14
+ [0, 255, 0x0000, 'ff'],
15
+ [1, 'string', 0x0000, ''],
16
+ [1, :unknown, 0x0000, ''],
17
+ [1, -1, 0x0000, ''],
18
+ [1, 256, 0x0000, '']
19
+ ], [
20
+ # Version
21
+ [0, :v10, 0x0000, ''],
22
+ [0, :v12, 0x1000, ''],
23
+ [0, 0, 0x0800, '0000'],
24
+ [0, 255, 0x0800, '00ff'],
25
+ [0, 256, 0x0800, '0100'],
26
+ [0, 2**16 - 1, 0x0800, 'ffff'],
27
+ [1, 'string', 0x0800, ''],
28
+ [1, :reserved, 0x0800, ''],
29
+ [1, -1, 0x0800, ''],
30
+ [1, 2**16, 0x0800, '']
31
+ ], [
32
+ # Epoch
33
+ [0, :implizit, 0x0700, ''],
34
+ [0, 0, 0x0000, ''],
35
+ [0, 4, 0x0400, ''],
36
+ [0, 5, 0x0500, '05'],
37
+ [0, 255, 0x0500, 'ff'],
38
+ [0, 256, 0x0600, '0100'],
39
+ [0, 2**16 - 1, 0x0600, 'ffff'],
40
+ [1, 'string', 0x0500, ''],
41
+ [1, :unknown, 0x0500, ''],
42
+ [1, -1, 0x0600, ''],
43
+ [1, 2**16, 0x0600, '']
44
+ ], [
45
+ # Seq_Num
46
+ [0, :none, 0x0000, ''],
47
+ [0, :implizit, 0x001C, ''],
48
+ [0, 0, 0x0004, '00'],
49
+ [0, 255, 0x0004, 'ff'],
50
+ [0, 256, 0x0008, '0100'],
51
+ [0, 2**16 - 1, 0x0008, 'ffff'],
52
+ [0, 2**16, 0x000C, '010000'],
53
+ [0, 2**48 - 1, 0x0018, 'ffffffffffff'],
54
+ [1, 'string', 0x0004, ''],
55
+ [1, :unknown, 0x0008, ''],
56
+ [1, -1, 0x000C, ''],
57
+ [1, 2**48, 0x0018, '']
58
+ ], [
59
+ # Length
60
+ [0, :implizit, 0x0003, ''],
61
+ [0, 0, 0x0000, ''],
62
+ [0, 5, 0x0001, '05'],
63
+ [0, 128, 0x0001, '80'],
64
+ [0, 255, 0x0001, 'ff'],
65
+ [0, 256, 0x0002, '0100'],
66
+ [0, 2**16 - 1, 0x0002, 'ffff'],
67
+ [1, 'string', 0x0001, ''],
68
+ [1, :unknown, 0x0001, ''],
69
+ [1, -1, 0x0002, ''],
70
+ [1, 2**16, 0x0002, '']
71
+ ]]
72
+
73
+ def test_record
74
+ assert_raises(CoDTLS::RecordError) { CoDTLS::Record.parse('') }
75
+ assert_raises(CoDTLS::RecordError) { CoDTLS::Record.parse(' ') }
76
+
77
+ V[0].each do |t|
78
+ V[1].each do |v|
79
+ V[2].each do |e|
80
+ V[3].each do |s|
81
+ V[4].each do |l|
82
+ header = 0x00C0 | t[2] | v[2] | e[2] | s[2] | l[2]
83
+ to_add = t[3] + v[3] + e[3] + s[3] + l[3]
84
+ complete = [header].pack('n').unpack('H*')[0] + to_add
85
+
86
+ fail = t[0] | v[0] | e[0] | s[0] | l[0]
87
+ if fail == 1
88
+ assert_raises CoDTLS::RecordError, complete do
89
+ r = CoDTLS::Record.new(t[1], e[1], s[1])
90
+ r.version = v[1]
91
+ r.length = l[1]
92
+ end
93
+ assert_raises CoDTLS::RecordError, complete do
94
+ CoDTLS::Record.parse([complete].pack('H*'))
95
+ end
96
+ else
97
+ nonce = 'abcd'
98
+ nonce += [e[1].class == Symbol ? 0 : e[1]].pack('n')
99
+ seq = [s[1].class == Symbol ? 0 : s[1]].pack('Q')
100
+ nonce += seq[0...6].reverse
101
+ # to_wire
102
+ r = CoDTLS::Record.new(t[1], e[1], s[1])
103
+ r.version = v[1]
104
+ r.length = l[1]
105
+ assert_equal(complete, r.to_wire.unpack('H*')[0], r.inspect)
106
+ assert_equal(nonce, r.nonce('abcd'))
107
+ # parse
108
+ data = 'Hello World!'
109
+ fail_info = complete + data
110
+ complete = [complete].pack('H*') + data
111
+ r, d = CoDTLS::Record.parse(complete)
112
+ assert_equal(t[1], r.type, fail_info + ' Type')
113
+ assert_equal(v[1], r.version, fail_info + ' Version')
114
+ assert_equal(e[1], r.epoch, fail_info + ' Epoch')
115
+ assert_equal(s[1], r.seq_num, fail_info + ' Seq_num')
116
+ assert_equal(l[1], r.length, fail_info + ' Length')
117
+ range = (r.length == :implizit ? 0..-1 : 0...r.length)
118
+ assert_equal(data.slice!(range), d, fail_info + ' Payload')
119
+ assert_equal(data, complete, fail_info + ' Rest')
120
+ assert_equal(nonce, r.nonce('abcd'))
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end