Skip to content

Commit

Permalink
Update cipher validation to be case-insensitive
Browse files Browse the repository at this point in the history
  • Loading branch information
SmallLars committed Jun 27, 2019
1 parent 5bc92b6 commit ce58e94
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 53 deletions.
8 changes: 3 additions & 5 deletions lib/openssl/cmac.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ class CMAC
#
# @return [[String]] supported algorithms
def self.ciphers
l = OpenSSL::Cipher.ciphers.keep_if { |c| c.end_with?('-128-CBC') }
l.length.times { |i| l[i] = l[i][0..-9] }
l
@ciphers ||= OpenSSL::Cipher.ciphers.select { |c| c.match(/-128-CBC$/i) }.map { |e| e[0..-9].upcase }.uniq
end

# Returns the authentication code as a binary string. The cipher parameter
Expand Down Expand Up @@ -56,13 +54,13 @@ def self.digest(cipher, key, data, length = 16)
#
# @return [Object] the new CMAC object
def initialize(cipher, key = '')
unless CMAC.ciphers.include?(cipher)
unless CMAC.ciphers.include?(cipher.upcase)
fail CMACError, "unsupported cipher algorithm (#{cipher})"
end

@keys = []
@buffer = ''.force_encoding('ASCII-8BIT')
@cipher = OpenSSL::Cipher.new("#{cipher}-128-CBC")
@cipher = OpenSSL::Cipher.new("#{cipher.upcase}-128-CBC")

self.key = key unless key == ''
end
Expand Down
100 changes: 52 additions & 48 deletions test/test_cmac.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,39 +87,41 @@ def test_cmac_vars
end

def test_cmac_update
# Test with 1 call of update and new CCM object for each test.
DATA.length.times do |i|
cmac = OpenSSL::CMAC.new('AES', KEY)
m = cmac.update(DATA[i]).digest.unpack('H*')[0]
assert_equal(MAC[i], m, "Test: 1, Vector: #{i + 1}")
end
for cipher in ['aes', 'AES']
# Test with 1 call of update and new CCM object for each test.
DATA.length.times do |i|
cmac = OpenSSL::CMAC.new(cipher, KEY)
m = cmac.update(DATA[i]).digest.unpack('H*')[0]
assert_equal(MAC[i], m, "Test: 1, Vector: #{i + 1}")
end

# Test with 1 call of update and same CCM object for each test.
# There is no reset, because it should be possible to calculate
# a new mac after digest without reset.
cmac = OpenSSL::CMAC.new('AES', KEY)
DATA.length.times do |i|
m = cmac.update(DATA[i]).digest.unpack('H*')[0]
assert_equal(MAC[i], m, "Test: 2, Vector: #{i + 1}")
end
# Test with 1 call of update and same CCM object for each test.
# There is no reset, because it should be possible to calculate
# a new mac after digest without reset.
cmac = OpenSSL::CMAC.new(cipher, KEY)
DATA.length.times do |i|
m = cmac.update(DATA[i]).digest.unpack('H*')[0]
assert_equal(MAC[i], m, "Test: 2, Vector: #{i + 1}")
end

# Test with multiple calls of update and new CCM object for each test
1.upto(DATA.length - 1) do |i|
1.upto(17) do |c|
cmac = OpenSSL::CMAC.new('AES', KEY)
DATA[i].bytes.each_slice(c) { |w| cmac.update(w.pack('C*')) }
m = cmac.digest.unpack('H*')[0]
assert_equal(MAC[i], m, "Test: 3, Vector: #{i + 1}, Tokenlen: #{c}")
# Test with multiple calls of update and new CCM object for each test
1.upto(DATA.length - 1) do |i|
1.upto(17) do |c|
cmac = OpenSSL::CMAC.new(cipher, KEY)
DATA[i].bytes.each_slice(c) { |w| cmac.update(w.pack('C*')) }
m = cmac.digest.unpack('H*')[0]
assert_equal(MAC[i], m, "Test: 3, Vector: #{i + 1}, Tokenlen: #{c}")
end
end
end

# Test with multiple calls of update and same CCM object for each test
cmac = OpenSSL::CMAC.new('AES', KEY)
1.upto(DATA.length - 1) do |i|
1.upto(17) do |c|
DATA[i].bytes.each_slice(c) { |w| cmac.update(w.pack('C*')) }
m = cmac.digest.unpack('H*')[0]
assert_equal(MAC[i], m, "Test: 4, Vector: #{i + 1}, Tokenlen: #{c}")
# Test with multiple calls of update and same CCM object for each test
cmac = OpenSSL::CMAC.new(cipher, KEY)
1.upto(DATA.length - 1) do |i|
1.upto(17) do |c|
DATA[i].bytes.each_slice(c) { |w| cmac.update(w.pack('C*')) }
m = cmac.digest.unpack('H*')[0]
assert_equal(MAC[i], m, "Test: 4, Vector: #{i + 1}, Tokenlen: #{c}")
end
end
end

Expand All @@ -130,25 +132,27 @@ def test_cmac_update
end

def test_cmac_digest
cmac = OpenSSL::CMAC.new('AES', KEY)
m = cmac.update(DATA[3]).digest.unpack('H*')[0]
assert_equal(MAC[3], m, 'Digest with no update')

cmac.update(DATA[3].b[0...20])
m = cmac.update(DATA[3].b[20...64]).digest.unpack('H*')[0]
assert_equal(MAC[3], m, 'Digest after update')

cmac.update(DATA[3])
m = cmac.update('').digest.unpack('H*')[0]
assert_equal(MAC[3], m, 'Empty digest')

DATA.length.times do |i|
m = OpenSSL::CMAC.digest('AES', KEY, DATA[i]).unpack('H*')[0]
assert_equal(MAC[i], m, "Vector: #{i + 1}")

m = OpenSSL::CMAC.digest('AES', KEY, DATA[i], 12).unpack('H*')[0]
assert_equal(24, m.length, "Vector: #{i + 1} - length")
assert_equal(MAC[i][0...24], m, "Vector: #{i + 1} - 12")
for cipher in ['aes', 'AES']
cmac = OpenSSL::CMAC.new(cipher, KEY)
m = cmac.update(DATA[3]).digest.unpack('H*')[0]
assert_equal(MAC[3], m, 'Digest with no update')

cmac.update(DATA[3].b[0...20])
m = cmac.update(DATA[3].b[20...64]).digest.unpack('H*')[0]
assert_equal(MAC[3], m, 'Digest after update')

cmac.update(DATA[3])
m = cmac.update('').digest.unpack('H*')[0]
assert_equal(MAC[3], m, 'Empty digest')

DATA.length.times do |i|
m = OpenSSL::CMAC.digest(cipher, KEY, DATA[i]).unpack('H*')[0]
assert_equal(MAC[i], m, "Vector: #{i + 1}")

m = OpenSSL::CMAC.digest(cipher, KEY, DATA[i], 12).unpack('H*')[0]
assert_equal(24, m.length, "Vector: #{i + 1} - length")
assert_equal(MAC[i][0...24], m, "Vector: #{i + 1} - 12")
end
end
end

Expand Down

0 comments on commit ce58e94

Please sign in to comment.