blob: 74547a6a7cce2bba11a3aeed04830f71f8e361e7 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/crypto/drivers/aes.h"
#include "sw/device/lib/base/hardened_status.h"
#include "sw/device/lib/base/memory.h"
#include "sw/device/lib/crypto/impl/status.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
// NIST 800-38a F.5.1 CTR-AES128.Encrypt test vectors.
static const uint32_t kSecretKey[] = {
// Key: 2b7e151628aed2a6abf7158809cf4f3c
0x16157e2b,
0xa6d2ae28,
0x8815f7ab,
0x3c4fcf09,
};
static const aes_block_t kIv = {
.data =
{
// Init Counter: f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
0xf3f2f1f0,
0xf7f6f5f4,
0xfbfaf9f8,
0xfffefdfc,
},
};
static const aes_block_t kPlaintext[] = {
// Block#1: 6bc1bee22e409f96e93d7e117393172a
{.data = 0xe2bec16b, 0x969f402e, 0x117e3de9, 0x2a179373},
// Block#2: ae2d8a571e03ac9c9eb76fac45af8e51
{.data = 0x578a2dae, 0x9cac031e, 0xac6fb79e, 0x518eaf45},
// Block#3: 30c81c46a35ce411e5fbc1191a0a52ef
{.data = 0x461cc830, 0x11e45ca3, 0x19c1fbe5, 0xef520a1a},
// Block#4: f69f2445df4f9b17ad2b417be66c3710
{.data = 0x45249ff6, 0x179b4fdf, 0x7b412bad, 0x10376ce6},
};
static const aes_block_t kCiphertext[] = {
// Block#1: 874d6191b620e3261bef6864990db6ce
{.data = 0x91614d87, 0x26e320b6, 0x6468ef1b, 0xceb60d99},
// Block#2: 9806f66b7970fdff8617187bb9fffdff
{.data = 0x6bf60698, 0xfffd7079, 0x7b181786, 0xfffdffb9},
// Block#3: 5ae4df3edbd5d35e5b4f09020db03eab
{.data = 0x3edfe45a, 0x5ed3d5db, 0x02094f5b, 0xab3eb00d},
// Block#4: 1e031dda2fbe03d1792170a0f3009cee
{.data = 0xda1d031e, 0xd103be2f, 0xa0702179, 0xee9c00f3},
};
static status_t run_aes_test(void) {
// This is a weak share intended to exercise correct configuration of the
// hardware; in general, the key should be generated by either generating
// two shares and setting key = a ^ b, or generating a mask and setting
// a = key ^ mask, b = mask.
const uint32_t share0[8] = {~kSecretKey[0],
~kSecretKey[1],
~kSecretKey[2],
~kSecretKey[3],
0,
0,
0,
0};
const uint32_t share1[8] = {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX,
0, 0, 0, 0};
LOG_INFO("Configuring the AES hardware.");
aes_key_t key = {
.mode = kAesCipherModeCtr,
.sideload = kHardenedBoolFalse,
.key_len = kAesKeyLen128,
.key_shares = {share0, share1},
};
TRY(aes_encrypt_begin(key, &kIv));
aes_block_t ciphertext[ARRAYSIZE(kCiphertext)] = {0};
aes_block_t *out = NULL;
for (size_t i = 0; i < ARRAYSIZE(kPlaintext); ++i) {
LOG_INFO("Processing block %d.", i);
TRY(aes_update(out, &kPlaintext[i]));
out = &ciphertext[i];
}
TRY(aes_update(out, NULL));
CHECK_ARRAYS_EQ((uint32_t *)ciphertext, (uint32_t *)kCiphertext,
sizeof(ciphertext) / (sizeof(uint32_t)));
LOG_INFO("Cleaning up.");
TRY(aes_end());
return OTCRYPTO_OK;
}
OTTF_DEFINE_TEST_CONFIG();
bool test_main(void) {
CHECK_STATUS_OK(run_aes_test());
return true;
}