Skip to content

Commit

Permalink
Rewrite nistkatrng and calculate nistkat checksum on board (#30)
Browse files Browse the repository at this point in the history
* nistkatrng license under apache-2.0

Signed-off-by: Thing-han, Lim <[email protected]>

* add sha3-256 checksum to META file and update the tests script for
nistkat testing

Signed-off-by: Thing-han, Lim <[email protected]>

* calculate sha3-256 sum on the board instead

Signed-off-by: Thing-han, Lim <[email protected]>

* minor refactoring of nistkat.c

Signed-off-by: Matthias J. Kannwischer <[email protected]>

* use shake256-256 instead of sha3

Signed-off-by: Thing-han, Lim <[email protected]>

---------

Signed-off-by: Thing-han, Lim <[email protected]>
Signed-off-by: Matthias J. Kannwischer <[email protected]>
Co-authored-by: Matthias J. Kannwischer <[email protected]>
  • Loading branch information
potsrevennil and mkannwischer authored Apr 29, 2024
1 parent 544e38a commit 4e03a70
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 105 deletions.
3 changes: 3 additions & 0 deletions META.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ implementations:
length-secret-key: 1632
length-shared-secret: 32
nistkat-sha256: 4b88ac7643ff60209af1175e025f354272e88df827a0ce1c056e403629b88e04
nistkat-shake256-256: 4b075815c72f4984e2290a2ebb62f6aa2c42bb386b9a210a78bf6ac73ee02cb8
- name: mlkem768
claimed-nist-level: 3
claimed-security: IND-CCA2
Expand All @@ -19,6 +20,7 @@ implementations:
length-secret-key: 2400
length-shared-secret: 32
nistkat-sha256: 21b4a1e1ea34a13c26a9da5eeb9325afb5ca11596ca6f3704c3f2637e3ea7524
nistkat-shake256-256: 3acd660b1b60808c1b8b02f499ffdc4bdacaaf35ec02a267b7a8e40dd4b26457
- name: mlkem1024
claimed-nist-level: 5
claimed-security: IND-CCA2
Expand All @@ -27,3 +29,4 @@ implementations:
length-secret-key: 3168
length-shared-secret: 32
nistkat-sha256: 6471398b0a728ee1ef39e93bb89b526fbf59587a3662edadbcfc6c88a512cd71
nistkat-shake256-256: e619f782857675c7d273139a48f8081652cc9c583c92aa4e627a2f36a7d943d1
1 change: 1 addition & 0 deletions mk/mps2-an386.mk
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ else
LIBHAL_SRC += \
test/common/nistkatrng.c \
test/common/aes.c
CPPFLAGS += -Itest/common
endif
endif

Expand Down
5 changes: 3 additions & 2 deletions scripts/tests
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python
# SPDX-License-Identifier: Apache-2.0
import sys
import serial
import hashlib
import platform
Expand Down Expand Up @@ -253,7 +254,7 @@ def nistkat(platform_cfg, verbose, emulate):
"--arg",
"scheme",
scheme,
'.implementations.[] | select(.name == $scheme) | ."nistkat-sha256"',
'.implementations.[] | select(.name == $scheme) | ."nistkat-shake256-256"',
"./META.yml",
],
capture_output=True,
Expand All @@ -269,7 +270,7 @@ def nistkat(platform_cfg, verbose, emulate):
platform_cfg,
0,
scheme_hash,
lambda output: hashlib.sha256(output).hexdigest(),
lambda output: str(output, encoding="utf-8").strip().lower(),
verbose,
)
except asyncio.CancelledError:
Expand Down
138 changes: 64 additions & 74 deletions test/common/nistkatrng.c
Original file line number Diff line number Diff line change
@@ -1,98 +1,88 @@
// SPDX-License-Identifier: CC0-1.0
// SPDX-License-Identifier: Apache-2.0

#include <assert.h>
#include <string.h>

