|  | // 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; | 
|  | } |