blob: 1a55ac1b9c011546d4155f3efd5f479343005bf8 [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/memory.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"
static const char kSecretKey[] = "Secret test key.";
static const char kPlaintext[] =
"Muchos años después, frente al pelotón de fusilamiento, el coronel "
"Aureliano Buendía había de recordar aquella tarde remota en que su "
"padre lo llevó a conocer el hielo.";
// AES-CTR encrypted using all zeroes IV.
static const uint32_t kCiphertext[] = {
0x141cf4f1, 0xdcbf3c9b, 0x41c1e909, 0x0202d9f7, 0x27000325, 0x882033f3,
0xd77b0a50, 0x92425836, 0x72733658, 0x3f80eeef, 0x250086fe, 0x1f015d22,
0x7054e010, 0xaef95ca9, 0xb446fd50, 0x6bef787d, 0x564e1dcc, 0xe3650cc0,
0xa75a3298, 0xa0e7a3b8, 0x7d91ca73, 0x034ea236, 0x6cc76e1c, 0xb6b333ab,
0x4989dfa4, 0x41a7e22b, 0x5d41f04f, 0x7b49b3c6, 0x127e7daa, 0x081306e0,
0x60d9450c, 0xc7e08a02, 0x353f0dc2, 0x59e33d60, 0x35900057, 0xec8901d5,
0xb28a4979, 0x52340cc1, 0x95ca3392, 0xfc4d8a32, 0x981cd522, 0x7dab4b1e,
0xc3352eb6, 0x008ee548, 0x00000000, 0x00000000,
};
const test_config_t kTestConfig;
bool test_main(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.
uint32_t share0[4];
uint32_t share1[4];
memcpy(share0, kSecretKey, ARRAYSIZE(kSecretKey));
for (int i = 0; i < ARRAYSIZE(share0); ++i) {
if (i % 2 == 0) {
share0[i] = ~share0[i];
share1[i] = -1;
} else {
share1[i] = ~share0[i];
share0[i] = -1;
}
}
LOG_INFO("Configuring the AES hardware.");
CHECK(aes_begin((aes_params_t){
.encrypt = true,
.mode = kAesCipherModeCtr,
.key_len = kAesKeyLen128,
.key = {share0, share1},
.iv = {0},
}) == kAesOk);
// NOTE: ARRAYSIZE(kPlaintext) is not a multiple of the block size!
uint32_t ciphertext[ARRAYSIZE(kCiphertext)] = {0};
char *cipherptr = (char *)&ciphertext[0];
for (size_t i = 0;; i += sizeof(aes_block_t)) {
LOG_INFO("Processing block %d.", i / sizeof(aes_block_t));
size_t bytes_left = ARRAYSIZE(kPlaintext) - i;
size_t len = sizeof(aes_block_t);
if (len > bytes_left) {
len = bytes_left;
}
size_t bytes_left_prev = ARRAYSIZE(kPlaintext) - i + sizeof(aes_block_t);
size_t len_prev = sizeof(aes_block_t);
if (len_prev > bytes_left_prev) {
len_prev = bytes_left_prev;
}
LOG_INFO("Block len: %d/%d.", len, len_prev);
aes_block_t in = {0};
aes_block_t out = {0};
if (i == 0) {
memcpy(&in, &kPlaintext[i], len);
CHECK(aes_update(NULL, &in) == kAesOk);
} else if (i >= ARRAYSIZE(kPlaintext)) {
CHECK(aes_update(&out, NULL) == kAesOk);
memcpy(cipherptr + i - sizeof(out), &out, len_prev);
break;
} else {
memcpy(&in, &kPlaintext[i], len);
CHECK(aes_update(&out, &in) == kAesOk);
memcpy(cipherptr + i - sizeof(out), &out, len_prev);
}
}
CHECK_ARRAYS_EQ(ciphertext, kCiphertext, ARRAYSIZE(kCiphertext));
LOG_INFO("Cleaning up.");
CHECK(aes_end() == kAesOk);
return true;
}