#include "aes.h"
#include "randombytes.h"
#include "nistkatrng.h"

typedef struct {
uint8_t Key[32];
uint8_t V[16];
int reseed_counter;
} AES256_CTR_DRBG_struct;

static AES256_CTR_DRBG_struct DRBG_ctx;
static void AES256_CTR_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V);

// Use whatever AES implementation you have. This uses AES from openSSL library
// key - 256-bit AES key
// ctr - a 128-bit plaintext value
// buffer - a 128-bit ciphertext value
static void AES256_ECB(uint8_t *key, uint8_t *ctr, uint8_t *buffer) {
aes256ctx ctx;
aes256_ecb_keyexp(&ctx, key);
aes256_ecb(buffer, ctr, 1, &ctx);
aes256_ctx_release(&ctx);
unsigned char key[AES256_KEYBYTES];
unsigned char ctr[AES_BLOCKBYTES];
} nistkatctx;

static nistkatctx ctx;

static void _aes256_ecb(unsigned char key[AES256_KEYBYTES], unsigned char ctr[AES_BLOCKBYTES], unsigned char buffer[AES_BLOCKBYTES]) {
aes256ctx aesctx;
aes256_ecb_keyexp(&aesctx, key);
aes256_ecb(buffer, ctr, 1, &aesctx);
aes256_ctx_release(&aesctx);
}

