Dilithium: Add KATs and fix key generation

Add KATs from NIST and fix key generation to produce output of KATs.
pull/7711/head
Sean Parkinson 2024-07-04 17:08:10 +10:00
parent 1c23d2222c
commit 387f36657c
3 changed files with 4475 additions and 15 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1897,9 +1897,9 @@ static int dilithium_expand_a(wc_Shake* shake128, const byte* pub_seed, byte k,
((b) < DILITHIUM_ETA_2_MOD) ((b) < DILITHIUM_ETA_2_MOD)
static const byte dilithium_coeff_eta2[] = { static const byte dilithium_coeff_eta2[] = {
-2, -1, 0, 1, 2, 2, 1, 0, -1, -2,
-2, -1, 0, 1, 2, 2, 1, 0, -1, -2,
-2, -1, 0, 1, 2 2, 1, 0, -1, -2
}; };
/* Convert random value 0..15 to a value in range of -2..2. /* Convert random value 0..15 to a value in range of -2..2.
* *
@ -2131,7 +2131,7 @@ static void dilithium_extract_coeffs(byte* z, unsigned int zLen, byte eta,
min &= ~(unsigned int)7; min &= ~(unsigned int)7;
/* Extract values from the squeezed data. */ /* Extract values from the squeezed data. */
for (c = 0; c < min; c += 8) { for (c = 0; c < min; c += 8) {
word64 z64 = *(word64*)z; word64 z64 = *(word64*)(z + c);
sword8 t; sword8 t;
/* Do each nibble from lowest to highest 16 at a time. */ /* Do each nibble from lowest to highest 16 at a time. */
@ -2156,7 +2156,7 @@ static void dilithium_extract_coeffs(byte* z, unsigned int zLen, byte eta,
min &= ~(unsigned int)3; min &= ~(unsigned int)3;
/* Extract values from the squeezed data. */ /* Extract values from the squeezed data. */
for (c = 0; c < min; c += 4) { for (c = 0; c < min; c += 4) {
word32 z32 = *(word32*)z; word32 z32 = *(word32*)(z + c);
sword8 t; sword8 t;
/* Do each nibble from lowest to highest 8 at a time. */ /* Do each nibble from lowest to highest 8 at a time. */
@ -2223,7 +2223,7 @@ static int dilithium_rej_bound_poly(wc_Shake* shake256, byte* seed, sword32* s,
ret = wc_InitShake256(shake256, NULL, INVALID_DEVID); ret = wc_InitShake256(shake256, NULL, INVALID_DEVID);
if (ret == 0) { if (ret == 0) {
/* Absorb the seed. */ /* Absorb the seed. */
ret = wc_Shake256_Absorb(shake256, seed, DILITHIUM_GEN_A_SEED_SZ); ret = wc_Shake256_Absorb(shake256, seed, DILITHIUM_GEN_S_SEED_SZ);
} }
if (ret == 0) { if (ret == 0) {
do { do {
@ -2303,7 +2303,7 @@ static int dilithium_expand_s(wc_Shake* shake256, byte* priv_seed, byte eta,
seed[DILITHIUM_PRIV_SEED_SZ + 1] = 0; seed[DILITHIUM_PRIV_SEED_SZ + 1] = 0;
/* Step 1: Each polynomial in s1. */ /* Step 1: Each polynomial in s1. */
for (r = 0; (ret == 0) && (r < s1Len); r++) { for (r = 0; (ret == 0) && (r < s1Len); r++) {
/* Set bottom 8-bits of r into buffer. */ /* Set bottom 8-bits of r into buffer - little endian. */
seed[DILITHIUM_PRIV_SEED_SZ] = r; seed[DILITHIUM_PRIV_SEED_SZ] = r;
/* Step 2: Generate polynomial for s1. */ /* Step 2: Generate polynomial for s1. */
@ -2313,7 +2313,7 @@ static int dilithium_expand_s(wc_Shake* shake256, byte* priv_seed, byte eta,
} }
/* Step 4: Each polynomial in s2. */ /* Step 4: Each polynomial in s2. */
for (r = 0; (ret == 0) && (r < s2Len); r++) { for (r = 0; (ret == 0) && (r < s2Len); r++) {
/* Set bottom 8-bits of r + l into buffer. */ /* Set bottom 8-bits of r + l into buffer - little endian. */
seed[DILITHIUM_PRIV_SEED_SZ] = r + s1Len; seed[DILITHIUM_PRIV_SEED_SZ] = r + s1Len;
/* Step 5: Generate polynomial for s1. */ /* Step 5: Generate polynomial for s1. */
ret = dilithium_rej_bound_poly(shake256, seed, s2, eta); ret = dilithium_rej_bound_poly(shake256, seed, s2, eta);
@ -3018,7 +3018,7 @@ static void dilithium_use_hint_32(sword32* w1, const byte* h, byte omega,
dilithium_decompose_q32(r, &r0, &r1); dilithium_decompose_q32(r, &r0, &r1);
/* Check for hint. */ /* Check for hint. */
if ((o < h[omega + i]) && (h[o] == (byte)j)) { if ((o < h[omega + i]) && (h[o] == (byte)j)) {
/* Add or subtrac hint based on sign of r0. */ /* Add or subtract hint based on sign of r0. */
r1 += 1 - (2 * (((word32)r0) >> 31)); r1 += 1 - (2 * (((word32)r0) >> 31));
/* Go to next hint offset. */ /* Go to next hint offset. */
o++; o++;
@ -4840,7 +4840,7 @@ static void dilithium_vec_make_pos(sword32* a, byte l)
* @return MEMORY_E when memory allocation fails. * @return MEMORY_E when memory allocation fails.
* @return Other negative when an error occurs. * @return Other negative when an error occurs.
*/ */
static int dilithium_make_key_from_seed(dilithium_key* key, byte* seed) static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed)
{ {
int ret = 0; int ret = 0;
const wc_dilithium_params* params = key->params; const wc_dilithium_params* params = key->params;
@ -4999,7 +4999,7 @@ static int dilithium_make_key(dilithium_key* key, WC_RNG* rng)
ret = wc_RNG_GenerateBlock(rng, seed, DILITHIUM_SEED_SZ); ret = wc_RNG_GenerateBlock(rng, seed, DILITHIUM_SEED_SZ);
if (ret == 0) { if (ret == 0) {
/* Make key with random seed. */ /* Make key with random seed. */
ret = dilithium_make_key_from_seed(key, seed); ret = wc_dilithium_make_key_from_seed(key, seed);
} }
return ret; return ret;
@ -5091,7 +5091,7 @@ static void dilithium_make_priv_vecs(dilithium_key* key, sword32* s1,
* 33: return sigma * 33: return sigma
* *
* @param [in, out] key Dilithium key. * @param [in, out] key Dilithium key.
* @param [in, out] rng Random number generator. * @param [in, out] seed Random seed.
* @param [in] msg Message data to sign. * @param [in] msg Message data to sign.
* @param [in] msgLen Length of message data in bytes. * @param [in] msgLen Length of message data in bytes.
* @param [out] sig Buffer to hold signature. * @param [out] sig Buffer to hold signature.
@ -5102,7 +5102,7 @@ static void dilithium_make_priv_vecs(dilithium_key* key, sword32* s1,
* @return MEMORY_E when memory allocation fails. * @return MEMORY_E when memory allocation fails.
* @return Other negative when an error occurs. * @return Other negative when an error occurs.
*/ */
static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* rnd, static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed,
const byte* msg, word32 msgLen, byte* sig, word32 *sigLen) const byte* msg, word32 msgLen, byte* sig, word32 *sigLen)
{ {
int ret = 0; int ret = 0;
@ -5228,7 +5228,7 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* rnd,
} }
if (ret == 0) { if (ret == 0) {
/* Step 7: Copy random into buffer for hashing. */ /* Step 7: Copy random into buffer for hashing. */
XMEMCPY(data, rnd, DILITHIUM_RND_SZ); XMEMCPY(data, seed, DILITHIUM_RND_SZ);
} }
if (ret == 0) { if (ret == 0) {
/* Step 9: Compute private random using hash. */ /* Step 9: Compute private random using hash. */
@ -5390,7 +5390,8 @@ static int dilithium_sign_msg(dilithium_key* key, WC_RNG* rng, const byte* msg,
} }
if (ret == 0) { if (ret == 0) {
/* Sign with random seed. */ /* Sign with random seed. */
ret = dilithium_sign_msg_with_seed(key, rnd, msg, msgLen, sig, sigLen); ret = dilithium_sign_msg_with_seed(key, rnd, msg, msgLen, sig,
sigLen);
} }
return ret; return ret;
@ -6025,6 +6026,34 @@ int wc_dilithium_make_key(dilithium_key* key, WC_RNG* rng)
return ret; return ret;
} }
int wc_dilithium_make_key_from_seed(dilithium_key* key, const byte* seed)
{
int ret = 0;
/* Validate parameters. */
if ((key == NULL) || (seed == NULL)) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
#ifdef WOLFSSL_WC_DILITHIUM
/* Check the level or parameters have been set. */
if (key->params == NULL) {
ret = BAD_STATE_E;
}
else {
/* Make the key. */
ret = dilithium_make_key_from_seed(key, seed);
}
#elif defined(HAVE_LIBOQS)
/* Make the key. */
ret = NOT_COMPILED_IN;
#endif
}
return ret;
}
#endif #endif
#ifndef WOLFSSL_DILITHIUM_NO_SIGN #ifndef WOLFSSL_DILITHIUM_NO_SIGN
@ -6077,6 +6106,42 @@ int wc_dilithium_sign_msg(const byte* msg, word32 msgLen, byte* sig,
return ret; return ret;
} }
/* Sign the message using the dilithium private key.
*
* msg [in] Message to sign.
* msgLen [in] Length of the message in bytes.
* sig [out] Buffer to write signature into.
* sigLen [in/out] On in, size of buffer.
* On out, the length of the signature in bytes.
* key [in] Dilithium key to use when signing
* returns BAD_FUNC_ARG when a parameter is NULL or public key not set,
* BUFFER_E when outLen is less than DILITHIUM_LEVEL2_SIG_SIZE,
* 0 otherwise.
*/
int wc_dilithium_sign_msg_with_seed(const byte* msg, word32 msgLen, byte* sig,
word32 *sigLen, dilithium_key* key, byte* seed)
{
int ret = 0;
/* Validate parameters. */
if ((msg == NULL) || (sig == NULL) || (sigLen == NULL) || (key == NULL)) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
/* Sign message. */
#ifdef WOLFSSL_WC_DILITHIUM
ret = dilithium_sign_msg_with_seed(key, seed, msg, msgLen, sig, sigLen);
#elif defined(HAVE_LIBOQS)
ret = NOT_COMPILED_IN;
(void)msgLen;
(void)seed;
#endif
}
return ret;
}
#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ #endif /* !WOLFSSL_DILITHIUM_NO_SIGN */
#ifndef WOLFSSL_DILITHIUM_NO_VERIFY #ifndef WOLFSSL_DILITHIUM_NO_VERIFY

View File

@ -591,10 +591,15 @@ struct dilithium_key {
#ifndef WOLFSSL_DILITHIUM_VERIFY_ONLY #ifndef WOLFSSL_DILITHIUM_VERIFY_ONLY
WOLFSSL_API WOLFSSL_API
int wc_dilithium_make_key(dilithium_key* key, WC_RNG* rng); int wc_dilithium_make_key(dilithium_key* key, WC_RNG* rng);
WOLFSSL_API
int wc_dilithium_make_key_from_seed(dilithium_key* key, const byte* seed);
WOLFSSL_API WOLFSSL_API
int wc_dilithium_sign_msg(const byte* in, word32 inLen, byte* out, int wc_dilithium_sign_msg(const byte* in, word32 inLen, byte* out,
word32 *outLen, dilithium_key* key, WC_RNG* rng); word32 *outLen, dilithium_key* key, WC_RNG* rng);
WOLFSSL_API
int wc_dilithium_sign_msg_with_seed(const byte* in, word32 inLen, byte* out,
word32 *outLen, dilithium_key* key, byte* seed);
#endif #endif
WOLFSSL_API WOLFSSL_API
int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg,