Skip to content

Commit

Permalink
Run HQC KATs with custom PRNG
Browse files Browse the repository at this point in the history
  • Loading branch information
SWilson4 committed Oct 23, 2023
1 parent 8474bad commit 7f8646a
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ liboqs includes some third party libraries or modules that are licensed differen
- `src/common/crypto/sha3/xkcp_low/.../brg_endian.h` : BSD 3-Clause License
- `src/common/crypto/sha3/xkcp_low/.../KeccakP-1600-AVX2.s` : BSD-like [CRYPTOGAMS license](http://www.openssl.org/~appro/cryptogams/)
- `src/common/rand/rand_nist.c`: See file
- TODO: update for hqc
- `src/kem/bike/additional`: Apache License v2.0
- `src/kem/classic_mceliece/pqclean_*`: public domain
- `src/kem/kyber/pqcrystals-*`: public domain (CC0) or Apache License v2.0
Expand Down
3 changes: 2 additions & 1 deletion src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ add_library(common OBJECT ${AES_IMPL}
pqclean_shims/fips202.c
pqclean_shims/fips202x4.c
rand/rand.c
rand/rand_nist.c)
rand/rand_nist.c
rand/rand_hqc.c)

if(${OQS_USE_OPENSSL})
target_include_directories(common PRIVATE ${OPENSSL_INCLUDE_DIR})
Expand Down
4 changes: 4 additions & 0 deletions src/common/rand/rand.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

void OQS_randombytes_system(uint8_t *random_array, size_t bytes_to_read);
void OQS_randombytes_nist_kat(uint8_t *random_array, size_t bytes_to_read);
void OQS_randombytes_hqc_kat(uint8_t *random_array, size_t bytes_to_read);
#ifdef OQS_USE_OPENSSL
void OQS_randombytes_openssl(uint8_t *random_array, size_t bytes_to_read);
#endif
Expand All @@ -37,6 +38,9 @@ OQS_API OQS_STATUS OQS_randombytes_switch_algorithm(const char *algorithm) {
} else if (0 == strcasecmp(OQS_RAND_alg_nist_kat, algorithm)) {
oqs_randombytes_algorithm = &OQS_randombytes_nist_kat;
return OQS_SUCCESS;
} else if (0 == strcasecmp(OQS_RAND_alg_hqc_kat, algorithm)) {
oqs_randombytes_algorithm = &OQS_randombytes_hqc_kat;
return OQS_SUCCESS;
} else if (0 == strcasecmp(OQS_RAND_alg_openssl, algorithm)) {
#ifdef OQS_USE_OPENSSL
oqs_randombytes_algorithm = &OQS_randombytes_openssl;
Expand Down
17 changes: 17 additions & 0 deletions src/common/rand/rand.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ extern "C" {
#define OQS_RAND_alg_system "system"
/** Algorithm identifier for NIST deterministic RNG for KATs. */
#define OQS_RAND_alg_nist_kat "NIST-KAT"
/** Algorithm identifier for HQC deterministic RNG for KATs. */
#define OQS_RAND_alg_hqc_kat "HQC-KAT"
/** Algorithm identifier for using OpenSSL's PRNG. */
#define OQS_RAND_alg_openssl "OpenSSL"

Expand Down Expand Up @@ -66,6 +68,21 @@ OQS_API void OQS_randombytes(uint8_t *random_array, size_t bytes_to_read);
*/
OQS_API void OQS_randombytes_nist_kat_init_256bit(const uint8_t *entropy_input, const uint8_t *personalization_string);

/**
* Initializes the HQC PRNG with a given seed.
* OQS_randombytes_hqc_kat_release should be called afterwards to clean up memory.
*
* @param[in] entropy_input The seed; must be exactly 48 bytes
* @param[in] personalization_string An optional personalization string;
* may be NULL; if not NULL, must be at least 48 bytes long
*/
OQS_API void OQS_randombytes_hqc_kat_init(const uint8_t *entropy_input, const uint8_t *personalization_string);

/**
* Releases the HQC PRNG context. Can be called safely even if OQS_randombytes_hqc_kat_init was not called.
*/
OQS_API void OQS_randombytes_hqc_kat_free(void);

#if defined(__cplusplus)
} // extern "C"
#endif
Expand Down
35 changes: 35 additions & 0 deletions src/common/rand/rand_hqc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "oqs/sha3.h"

#define PRNG_DOMAIN 1

// TODO document licence etc

OQS_SHA3_shake256_inc_ctx shake_prng_state = { NULL };

void OQS_randombytes_hqc_kat(uint8_t *buf, size_t n);

void OQS_randombytes_hqc_kat_init(const uint8_t *entropy_input, const uint8_t *personalization_string) {
uint8_t domain = PRNG_DOMAIN;
if (shake_prng_state.ctx != NULL) {
OQS_SHA3_shake256_inc_ctx_reset(&shake_prng_state);
} else {
OQS_SHA3_shake256_inc_init(&shake_prng_state);
}
OQS_SHA3_shake256_inc_absorb(&shake_prng_state, entropy_input, 48);
if (personalization_string) {
OQS_SHA3_shake256_inc_absorb(&shake_prng_state, personalization_string, 48);
}
OQS_SHA3_shake256_inc_absorb(&shake_prng_state, &domain, 1);
OQS_SHA3_shake256_inc_finalize(&shake_prng_state);
}

void OQS_randombytes_hqc_kat(uint8_t *buf, size_t n) {
OQS_SHA3_shake256_inc_squeeze(buf, n, &shake_prng_state);
}

void OQS_randombytes_hqc_kat_free() {
if (shake_prng_state.ctx != NULL) {
OQS_SHA3_shake256_inc_ctx_release(&shake_prng_state);
shake_prng_state.ctx = NULL;
}
}
32 changes: 29 additions & 3 deletions tests/kat_kem.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
//
// TODO fix leak

// This KAT test only generates a subset of the NIST KAT files.
// To extract the subset from a submission file, use the command:
Expand Down Expand Up @@ -37,6 +39,12 @@ static void fprintBstr(FILE *fp, const char *S, const uint8_t *A, size_t L) {
fprintf(fp, "\n");
}

static inline bool is_hqc(const char *method_name) {
return (0 == strcmp(method_name, OQS_KEM_alg_hqc_128))
|| (0 == strcmp(method_name, OQS_KEM_alg_hqc_192))
|| (0 == strcmp(method_name, OQS_KEM_alg_hqc_256));
}

static OQS_STATUS kem_kat(const char *method_name) {

uint8_t entropy_input[48];
Expand All @@ -50,6 +58,7 @@ static OQS_STATUS kem_kat(const char *method_name) {
uint8_t *shared_secret_d = NULL;
OQS_STATUS rc, ret = OQS_ERROR;
int rv;
char *rand_alg;

kem = OQS_KEM_new(method_name);
if (kem == NULL) {
Expand All @@ -61,19 +70,33 @@ static OQS_STATUS kem_kat(const char *method_name) {
entropy_input[i] = i;
}

rc = OQS_randombytes_switch_algorithm(OQS_RAND_alg_nist_kat);
rand_alg = OQS_RAND_alg_nist_kat;
if (is_hqc(method_name)) {
rand_alg = OQS_RAND_alg_hqc_kat;
}
rc = OQS_randombytes_switch_algorithm(rand_alg);
if (rc != OQS_SUCCESS) {
goto err;
}
OQS_randombytes_nist_kat_init_256bit(entropy_input, NULL);

if (is_hqc(method_name)) {
OQS_randombytes_hqc_kat_init(entropy_input, NULL);
} else {
OQS_randombytes_nist_kat_init_256bit(entropy_input, NULL);
}

fh = stdout;

fprintf(fh, "count = 0\n");
OQS_randombytes(seed, 48);
fprintBstr(fh, "seed = ", seed, 48);

OQS_randombytes_nist_kat_init_256bit(seed, NULL);
if (is_hqc(method_name)) {
OQS_randombytes_hqc_kat_init(seed, NULL);
} else {
OQS_randombytes_nist_kat_init_256bit(seed, NULL);
}


public_key = malloc(kem->length_public_key);
secret_key = malloc(kem->length_secret_key);
Expand Down Expand Up @@ -131,6 +154,9 @@ static OQS_STATUS kem_kat(const char *method_name) {
OQS_MEM_secure_free(shared_secret_e, kem->length_shared_secret);
OQS_MEM_secure_free(shared_secret_d, kem->length_shared_secret);
}
if (is_hqc(method_name)) {
OQS_randombytes_hqc_kat_free();
}
OQS_MEM_insecure_free(public_key);
OQS_MEM_insecure_free(ciphertext);
OQS_KEM_free(kem);
Expand Down

0 comments on commit 7f8646a

Please sign in to comment.