void nist_kat_init(uint8_t *entropy_input, const uint8_t *personalization_string, int security_strength);
void nist_kat_init(uint8_t *entropy_input, const uint8_t *personalization_string, int security_strength) {
uint8_t seed_material[48];
static void aes256_block_update(uint8_t block[AES_BLOCKBYTES]) {
for (int j = AES_BLOCKBYTES - 1; j >= 0; j--) {
ctx.ctr[j]++;

assert(security_strength == 256);
memcpy(seed_material, entropy_input, 48);
if (personalization_string) {
for (int i = 0; i < 48; i++) {
seed_material[i] ^= personalization_string[i];
if (ctx.ctr[j] != 0x00) {
break;
}
}
memset(DRBG_ctx.Key, 0x00, 32);
memset(DRBG_ctx.V, 0x00, 16);
AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V);
DRBG_ctx.reseed_counter = 1;

_aes256_ecb(ctx.key, ctx.ctr, block);
}

int randombytes(uint8_t *buf, size_t n) {
uint8_t block[16];
int i = 0;

while (n > 0) {
//increment V
for (int j = 15; j >= 0; j--) {
if (DRBG_ctx.V[j] == 0xff) {
DRBG_ctx.V[j] = 0x00;
} else {
DRBG_ctx.V[j]++;
break;
}
}
AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block);
if (n > 15) {
memcpy(buf + i, block, 16);
i += 16;
n -= 16;
} else {
memcpy(buf + i, block, n);
n = 0;
static void nistkat_update(const unsigned char *provided_data, unsigned char *key, unsigned char *ctr) {
int len = AES256_KEYBYTES + AES_BLOCKBYTES;
uint8_t tmp[len];

for (int i = 0; i < len / AES_BLOCKBYTES; i++) {
aes256_block_update(tmp + AES_BLOCKBYTES * i);
}

if (provided_data) {
for (int i = 0; i < len; i++) {
tmp[i] ^= provided_data[i];
}
}
AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V);
DRBG_ctx.reseed_counter++;
return 0;

memcpy(key, tmp, AES256_KEYBYTES);
memcpy(ctr, tmp + AES256_KEYBYTES, AES_BLOCKBYTES);
}

static void AES256_CTR_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V) {
uint8_t temp[48];

for (int i = 0; i < 3; i++) {
//increment V
for (int j = 15; j >= 0; j--) {
if (V[j] == 0xff) {
V[j] = 0x00;
} else {
V[j]++;
break;
}
void randombytes_init(unsigned char entropy_input[AES256_KEYBYTES + AES_BLOCKBYTES], const unsigned char personalization_string[AES256_KEYBYTES + AES_BLOCKBYTES], int security_strength) {
int len = AES256_KEYBYTES + AES_BLOCKBYTES;
uint8_t seed_material[len];
(void) security_strength;

memcpy(seed_material, entropy_input, len);
if (personalization_string) {
for (int i = 0; i < len; i++) {
seed_material[i] ^= personalization_string[i];
}
}
memset(ctx.key, 0x00, AES256_KEYBYTES);
memset(ctx.ctr, 0x00, AES_BLOCKBYTES);
nistkat_update(seed_material, ctx.key, ctx.ctr);
}

int randombytes(uint8_t *buf, size_t n) {
uint8_t block[AES_BLOCKBYTES];

size_t nb = n / AES_BLOCKBYTES;
size_t tail = n % AES_BLOCKBYTES;

AES256_ECB(Key, V, temp + 16 * i);
for (size_t i = 0; i < nb; i++) {
aes256_block_update(block);
memcpy(buf + i * AES_BLOCKBYTES, block, AES_BLOCKBYTES);
}
if (provided_data != NULL) {
for (int i = 0; i < 48; i++) {
temp[i] ^= provided_data[i];
}

if (tail > 0) {
aes256_block_update(block);
memcpy(buf + nb * AES_BLOCKBYTES, block, tail);
}
memcpy(Key, temp, 32);
memcpy(V, temp + 32, 16);

nistkat_update(NULL, ctx.key, ctx.ctr);
return 0;
}
10 changes: 10 additions & 0 deletions test/common/nistkatrng.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: Apache-2.0

#ifndef NISTKATRNG_H
#define NISTKATRNG_H

#include "aes.h"

void randombytes_init(unsigned char entropy_input[AES256_KEYBYTES + AES_BLOCKBYTES], const unsigned char personalization_string[AES256_KEYBYTES + AES_BLOCKBYTES], int security_strength);

#endif
77 changes: 48 additions & 29 deletions test/nistkat.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "kem.h"
#include "hal.h"
#include "randombytes.h"
#include "nistkatrng.h"
#include "fips202.h"

// NOTE: used Kyber in the nistkat rsp file for now to avoid changing the checksum
#if (MLKEM_K == 2)
Expand All @@ -22,33 +24,44 @@
#define OLD_CRYPTO_ALGNAME "Kyber1024"
#endif

void nist_kat_init(unsigned char *entropy_input, unsigned char *personalization_string, int security_strength);

static void hal_send_Bstr(const char *S, const uint8_t *A, size_t L) {
size_t i;
char buf[16384];
size_t format_bstr(char *buf, const char *S, const uint8_t *A, size_t L) {
size_t len = strlen(S);
memcpy(buf, S, strlen(S));
for (i = 0; i < L; i++) {
snprintf(buf + strlen(S) + 2 * i, 3, "%02X", A[i]);
}
if (L == 0) {
snprintf(buf + strlen(S) + 2 * L, 3, "00");

for (size_t i = 0; i < L; i++) {
len += snprintf(buf + strlen(S) + 2 * i, 3, "%02X", A[i]);
}

return len;
}

void inc_hash_bstr(shake256incctx *state, const char *S, const uint8_t *A, size_t L) {
size_t len;
char buf[strlen(S) + 2 * L + 1];

len = format_bstr(buf, S, A, L);
len += snprintf(buf + strlen(S) + 2 * L, 2, "\n");

shake256_inc_absorb(state, (unsigned char *)buf, len);
}

void hal_send_bstr(const char *S, const uint8_t *A, size_t L) {
char buf[strlen(S) + 2 * L + 1];
format_bstr(buf, S, A, L);
hal_send_str(buf);
}

int hal_send_format(const char *S, ...) {
int result;
size_t inc_hash_format(shake256incctx *state, const char *S, ...) {
size_t len;
char buf[1024];
va_list args;
va_start(args, S);
result = vsnprintf(buf, 1024, S, args);
len = vsnprintf(buf, 1024, S, args);
va_end(args);

hal_send_str(buf);
shake256_inc_absorb(state, (unsigned char *)buf, len);

return result;
return len;
}

int main(void) {
Expand All @@ -60,6 +73,8 @@ int main(void) {
uint8_t ciphertext[CRYPTO_CIPHERTEXTBYTES];
uint8_t shared_secret_e[CRYPTO_BYTES];
uint8_t shared_secret_d[CRYPTO_BYTES];
uint8_t result[32];
shake256incctx hash_state;
int rc;

hal_setup(CLOCK_FAST);
Expand All @@ -69,38 +84,40 @@ int main(void) {
entropy_input[i] = i;
}

nist_kat_init(entropy_input, NULL, 256);
randombytes_init(entropy_input, NULL, 256);

for (size_t i = 0; i < counts; i++) {
randombytes(seeds[i], 48);
}

hal_send_format("# %s\n", OLD_CRYPTO_ALGNAME);
shake256_inc_init(&hash_state);

inc_hash_format(&hash_state, "# %s\n\n", OLD_CRYPTO_ALGNAME);

for (size_t i = 0; i < counts; i++) {
hal_send_format("count = %d", i);
nist_kat_init(seeds[i], NULL, 256);
hal_send_Bstr("seed = ", seeds[i], 48);
inc_hash_format(&hash_state, "count = %d\n", i);
randombytes_init(seeds[i], NULL, 256);
inc_hash_bstr(&hash_state, "seed = ", seeds[i], 48);

rc = crypto_kem_keypair(public_key, secret_key);
if (rc != 0) {
hal_send_format("[kat_kem] %s ERROR: crypto_kem_keypair failed!\n", CRYPTO_ALGNAME);
hal_send_str("ERROR: crypto_kem_keypair failed!");
return -1;
}
hal_send_Bstr("pk = ", public_key, CRYPTO_PUBLICKEYBYTES);
hal_send_Bstr("sk = ", secret_key, CRYPTO_SECRETKEYBYTES);
inc_hash_bstr(&hash_state, "pk = ", public_key, CRYPTO_PUBLICKEYBYTES);
inc_hash_bstr(&hash_state, "sk = ", secret_key, CRYPTO_SECRETKEYBYTES);

rc = crypto_kem_enc(ciphertext, shared_secret_e, public_key);
if (rc != 0) {
hal_send_format("[kat_kem] %s ERROR: crypto_kem_enc failed!\n", CRYPTO_ALGNAME);
hal_send_str("ERROR: crypto_kem_enc failed!");
return -2;
}
hal_send_Bstr("ct = ", ciphertext, CRYPTO_CIPHERTEXTBYTES);
hal_send_Bstr("ss = ", shared_secret_e, CRYPTO_BYTES);
inc_hash_bstr(&hash_state, "ct = ", ciphertext, CRYPTO_CIPHERTEXTBYTES);
inc_hash_bstr(&hash_state, "ss = ", shared_secret_e, CRYPTO_BYTES);

rc = crypto_kem_dec(shared_secret_d, ciphertext, secret_key);
if (rc != 0) {
hal_send_format("[kat_kem] %s ERROR: crypto_kem_dec failed!\n", CRYPTO_ALGNAME);
hal_send_str("ERROR: crypto_kem_dec failed!");
return -3;
}

Expand All @@ -110,10 +127,12 @@ int main(void) {
return -4;
}

hal_send_str("");
inc_hash_format(&hash_state, "\n");
}
shake256_inc_finalize(&hash_state);
shake256_inc_squeeze(result, 32, &hash_state);
hal_send_bstr("", result, 32);
SERIAL_MARKER();

return 0;

}

0 comments on commit 4e03a70

Please sign in to comment.