blob: 8142be6dce2b4cc6ca670174dde40d5bb9e967cd [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/arch/device.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_kmac.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"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
OTTF_DEFINE_TEST_CONFIG();
#define DIGEST_LEN_KMAC_MAX 100
/**
* KMAC test description.
*/
typedef struct kmac_test {
dif_kmac_mode_kmac_t mode;
dif_kmac_key_t key;
const char *message;
size_t message_len;
const char *customization_string;
size_t customization_string_len;
const uint32_t digest[DIGEST_LEN_KMAC_MAX];
size_t digest_len;
bool digest_len_is_fixed;
} kmac_test_t;
/**
* KMAC tests.
*
* KMAC examples taken from:
* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf
*
* KMACXOF examples taken from:
* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMACXOF_samples.pdf
*/
const kmac_test_t kmac_tests[] = {
// KMAC
{
.mode = kDifKmacModeKmacLen128,
.key =
(dif_kmac_key_t){
.share0 = {0x43424140, 0x47464544, 0x4B4A4948, 0x4F4E4D4C,
0x53525150, 0x57565554, 0x5B5A5958, 0x5F5E5D5C},
.share1 = {0},
.length = kDifKmacKeyLen256,
},
.message = "\x00\x01\x02\x03",
.message_len = 4,
.customization_string = "",
.customization_string_len = 0,
.digest = {0x0D0B78E5, 0xD3F7A63E, 0x70C529A4, 0x003AA46A, 0xD4D7DBFA,
0x9E832896, 0x3F248731, 0x4EE16E45},
.digest_len = 8,
.digest_len_is_fixed = true,
},
{
.mode = kDifKmacModeKmacLen256,
.key =
(dif_kmac_key_t){
.share0 = {0x43424140, 0x47464544, 0x4B4A4948, 0x4F4E4D4C,
0x53525150, 0x57565554, 0x5B5A5958, 0x5F5E5D5C},
.share1 = {0},
.length = kDifKmacKeyLen256,
},
.message =
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
"\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
.message_len = 200,
.customization_string = "My Tagged Application",
.customization_string_len = 21,
.digest = {0xF71886B5, 0xD5E1921F, 0x558C1B6C, 0x18CDD7DD, 0xCAB4978B,
0x1E83994D, 0x839A69B2, 0xD9E4A27D, 0xFDACFB70, 0xAE3300E5,
0xA2F185A5, 0xC3108570, 0x0888072D, 0x2818BD01, 0x6847FE98,
0x6589FC76},
.digest_len = 16,
.digest_len_is_fixed = true,
},
{
.mode = kDifKmacModeKmacLen128,
.key =
(dif_kmac_key_t){
.share0 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15},
.share1 = {0},
.length = kDifKmacKeyLen512,
},
.message = "OpenTitan",
.message_len = 9,
.customization_string =
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
.customization_string_len = 32,
.digest = {0x0A77209A, 0x81797CFC, 0x6C6A61AA, 0x87E02697, 0xFC583498,
0x924C7FD8, 0xD7E11A80, 0xCEBFD97E, 0x5D01E715, 0xE197129F,
0xCED75441, 0x3A08D021, 0xBBACB3CA, 0x353539F9, 0xCD225ACE,
0x07C377A5, 0xDEB816E7, 0x6102E338, 0xBA1BA63C, 0x9FD50F0E,
0x2B2F632E, 0xABC632E1, 0xF44E5360, 0x01618ABD, 0xCEA93A18,
0xA25E1479, 0xACE0387A, 0x8CC8E65A, 0xC5323FBD, 0xCE278A2F,
0x6E5C6CD4, 0xDEF0B252, 0xC9569830, 0xDCD1E15A, 0x01592E1D,
0x6D41FBEC, 0x7625B67E, 0x2E6FDC71, 0x753253F6, 0xCBE2EE7B,
0x94B3F8AB, 0x5F7B9F4B, 0x9C32B704, 0xB75D2CD2, 0x2B9BF8D5,
0xF0C43941, 0x070A972F, 0x29039D89, 0x985B43BE, 0x3739526F,
0xEB9DE9FE, 0xE885D4EB, 0x147B854A, 0xF39840A4, 0x927FCEEF,
0xAA41A128, 0xBF85C5C4, 0x492D7E2B, 0xC39FC808, 0x260A3D02,
0x0EAB74F2, 0xFE7B8A99, 0xF77C71F7, 0x49D69382, 0x7B8405D4,
0x3D55F0F9, 0x551EAD0B, 0x53D648D0, 0x1820BAEB, 0x8D94C965,
0x079BC208, 0xD4D2742F, 0x8496D429, 0x464B6D3A, 0x34899027,
0x940B6F55, 0x154F43FB, 0x8C39F574, 0x89E07C5F, 0xE10F713B,
0x8B638E35, 0x16F0BFCE, 0x21CB26F8, 0x0A25F977, 0xAD944F1B,
0x6B8A6DB7, 0x0ABD1C91, 0x18E2C5AF, 0xE9AF73F5, 0x79CD8C86,
0x6830AD6F, 0x9EA2CC45, 0xA70D1807, 0x38993A63, 0xC2BF657E,
0x7CE11825, 0x98774D38, 0x9DB867E7, 0xB5F8CBFB, 0x86B242D5},
.digest_len = 100,
.digest_len_is_fixed = true,
},
// KMACXOF
{
.mode = kDifKmacModeKmacLen128,
.key =
(dif_kmac_key_t){
.share0 = {0x43424140, 0x47464544, 0x4B4A4948, 0x4F4E4D4C,
0x53525150, 0x57565554, 0x5B5A5958, 0x5F5E5D5C},
.share1 = {0},
.length = kDifKmacKeyLen256,
},
.message = "\x00\x01\x02\x03",
.message_len = 4,
.customization_string = "",
.customization_string_len = 0,
.digest = {0x0B7483CD, 0xC8CC92BD, 0x142B03CF, 0x46F4A081, 0xDDA97C0E,
0x0C8AB012, 0x8B173140, 0x35ECD6AC},
.digest_len = 8,
.digest_len_is_fixed = false,
},
{
.mode = kDifKmacModeKmacLen256,
.key =
(dif_kmac_key_t){
.share0 = {0x43424140, 0x47464544, 0x4B4A4948, 0x4F4E4D4C,
0x53525150, 0x57565554, 0x5B5A5958, 0x5F5E5D5C},
.share1 = {0},
.length = kDifKmacKeyLen256,
},
.message =
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
"\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
.message_len = 200,
.customization_string = "My Tagged Application",
.customization_string_len = 21,
.digest = {0x1C73BED5, 0x73D74E95, 0x59BB4628, 0xE3A8E3DB, 0x7AE7830F,
0x5944FF4B, 0xB4C2F1F2, 0xCEB8EBEC, 0xC601BA67, 0x57B88A2E,
0x9B492D8D, 0x6727BBD1, 0x90117868, 0x6A300A02, 0x1D28DE97,
0x5D3030CC},
.digest_len = 16,
.digest_len_is_fixed = false,
},
};
bool test_main(void) {
LOG_INFO("Running KMAC DIF test...");
// Intialize KMAC hardware.
dif_kmac_t kmac;
dif_kmac_operation_state_t kmac_operation_state;
CHECK_DIF_OK(
dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
// Configure KMAC hardware using software entropy.
dif_kmac_config_t config = (dif_kmac_config_t){
.entropy_mode = kDifKmacEntropyModeSoftware,
.entropy_seed = {0xaa25b4bf, 0x48ce8fff, 0x5a78282a, 0x48465647,
0x70410fef},
.entropy_fast_process = kDifToggleEnabled,
};
CHECK_DIF_OK(dif_kmac_configure(&kmac, config));
// Run fixed length KMAC test cases using single blocking absorb/squeeze
// operations.
for (int i = 0; i < ARRAYSIZE(kmac_tests); ++i) {
kmac_test_t test = kmac_tests[i];
dif_kmac_customization_string_t s;
CHECK_DIF_OK(dif_kmac_customization_string_init(
test.customization_string, test.customization_string_len, &s));
// Use NULL for empty strings to exercise that code path.
dif_kmac_customization_string_t *sp =
test.customization_string_len == 0 ? NULL : &s;
size_t l = test.digest_len_is_fixed ? test.digest_len : 0;
CHECK_DIF_OK(dif_kmac_mode_kmac_start(&kmac, &kmac_operation_state,
test.mode, l, &test.key, sp));
CHECK_DIF_OK(dif_kmac_absorb(&kmac, &kmac_operation_state, test.message,
test.message_len, NULL));
uint32_t out[DIGEST_LEN_KMAC_MAX];
CHECK(DIGEST_LEN_KMAC_MAX >= test.digest_len);
CHECK_DIF_OK(dif_kmac_squeeze(&kmac, &kmac_operation_state, out,
test.digest_len, NULL));
CHECK_DIF_OK(dif_kmac_end(&kmac, &kmac_operation_state));
for (int j = 0; j < test.digest_len; ++j) {
CHECK(out[j] == test.digest[j],
"test %d: mismatch at %d got=0x%x want=0x%x", i, j, out[j],
test.digest[j]);
}
}
return true;
}