SHAKE: add a test for custom delimiters with the MSB set

This commit is contained in:
Frank Denis
2025-12-30 00:42:54 +01:00
parent 32f787a79b
commit 7a58f66b43
4 changed files with 324 additions and 0 deletions
+81
View File
@@ -9,6 +9,66 @@ typedef struct {
size_t out_len;
} testvector;
static void
shake128_manual_with_domain(unsigned char *out, size_t outlen, const unsigned char *in,
size_t inlen, unsigned char domain)
{
unsigned char state[crypto_core_keccak1600_STATEBYTES];
size_t rate = crypto_xof_shake128_blockbytes();
size_t offset = 0;
size_t consumed = 0;
size_t chunk_size;
size_t extracted = 0;
unsigned char pad;
crypto_core_keccak1600_init(state);
while (consumed < inlen) {
if (offset == rate) {
crypto_core_keccak1600_permute_24(state);
offset = 0;
}
chunk_size = rate - offset;
if (chunk_size > inlen - consumed) {
chunk_size = inlen - consumed;
}
crypto_core_keccak1600_xor_bytes(state, &in[consumed], offset, chunk_size);
offset += chunk_size;
consumed += chunk_size;
}
if (offset == rate) {
crypto_core_keccak1600_permute_24(state);
offset = 0;
}
if (offset == rate - 1) {
pad = (unsigned char) (domain ^ 0x80);
crypto_core_keccak1600_xor_bytes(state, &pad, offset, 1);
} else {
crypto_core_keccak1600_xor_bytes(state, &domain, offset, 1);
pad = 0x80;
crypto_core_keccak1600_xor_bytes(state, &pad, rate - 1, 1);
}
crypto_core_keccak1600_permute_24(state);
offset = 0;
while (extracted < outlen) {
if (offset == rate) {
crypto_core_keccak1600_permute_24(state);
offset = 0;
}
chunk_size = rate - offset;
if (chunk_size > outlen - extracted) {
chunk_size = outlen - extracted;
}
crypto_core_keccak1600_extract_bytes(state, &out[extracted], offset, chunk_size);
offset += chunk_size;
extracted += chunk_size;
}
}
int
main(void)
{
@@ -129,6 +189,27 @@ main(void)
return 1;
}
/* Test domain byte with MSB set when padding overlaps */
{
unsigned char msg[crypto_xof_shake128_BLOCKBYTES - 1];
unsigned char out_manual[32];
unsigned char out_impl[32];
const unsigned char domain = 0x99;
memset(msg, 0xAA, sizeof msg);
shake128_manual_with_domain(out_manual, sizeof out_manual, msg, sizeof msg, domain);
crypto_xof_shake128_init_with_domain(&state, domain);
crypto_xof_shake128_update(&state, msg, sizeof msg);
crypto_xof_shake128_squeeze(&state, out_impl, sizeof out_impl);
if (memcmp(out_manual, out_impl, sizeof out_manual) != 0) {
printf("Domain MSB padding test failed\n");
return 1;
}
}
printf("All SHAKE-128 tests passed\n");
return 0;
}
+81
View File
@@ -9,6 +9,66 @@ typedef struct {
size_t out_len;
} testvector;
static void
shake256_manual_with_domain(unsigned char *out, size_t outlen, const unsigned char *in,
size_t inlen, unsigned char domain)
{
unsigned char state[crypto_core_keccak1600_STATEBYTES];
size_t rate = crypto_xof_shake256_blockbytes();
size_t offset = 0;
size_t consumed = 0;
size_t chunk_size;
size_t extracted = 0;
unsigned char pad;
crypto_core_keccak1600_init(state);
while (consumed < inlen) {
if (offset == rate) {
crypto_core_keccak1600_permute_24(state);
offset = 0;
}
chunk_size = rate - offset;
if (chunk_size > inlen - consumed) {
chunk_size = inlen - consumed;
}
crypto_core_keccak1600_xor_bytes(state, &in[consumed], offset, chunk_size);
offset += chunk_size;
consumed += chunk_size;
}
if (offset == rate) {
crypto_core_keccak1600_permute_24(state);
offset = 0;
}
if (offset == rate - 1) {
pad = (unsigned char) (domain ^ 0x80);
crypto_core_keccak1600_xor_bytes(state, &pad, offset, 1);
} else {
crypto_core_keccak1600_xor_bytes(state, &domain, offset, 1);
pad = 0x80;
crypto_core_keccak1600_xor_bytes(state, &pad, rate - 1, 1);
}
crypto_core_keccak1600_permute_24(state);
offset = 0;
while (extracted < outlen) {
if (offset == rate) {
crypto_core_keccak1600_permute_24(state);
offset = 0;
}
chunk_size = rate - offset;
if (chunk_size > outlen - extracted) {
chunk_size = outlen - extracted;
}
crypto_core_keccak1600_extract_bytes(state, &out[extracted], offset, chunk_size);
offset += chunk_size;
extracted += chunk_size;
}
}
int
main(void)
{
@@ -130,6 +190,27 @@ main(void)
return 1;
}
/* Test domain byte with MSB set when padding overlaps */
{
unsigned char msg[crypto_xof_shake256_BLOCKBYTES - 1];
unsigned char out_manual[32];
unsigned char out_impl[32];
const unsigned char domain = 0x99;
memset(msg, 0xAA, sizeof msg);
shake256_manual_with_domain(out_manual, sizeof out_manual, msg, sizeof msg, domain);
crypto_xof_shake256_init_with_domain(&state, domain);
crypto_xof_shake256_update(&state, msg, sizeof msg);
crypto_xof_shake256_squeeze(&state, out_impl, sizeof out_impl);
if (memcmp(out_manual, out_impl, sizeof out_manual) != 0) {
printf("Domain MSB padding test failed\n");
return 1;
}
}
printf("All SHAKE-256 tests passed\n");
return 0;
}
+81
View File
@@ -9,6 +9,66 @@ typedef struct {
size_t out_len;
} testvector;
static void
turboshake128_manual_with_domain(unsigned char *out, size_t outlen, const unsigned char *in,
size_t inlen, unsigned char domain)
{
unsigned char state[crypto_core_keccak1600_STATEBYTES];
size_t rate = crypto_xof_turboshake128_blockbytes();
size_t offset = 0;
size_t consumed = 0;
size_t chunk_size;
size_t extracted = 0;
unsigned char pad;
crypto_core_keccak1600_init(state);
while (consumed < inlen) {
if (offset == rate) {
crypto_core_keccak1600_permute_12(state);
offset = 0;
}
chunk_size = rate - offset;
if (chunk_size > inlen - consumed) {
chunk_size = inlen - consumed;
}
crypto_core_keccak1600_xor_bytes(state, &in[consumed], offset, chunk_size);
offset += chunk_size;
consumed += chunk_size;
}
if (offset == rate) {
crypto_core_keccak1600_permute_12(state);
offset = 0;
}
if (offset == rate - 1) {
pad = (unsigned char) (domain ^ 0x80);
crypto_core_keccak1600_xor_bytes(state, &pad, offset, 1);
} else {
crypto_core_keccak1600_xor_bytes(state, &domain, offset, 1);
pad = 0x80;
crypto_core_keccak1600_xor_bytes(state, &pad, rate - 1, 1);
}
crypto_core_keccak1600_permute_12(state);
offset = 0;
while (extracted < outlen) {
if (offset == rate) {
crypto_core_keccak1600_permute_12(state);
offset = 0;
}
chunk_size = rate - offset;
if (chunk_size > outlen - extracted) {
chunk_size = outlen - extracted;
}
crypto_core_keccak1600_extract_bytes(state, &out[extracted], offset, chunk_size);
offset += chunk_size;
extracted += chunk_size;
}
}
int
main(void)
{
@@ -129,6 +189,27 @@ main(void)
return 1;
}
/* Test domain byte with MSB set when padding overlaps */
{
unsigned char msg[crypto_xof_turboshake128_BLOCKBYTES - 1];
unsigned char out_manual[32];
unsigned char out_impl[32];
const unsigned char domain = 0x99;
memset(msg, 0xAA, sizeof msg);
turboshake128_manual_with_domain(out_manual, sizeof out_manual, msg, sizeof msg, domain);
crypto_xof_turboshake128_init_with_domain(&state, domain);
crypto_xof_turboshake128_update(&state, msg, sizeof msg);
crypto_xof_turboshake128_squeeze(&state, out_impl, sizeof out_impl);
if (memcmp(out_manual, out_impl, sizeof out_manual) != 0) {
printf("Domain MSB padding test failed\n");
return 1;
}
}
printf("All TurboSHAKE-128 tests passed\n");
return 0;
}
+81
View File
@@ -9,6 +9,66 @@ typedef struct {
size_t out_len;
} testvector;
static void
turboshake256_manual_with_domain(unsigned char *out, size_t outlen, const unsigned char *in,
size_t inlen, unsigned char domain)
{
unsigned char state[crypto_core_keccak1600_STATEBYTES];
size_t rate = crypto_xof_turboshake256_blockbytes();
size_t offset = 0;
size_t consumed = 0;
size_t chunk_size;
size_t extracted = 0;
unsigned char pad;
crypto_core_keccak1600_init(state);
while (consumed < inlen) {
if (offset == rate) {
crypto_core_keccak1600_permute_12(state);
offset = 0;
}
chunk_size = rate - offset;
if (chunk_size > inlen - consumed) {
chunk_size = inlen - consumed;
}
crypto_core_keccak1600_xor_bytes(state, &in[consumed], offset, chunk_size);
offset += chunk_size;
consumed += chunk_size;
}
if (offset == rate) {
crypto_core_keccak1600_permute_12(state);
offset = 0;
}
if (offset == rate - 1) {
pad = (unsigned char) (domain ^ 0x80);
crypto_core_keccak1600_xor_bytes(state, &pad, offset, 1);
} else {
crypto_core_keccak1600_xor_bytes(state, &domain, offset, 1);
pad = 0x80;
crypto_core_keccak1600_xor_bytes(state, &pad, rate - 1, 1);
}
crypto_core_keccak1600_permute_12(state);
offset = 0;
while (extracted < outlen) {
if (offset == rate) {
crypto_core_keccak1600_permute_12(state);
offset = 0;
}
chunk_size = rate - offset;
if (chunk_size > outlen - extracted) {
chunk_size = outlen - extracted;
}
crypto_core_keccak1600_extract_bytes(state, &out[extracted], offset, chunk_size);
offset += chunk_size;
extracted += chunk_size;
}
}
int
main(void)
{
@@ -129,6 +189,27 @@ main(void)
return 1;
}
/* Test domain byte with MSB set when padding overlaps */
{
unsigned char msg[crypto_xof_turboshake256_BLOCKBYTES - 1];
unsigned char out_manual[32];
unsigned char out_impl[32];
const unsigned char domain = 0x99;
memset(msg, 0xAA, sizeof msg);
turboshake256_manual_with_domain(out_manual, sizeof out_manual, msg, sizeof msg, domain);
crypto_xof_turboshake256_init_with_domain(&state, domain);
crypto_xof_turboshake256_update(&state, msg, sizeof msg);
crypto_xof_turboshake256_squeeze(&state, out_impl, sizeof out_impl);
if (memcmp(out_manual, out_impl, sizeof out_manual) != 0) {
printf("Domain MSB padding test failed\n");
return 1;
}
}
printf("All TurboSHAKE-256 tests passed\n");
return 0;
}