blob: abab788efcc1e4078fd620ec513e8248de7a49b7 [file] [log] [blame]
#!/usr/bin/python
# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module for generating AES test vectors."""
from binascii import b2a_hex as b2a
from Crypto.Cipher import AES
from itertools import izip_longest
import os
modes = {
AES.MODE_CBC: 'CBC',
AES.MODE_CFB: 'CFB',
AES.MODE_OFB: 'OFB',
}
template = \
'''
<crypto_test name="AES:{mode}{key_bits} {test_num}">
<clear_text format="hex">
{pt}
</clear_text>
<key>
{key}
</key>
<cipher_text>
{ct}
</cipher_text>
<iv>
{iv}
</iv>
</crypto_test>
'''
def h2be(v):
# Convert input big-endian byte-string to 4-byte segmented
# little-endian words. Pad-bytes (if necessary) are the empty string.
word = [iter(v)] * 4
return ''.join([
''.join(b[::-1]) for b in izip_longest(*word, fillvalue='')
])
for mode in [AES.MODE_CBC, AES.MODE_CFB, AES.MODE_OFB]:
for key_bytes in [16, 24, 32]:
test_num = 0
for pt_len in [5, 16, 21, 32]:
# CBC mode requires block sized inputs.
if mode == AES.MODE_CBC and pt_len % 16:
continue
test_num += 1
actual_pt_len = pt_len
if pt_len % 16:
pt_len = 16 * ((pt_len / 16) + 1)
key = os.urandom(key_bytes)
iv = os.urandom(16)
pt = os.urandom(pt_len)
obj = AES.new(key, mode=mode, IV=iv, segment_size=128)
ct = obj.encrypt(pt)
obj = AES.new(key, mode=mode, IV=iv, segment_size=128)
assert obj.decrypt(ct)[:pt_len] == pt
print template.format(mode=modes[mode],
key_bits=str(key_bytes * 8),
test_num=str(test_num),
pt=b2a(h2be(pt[:actual_pt_len])),
key=b2a(h2be(key)),
ct=b2a(h2be(ct[:actual_pt_len])),
iv=b2a(h2be(iv))),