openssl-ccm 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d66abf07f1338dab11b2447f1021d7cdb8c48a00
4
+ data.tar.gz: ab8339239f00ab678d22094dc4155f7bafe9374d
5
+ SHA512:
6
+ metadata.gz: 0edc78d7cef5c7fbcb6023448c9e92413c86d8ff0aa40016f8a5ecbb13a81b4a528121a84e7e88594f7b2161528f80cca77227604968f689e6ec91efef960847
7
+ data.tar.gz: de45305879ceb9a473e6f02ba05b548212b7cdfe5bf95bce8e212f07a3583253b256151281c76ddbb514e8970c9d5b4602301be85e5d578dc9846978c5bb2fa7
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rdoc', '>=4.1.1'
4
+ gem 'yard', '>=0.8.7.3'
5
+ gem 'rubocop', '>=0.18.1'
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 SmallLars
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ openssl-ccm
2
+ ===========
3
+
4
+ Ruby Gem for RFC 3610 - Counter with CBC-MAC (CCM)
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ task :default => :build
5
+
6
+ desc "Run tests"
7
+ Rake::TestTask.new do |t|
8
+ t.libs << 'test'
9
+ end
10
+
11
+ desc "Uninstall gem"
12
+ task (:uninstall) { sh "gem uninstall openssl-ccm" }
13
+
14
+ desc "Development Dependencies"
15
+ task (:devinst) { sh "gem install --dev ./openssl-ccm-0.0.1.gem" }
16
+
17
+ desc "Clean gem"
18
+ task :clean do
19
+ begin; sh "rm ./openssl-ccm-*.gem"; rescue; end
20
+ begin; sh "rm -R ./.yardoc"; rescue; end
21
+ begin; sh "rm -R ./doc"; rescue; end
22
+ end
23
+
24
+ desc "Bundle install"
25
+ task (:bundle) { sh "bundle install" }
26
+
27
+ desc "Create documentation"
28
+ task :doc do
29
+ sh "gem rdoc --rdoc openssl-ccm"
30
+ sh "yardoc"
31
+ end
@@ -0,0 +1,164 @@
1
+ require 'openssl'
2
+
3
+ module OpenSSL
4
+ # TODO
5
+ class CCMError < StandardError
6
+ end
7
+
8
+ # Abstract from http://tools.ietf.org/html/rfc3610:
9
+ #
10
+ # Counter with CBC-MAC (CCM) is a generic authenticated encryption
11
+ # block cipher mode. CCM is defined for use with 128-bit block
12
+ # ciphers, such as the Advanced Encryption Standard (AES).
13
+ #
14
+ # At the moment there is no update function, because length of
15
+ # data and additional_data are needed to start of cipher process.
16
+ # In future init(nonce, data_len, additional_data_len) could
17
+ # be a solution, to solve this problem. After init, update(data)
18
+ # could be used to set additional_data first followed by data.
19
+ class CCM
20
+ # Searches for supported algorithms within OpenSSL
21
+ #
22
+ # @return [Stringlist] of supported algorithms
23
+ def self.ciphers
24
+ l = OpenSSL::Cipher.ciphers.keep_if { |c| c.end_with?('-128-CBC') }
25
+ l.length.times { |i| l[i] = l[i][0..-9] }
26
+ l
27
+ end
28
+
29
+ public
30
+
31
+ # Creates a new CCM object.
32
+ #
33
+ # @param cipher [String] one of the supported algorithms like 'AES'
34
+ # @param key [String] the key used for encryption and decryption
35
+ # @param mac_len [Number] the length of the mac.
36
+ # needs to be in 4, 6, 8, 10, 12, 14, 16
37
+ #
38
+ # @return [Object] the new CCM object
39
+ def initialize(cipher, key, mac_len)
40
+ unless CCM.ciphers.include?(cipher)
41
+ fail CCMError, "unsupported cipher algorithm (#{cipher})"
42
+ end
43
+ fail CCMError, 'invalid key length' unless key.b.length >= 16
44
+ unless (4..16).step(2).include?(mac_len)
45
+ fail CCMError, 'invalid mac length'
46
+ end
47
+
48
+ @cipher = OpenSSL::Cipher.new("#{cipher}-128-CBC")
49
+ @key = key
50
+ @mac_len = mac_len
51
+ end
52
+
53
+ # Encrypts the input data and appends mac for authentication.
54
+ # If there is additional data, its included into mac calculation.
55
+ #
56
+ # @param data [String] the data to encrypt
57
+ # @param nonce [String] the nonce used for encryption
58
+ # @param additional_data [String] additional data to
59
+ # authenticate with mac (not part of the output)
60
+ #
61
+ # @return [String] the encrypted data with appended mac
62
+ def encrypt(data, nonce, additional_data = '')
63
+ valid?(data, nonce, additional_data)
64
+
65
+ crypt(data, nonce) + mac(data, nonce, additional_data)
66
+ end
67
+
68
+ # Decrypts the input data and checks the appended mac.
69
+ # If additional data was used for encryption, its needed
70
+ # for decryption, to check the authentication (mac).
71
+ #
72
+ # @param data [String] the data to decrypt
73
+ # @param nonce [String] the nonce used for decryption
74
+ # @param additional_data [String] additional data to check
75
+ # authentication (not part of the output)
76
+ #
77
+ # @return [String] the decrypted data without mac
78
+ def decrypt(data, nonce, additional_data = '')
79
+ valid?(data, nonce, additional_data)
80
+
81
+ new_data = crypt(data.b[0...-@mac_len], nonce)
82
+ new_mac = mac(new_data, nonce, additional_data)
83
+ return new_data if new_mac == data.b[-@mac_len..-1]
84
+ ''
85
+ end
86
+
87
+ private
88
+
89
+ def valid?(data, nonce, additional_data)
90
+ unless (7..13).include?(nonce.b.length)
91
+ fail CCMError, 'invalid nonce length'
92
+ end
93
+ unless data.b.length < 2**(8 * (15 - nonce.b.length))
94
+ fail CCMError, 'invalid data length'
95
+ end
96
+ unless additional_data.b.length < 2**64
97
+ fail CCMError, 'invalid additional_data length'
98
+ end
99
+ true
100
+ end
101
+
102
+ def crypt(data, nonce)
103
+ result = ''
104
+ data.bytes.each_slice(16).with_index(1) do |block, b|
105
+ counter = get_counter(nonce, b).bytes
106
+ block.length.times { |i| counter[i] ^= block[i] }
107
+ result << counter[0, block.length].pack('C*')
108
+ end
109
+ result
110
+ end
111
+
112
+ def mac(data, nonce, additional_data)
113
+ @cipher.reset
114
+ @cipher.encrypt
115
+ @cipher.key = @key
116
+
117
+ b_0 = Array.new(8, 0)
118
+ b_0[0] = (additional_data.empty? ? 0 : 64) \
119
+ + (8 * ((@mac_len - 2) / 2)) \
120
+ + (14 - nonce.b.length)
121
+ b_0 += [data.b.length].pack('Q').reverse.bytes
122
+ b_0[1, nonce.b.length] = nonce.bytes
123
+ mac = @cipher.update(b_0.pack('C*')).bytes
124
+
125
+ unless additional_data.empty?
126
+ len = additional_data.b.length
127
+ d = case
128
+ when len < (2**16 - 2**8)
129
+ [len].pack('n')
130
+ when len < 2**32
131
+ "\xFF\xFE" + [len].pack('N')
132
+ else
133
+ "\xFF\xFF" + [len].pack('Q').reverse
134
+ end + additional_data
135
+ mac = @cipher.update(d + padding(d)).bytes[-16..-1]
136
+ end
137
+
138
+ unless data.empty?
139
+ mac = @cipher.update(data + padding(data)).bytes[-16..-1]
140
+ end
141
+
142
+ a_0 = get_counter(nonce, 0).bytes
143
+ 16.times { |i| mac[i] ^= a_0[i] }
144
+ mac[0...@mac_len].pack('C*')
145
+ end
146
+
147
+ def padding(data)
148
+ return '' if (data.b.length % 16) == 0
149
+ "\x00" * (16 - (data.b.length % 16))
150
+ end
151
+
152
+ def get_counter(nonce, index)
153
+ a = Array.new(8, 0)
154
+ a[0] = 14 - nonce.b.length
155
+ a += [index].pack('Q').reverse.bytes
156
+ a[1, nonce.b.length] = nonce.bytes
157
+
158
+ @cipher.reset
159
+ @cipher.encrypt
160
+ @cipher.key = @key
161
+ @cipher.update(a.pack('C*'))
162
+ end
163
+ end
164
+ end
data/test/data_1 ADDED
File without changes
data/test/data_1-1_e ADDED
@@ -0,0 +1 @@
1
+ �`��`C� �x�J)�
data/test/data_1-2_e ADDED
@@ -0,0 +1 @@
1
+ �3Qȳ��
data/test/data_1-3_e ADDED
@@ -0,0 +1 @@
1
+ ��#�=�ʵ��ii3
data/test/data_1-4_e ADDED
@@ -0,0 +1 @@
1
+ (����y
data/test/data_2 ADDED
@@ -0,0 +1,2 @@
1
+ Ein kleiner Text
2
+ zum Testen von CCM.
data/test/data_2-1_e ADDED
Binary file
data/test/data_2-2_e ADDED
@@ -0,0 +1 @@
1
+ Dz�p�5{h�5M���A=��%�֧ސ�ii��@���tS,��Ϲ
data/test/data_2-3_e ADDED
@@ -0,0 +1 @@
1
+ `��gM�T�)~>4�x����O��;���� �c���rܮ|��V*���<
data/test/data_2-4_e ADDED
@@ -0,0 +1,2 @@
1
+ �1U��p�b�vA���&pa�6����F=Z�
2
+ s���7UB�~�;�
data/test/data_3 ADDED
Binary file
data/test/data_3-1_e ADDED
Binary file
data/test/data_3-2_e ADDED
Binary file
data/test/data_3-3_e ADDED
Binary file
data/test/data_3-4_e ADDED
Binary file
data/test/test_ccm.rb ADDED
@@ -0,0 +1,265 @@
1
+ require 'test/unit'
2
+ require 'openssl-ccm'
3
+
4
+ # Testclass with Test Vectors from
5
+ # http://tools.ietf.org/html/rfc3610#section-8
6
+ class CCMTest < Test::Unit::TestCase
7
+ KEY = %W(C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF) * 12 \
8
+ + %W(D7828D13B2B0BDC325A76236DF93CC6B) * 12
9
+ NONCE = %W(
10
+ 00000003020100A0A1A2A3A4A5
11
+ 00000004030201A0A1A2A3A4A5
12
+ 00000005040302A0A1A2A3A4A5
13
+ 00000006050403A0A1A2A3A4A5
14
+ 00000007060504A0A1A2A3A4A5
15
+ 00000008070605A0A1A2A3A4A5
16
+ 00000009080706A0A1A2A3A4A5
17
+ 0000000A090807A0A1A2A3A4A5
18
+ 0000000B0A0908A0A1A2A3A4A5
19
+ 0000000C0B0A09A0A1A2A3A4A5
20
+ 0000000D0C0B0AA0A1A2A3A4A5
21
+ 0000000E0D0C0BA0A1A2A3A4A5
22
+ 00412B4EA9CDBE3C9696766CFA
23
+ 0033568EF7B2633C9696766CFA
24
+ 00103FE41336713C9696766CFA
25
+ 00764C63B8058E3C9696766CFA
26
+ 00F8B678094E3B3C9696766CFA
27
+ 00D560912D3F703C9696766CFA
28
+ 0042FFF8F1951C3C9696766CFA
29
+ 00920F40E56CDC3C9696766CFA
30
+ 0027CA0C7120BC3C9696766CFA
31
+ 005B8CCBCD9AF83C9696766CFA
32
+ 003EBE94044B9A3C9696766CFA
33
+ 008D493B30AE8B3C9696766CFA
34
+ )
35
+ DATA = %W(
36
+ 08090A0B0C0D0E0F101112131415161718191A1B1C1D1E
37
+ 08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
38
+ 08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20
39
+ 0C0D0E0F101112131415161718191A1B1C1D1E
40
+ 0C0D0E0F101112131415161718191A1B1C1D1E1F
41
+ 0C0D0E0F101112131415161718191A1B1C1D1E1F20
42
+ 08090A0B0C0D0E0F101112131415161718191A1B1C1D1E
43
+ 08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
44
+ 08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20
45
+ 0C0D0E0F101112131415161718191A1B1C1D1E
46
+ 0C0D0E0F101112131415161718191A1B1C1D1E1F
47
+ 0C0D0E0F101112131415161718191A1B1C1D1E1F20
48
+ 08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C
49
+ 9020EA6F91BDD85AFA0039BA4BAFF9BFB79C7028949CD0EC
50
+ B916E0EACC1C00D7DCEC68EC0B3BBB1A02DE8A2D1AA346132E
51
+ 12DAAC5630EFA5396F770CE1A66B21F7B2101C
52
+ E88B6A46C78D63E52EB8C546EFB5DE6F75E9CC0D
53
+ 6435ACBAFB11A82E2F071D7CA4A5EBD93A803BA87F
54
+ 8A19B950BCF71A018E5E6701C91787659809D67DBEDD18
55
+ 1761433C37C5A35FC1F39F406302EB907C6163BE38C98437
56
+ A434A8E58500C6E41530538862D686EA9E81301B5AE4226BFA
57
+ B96B49E21D621741632875DB7F6C9243D2D7C2
58
+ E2FCFBB880442C731BF95167C8FFD7895E337076
59
+ ABF21C0B02FEB88F856DF4A37381BCE3CC128517D4
60
+ )
61
+ ADD_DATA = %W(0001020304050607) * 3 \
62
+ + %W(000102030405060708090A0B) * 3 \
63
+ + %W(0001020304050607) * 3 \
64
+ + %W(000102030405060708090A0B) * 3 \
65
+ + %W(
66
+ 0BE1A88BACE018B1
67
+ 63018F76DC8A1BCB
68
+ AA6CFA36CAE86B40
69
+ D0D0735C531E1BECF049C244
70
+ 77B60F011C03E1525899BCAE
71
+ CD9044D2B71FDB8120EA60C0
72
+ D85BC7E69F944FB8
73
+ 74A0EBC9069F5B37
74
+ 44A3AA3AAE6475CA
75
+ EC46BB63B02520C33C49FD70
76
+ 47A65AC78B3D594227E85E71
77
+ 6E37A6EF546D955D34AB6059
78
+ )
79
+ CTR0001 = %W(
80
+ 50859D916DCB6DDDE077C2D1D4EC9F97
81
+ 7AC0103DED38F6C0390DBA871C4991F4
82
+ 59B8EFFF46147312B47A1D9D393D3CFF
83
+ AE81666A838B886AEEBF4A5B3284508A
84
+ D0FCF5744D8F31E8895B05054B7C90C3
85
+ 63CCBE1EE01744984564B23A8D245C80
86
+ 093CDBB9C5524FDAC1C5ECD291C470AF
87
+ 737C3391CC8E13DDE0AAC54B6DB7EB98
88
+ 8A5A106BC0299A555B936B0B0EA0DE5A
89
+ 0B392B9B056697063F12568F2B13A10F
90
+ 6B66BC0C90A1F112FCBE6F4E122077BC
91
+ CCF2AED9E04AC974E65855B32B9430BF
92
+ 4451B0117A8482BF0319AEC1595EBDDA
93
+ DCEBF413383C66A05A7255EF98D7FFAD
94
+ 08C4DAC8ECC1C07B4CE1F24C375A47EE
95
+ 0608FF95A694D559F40BB79DEFFA41DF
96
+ BDCE955CCFD3810A91EA77A6A45BC04C
97
+ 64A2C55650CEE04C7A93D8EEF543E88E
98
+ 363834FA28833DB755660D98650D6846
99
+ 4F71A5C11242E37D29F0FEE41BE1025F
100
+ 568A459E40094867EB85E09E6A2E6476
101
+ 88BC194280C1FA3EBEFCEFFB4DC62D54
102
+ 0A7E0A6353C8CF9EBC3B6E63159AD097
103
+ 58DB19B3889AA38B3CA40B16FF422C73
104
+ )
105
+ CTR0002 = %W(
106
+ 7546717AC6DE9AFF640C9C06DE6D0D8F
107
+ D40CDE22D5F92424F7BE9A569DA79F51
108
+ 69F122A078C79B8977894C99975C2378
109
+ D1B19206AC939E2FB6DDCE10A774FD8D
110
+ 72A0D4219F0DE1D40483BC2D3D0CFC2A
111
+ 396DBAA2A7D2CBD4B5E17C107945BBC0
112
+ 11578386E2C472B48ECC8AADAB776FCB
113
+ 74B77177C5AAC53B04A4F8708E92EB2B
114
+ EA05FDE2AB225CFEB77312CB88D9A54A
115
+ 078965252340943B9E69B256CC5EF731
116
+ 979E572BBE658AE5CC2011832A9A9B5B
117
+ A2CAAC1163F407E5E5F6E3B3790F79F8
118
+ 83EB76E13A44847F9220090776B825C5
119
+ 2F542CBA15D66CDFE1EC468F0E68A124
120
+ A7872E6C6DC44E842602504C3FA573C5
121
+ 80553A75783804A9648B68DD7FDCDD7A
122
+ 432EF232AE36D89222BF6337E6B26CE8
123
+ 18E765ACB7B0E9AF092BD0206CA1C83C
124
+ 35E96354871672563F0C08AF784431A9
125
+ 342BD3F17CB77BC1790B05056159272C
126
+ A600AA929203549AAEEF2CCC59137A57
127
+ 3E597DA5AE21CCA4009E4C0C91F62249
128
+ EA2032DA27826E139E1E725C5B0D3EBF
129
+ C32F243D65DC7E9F4B0216AB7FB96B4D
130
+ )
131
+ CIPHER = %W(
132
+ 588C979A61C663D2F066D0C2C0F989806D5F6B61DAC384
133
+ 72C91A36E135F8CF291CA894085C87E3CC15C439C9E43A3B
134
+ 51B1E5F44A197D1DA46B0F8E2D282AE871E838BB64DA859657
135
+ A28C6865939A9A79FAAA5C4C2A9D4A91CDAC8C
136
+ DCF1FB7B5D9E23FB9D4E131253658AD86EBDCA3E
137
+ 6FC1B011F006568B5171A42D953D469B2570A4BD87
138
+ 0135D1B2C95F41D5D1D4FEC185D166B8094E999DFED96C
139
+ 7B75399AC0831DD2F0BBD75879A2FD8F6CAE6B6CD9B7DB24
140
+ 82531A60CC24945A4B8279181AB5C84DF21CE7F9B73F42E197
141
+ 07342594157785152B074098330ABB141B947B
142
+ 676BB20380B0E301E8AB79590A396DA78B834934
143
+ C0FFA0D6F05BDB67F24D43A4338D2AA4BED7B20E43
144
+ 4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8
145
+ 4CCB1E7CA981BEFAA0726C55D378061298C85C92814ABC33
146
+ B1D23A2220DDC0AC900D9AA03C61FCF4A559A4417767089708
147
+ 14D253C3967B70609B7CBB7C49916028324526
148
+ 5545FF1A085EE2EFBF52B2E04BEE1E2336C73E3F
149
+ 009769ECABDF48625594C59251E6035722675E04C8
150
+ BC218DAA947427B6DB386A99AC1AEF23ADE0B52939CB6A
151
+ 5810E6FD25874022E80361A478E3E9CF484AB04F447EFFF6
152
+ F2BEED7BC5098E83FEB5B31608F8E29C38819A89C8E776F154
153
+ 31D750A09DA3ED7FDDD49A2032AABF17EC8EBF
154
+ E882F1DBD38CE3EDA7C23F04DD65071EB41342AC
155
+ F32905B88A641B04B9C9FFB58CC390900F3DA12AB1
156
+ )
157
+ MAC = %W(
158
+ 17E8D12CFDF926E0
159
+ A091D56E10400916
160
+ 4ADAA76FBD9FB0C5
161
+ 96C861B9C9E61EF1
162
+ 51E83F077D9C2D93
163
+ 405A0443AC91CB94
164
+ 048C56602C97ACBB7490
165
+ C17B4433F434963F34B4
166
+ EA9C07E56B5EB17E5F4E
167
+ 566AA9406B4D999988DD
168
+ F53AA2E9107A8B6C022C
169
+ CD1AA31662E7AD65D6DB
170
+ E78CF7CB0CDDD7B3
171
+ C52EE81D7D77C08A
172
+ A776796EDB723506
173
+ 9A6F49975BCADEAF
174
+ 762C0C7744FE7E3C
175
+ 47099E5AE0704551
176
+ 637CF9BEC2408897C6BA
177
+ F0A477CC2FC9BF548944
178
+ 4D4151A4ED3A8B87B9CE
179
+ 7D22C8088C666BE5C197
180
+ DF7E00DCCEC7AE52987D
181
+ 6DCE9E82EFA16DA62059
182
+ )
183
+
184
+ def test_aes_init
185
+ assert_raise(OpenSSL::CCMError) { OpenSSL::CCM.new('', 'A' * 16, 8) }
186
+ assert_raise(OpenSSL::CCMError) { OpenSSL::CCM.new('AE', 'A' * 16, 8) }
187
+
188
+ assert_raise(OpenSSL::CCMError) { OpenSSL::CCM.new('AES', '', 8) }
189
+ assert_raise(OpenSSL::CCMError) { OpenSSL::CCM.new('AES', 'A', 8) }
190
+ assert_raise(OpenSSL::CCMError) { OpenSSL::CCM.new('AES', 'A' * 15, 8) }
191
+
192
+ 3.step(17, 2) do |l|
193
+ assert_raise(OpenSSL::CCMError) { OpenSSL::CCM.new('AES', 'A' * 16, l) }
194
+ end
195
+ end
196
+
197
+ def test_aes_padding
198
+ ccm = OpenSSL::CCM.new('AES', 'A' * 16, 8)
199
+
200
+ assert_equal(''.b , ccm.send(:padding, '').b)
201
+ assert_equal("\x00".b , ccm.send(:padding, 'A' * 15).b)
202
+ assert_equal(''.b , ccm.send(:padding, 'A' * 16).b)
203
+ assert_equal(("\x00" * 15).b, ccm.send(:padding, 'A').b)
204
+ end
205
+
206
+ def test_aes_valid
207
+ ccm = OpenSSL::CCM.new('AES', 'A' * 16, 8)
208
+
209
+ assert(ccm.send(:valid?, '', 'A' * 13, ''))
210
+ assert(ccm.send(:valid?, 'A' * (256**2 - 1), 'A' * 13, ''))
211
+ assert_raise(OpenSSL::CCMError) do
212
+ ccm.send(:valid?, 'A' * 256**2, 'A' * 13, '')
213
+ end
214
+
215
+ assert_raise OpenSSL::CCMError do
216
+ ccm.send(:valid?, 'Hello!', 'A' * 6, '')
217
+ end
218
+ assert(ccm.send(:valid?, '', 'A' * 7, ''))
219
+ assert(ccm.send(:valid?, '', 'A' * 13, ''))
220
+ assert_raise OpenSSL::CCMError do
221
+ ccm.send(:valid?, 'Hello!', 'A' * 14, '')
222
+ end
223
+ end
224
+
225
+ def test_aes_vectors
226
+ assert(OpenSSL::CCM.ciphers.include?('AES'), 'Missing AES-Cipher')
227
+ KEY.length.times do |i|
228
+ ccm = OpenSSL::CCM.new('AES', [KEY[i]].pack('H*'),
229
+ [MAC[i]].pack('H*').b.length)
230
+
231
+ c = ccm.send(:get_counter, [NONCE[i]].pack('H*'), 1)
232
+ assert_equal(CTR0001[i], c.unpack('H*')[0].upcase,
233
+ "Wrong CTR0001 in Vector #{i + 1}")
234
+
235
+ c = ccm.send(:get_counter, [NONCE[i]].pack('H*'), 2)
236
+ assert_equal(CTR0002[i], c.unpack('H*')[0].upcase,
237
+ "Wrong CTR0002 in Vector #{i + 1}")
238
+
239
+ c = ccm.send(:crypt, [DATA[i]].pack('H*'), [NONCE[i]].pack('H*'))
240
+ assert_equal(CIPHER[i], c.unpack('H*')[0].upcase,
241
+ "Wrong CIPHER in Vector #{i + 1}")
242
+
243
+ c = ccm.send(:mac,
244
+ [DATA[i]].pack('H*'),
245
+ [NONCE[i]].pack('H*'),
246
+ [ADD_DATA[i]].pack('H*'))
247
+ assert_equal(MAC[i], c.unpack('H*')[0].upcase,
248
+ "Wrong MAC in Vector #{i + 1}")
249
+
250
+ c = ccm.send(:encrypt,
251
+ [DATA[i]].pack('H*'),
252
+ [NONCE[i]].pack('H*'),
253
+ [ADD_DATA[i]].pack('H*'))
254
+ assert_equal((CIPHER[i] + MAC[i]), c.unpack('H*')[0].upcase,
255
+ "Wrong ENCRYPT in Vector #{i + 1}")
256
+
257
+ c = ccm.send(:decrypt,
258
+ [CIPHER[i] + MAC[i]].pack('H*'),
259
+ [NONCE[i]].pack('H*'),
260
+ [ADD_DATA[i]].pack('H*'))
261
+ assert_equal(DATA[i], c.unpack('H*')[0].upcase,
262
+ "Wrong ENCRYPT in Vector #{i + 1}")
263
+ end
264
+ end
265
+ end
@@ -0,0 +1,37 @@
1
+ require 'test/unit'
2
+ require 'openssl-ccm'
3
+
4
+ # Testclass
5
+ class CCMFilesTest < Test::Unit::TestCase
6
+ KEY = %W(
7
+ 00000000000000000000000000000000
8
+ 001234567890ABCDEFDCAFFEED3921EE
9
+ 001234567890ABCDEFDCAFFEED3921EE
10
+ 11223344AABB00000000000000000000
11
+ )
12
+ NONCE = %W(
13
+ 00000000000000000000000000
14
+ 00112233445566778899
15
+ 001122334455667788990000
16
+ 00112233445566778899
17
+ )
18
+ MAC_LEN = [16, 8, 14, 8]
19
+
20
+ def test_aes
21
+ assert(OpenSSL::CCM.ciphers.include?('AES'), 'Missing AES-Cipher')
22
+ 1.upto(3) do |i|
23
+ open("test/data_#{i}", mode = 'r') do |i_file|
24
+ input = i_file.read
25
+ KEY.length.times do |j|
26
+ open("test/data_#{i}-#{j + 1}_e", mode = 'r') do |o_file|
27
+ output = o_file.read
28
+ ccm = OpenSSL::CCM.new('AES', [KEY[j]].pack('H*'), MAC_LEN[j])
29
+ c = ccm.encrypt(input, [NONCE[j]].pack('H*'))
30
+ assert_equal(output.unpack('H*'), c.unpack('H*'),
31
+ "Wrong ENCRYPT in Vector #{i + 1}")
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: openssl-ccm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Lars Schmertmann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rdoc
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 4.1.1
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '4.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 4.1.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: yard
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.8'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.8.7.3
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '0.8'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.8.7.3
53
+ - !ruby/object:Gem::Dependency
54
+ name: rubocop
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '0.18'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 0.18.1
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '0.18'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 0.18.1
73
+ description: Ruby Gem for RFC 3610 - Counter with CBC-MAC (CCM)
74
+ email: SmallLars@t-online.de
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files:
78
+ - README.md
79
+ - LICENSE
80
+ files:
81
+ - Gemfile
82
+ - LICENSE
83
+ - README.md
84
+ - Rakefile
85
+ - lib/openssl-ccm.rb
86
+ - test/data_1
87
+ - test/data_1-1_e
88
+ - test/data_1-2_e
89
+ - test/data_1-3_e
90
+ - test/data_1-4_e
91
+ - test/data_2
92
+ - test/data_2-1_e
93
+ - test/data_2-2_e
94
+ - test/data_2-3_e
95
+ - test/data_2-4_e
96
+ - test/data_3
97
+ - test/data_3-1_e
98
+ - test/data_3-2_e
99
+ - test/data_3-3_e
100
+ - test/data_3-4_e
101
+ - test/test_ccm.rb
102
+ - test/test_ccm_data.rb
103
+ homepage: ''
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message: Thanks for installing!
108
+ rdoc_options:
109
+ - "-x"
110
+ - test/data_*
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 2.0.0
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.2.2
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: RFC 3610 - CCM
129
+ test_files:
130
+ - test/test_ccm.rb
131
+ - test/test_ccm_data.rb
132
+ - test/data_1-3_e
133
+ - test/data_1-1_e
134
+ - test/data_3
135
+ - test/data_3-4_e
136
+ - test/data_3-2_e
137
+ - test/data_2-2_e
138
+ - test/data_1-2_e
139
+ - test/data_1-4_e
140
+ - test/data_3-1_e
141
+ - test/data_3-3_e
142
+ - test/data_1
143
+ - test/data_2
144
+ - test/data_2-4_e
145
+ - test/data_2-1_e
146
+ - test/data_2-3_e
147
+ has_rdoc: