#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 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."""
import os
from Crypto.Cipher import AES
modes = {
AES.MODE_CBC: 'CBC',
AES.MODE_CFB: 'CFB',
AES.MODE_OFB: 'OFB',
}
template = \
"""
{pt}
{key}
{ct}
{iv}
"""
def h2be(v):
"""Convert input big-endian byte-string to 4-byte segmented
Convert input big-endian byte-string to 4-byte segmented
little-endian words. Pad-bytes (if necessary) are the empty string.
"""
out = b''
while v:
out += int.from_bytes(v[:4].ljust(4, bytes([0])), 'big')\
.to_bytes(4, 'little')[4-len(v[:4]):]
v = v[4:]
return out
print('')
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=h2be(pt[:actual_pt_len]).hex(),
key=h2be(key).hex(),
ct=h2be(ct[:actual_pt_len]).hex(),
iv=h2be(iv).hex()))
print('')