forked from wolfSSL/wolfssl
FIPS Revalidation
1. Add a copy of the DSA parameter generation function to DH for use without DSA.
This commit is contained in:
@ -1240,4 +1240,249 @@ int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g,
|
|||||||
return wc_DhSetKey_ex(key, p, pSz, g, gSz, NULL, 0);
|
return wc_DhSetKey_ex(key, p, pSz, g, gSz, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_KEY_GEN
|
||||||
|
|
||||||
|
/* modulus_size in bits */
|
||||||
|
int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh)
|
||||||
|
{
|
||||||
|
mp_int tmp, tmp2;
|
||||||
|
int groupSz, bufSz = 0,
|
||||||
|
primeCheckCount = 0,
|
||||||
|
primeCheck = MP_NO,
|
||||||
|
ret = 0;
|
||||||
|
unsigned char *buf = NULL;
|
||||||
|
|
||||||
|
if (rng == NULL || dh == NULL)
|
||||||
|
ret = BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* set group size in bytes from modulus size
|
||||||
|
* FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256)
|
||||||
|
*/
|
||||||
|
if (ret == 0) {
|
||||||
|
switch (modSz) {
|
||||||
|
case 1024:
|
||||||
|
groupSz = 20;
|
||||||
|
break;
|
||||||
|
case 2048:
|
||||||
|
case 3072:
|
||||||
|
groupSz = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = BAD_FUNC_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* modulus size in bytes */
|
||||||
|
modSz /= WOLFSSL_BIT_SIZE;
|
||||||
|
bufSz = modSz - groupSz;
|
||||||
|
|
||||||
|
/* allocate ram */
|
||||||
|
buf = (unsigned char *)XMALLOC(bufSz,
|
||||||
|
dh->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (buf == NULL)
|
||||||
|
ret = MEMORY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make a random string that will be multplied against q */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_RNG_GenerateBlock(rng, buf, bufSz);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* force magnitude */
|
||||||
|
buf[0] |= 0xC0;
|
||||||
|
/* force even */
|
||||||
|
buf[bufSz - 1] &= ~1;
|
||||||
|
|
||||||
|
if (mp_init_multi(&tmp, &tmp2, &dh->p, &dh->q, &dh->g, 0)
|
||||||
|
!= MP_OKAY) {
|
||||||
|
ret = MP_INIT_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
if (mp_read_unsigned_bin(&tmp2, buf, bufSz) != MP_OKAY)
|
||||||
|
ret = MP_READ_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make our prime q */
|
||||||
|
if (ret == 0) {
|
||||||
|
if (mp_rand_prime(&dh->q, groupSz, rng, NULL) != MP_OKAY)
|
||||||
|
ret = PRIME_GEN_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* p = random * q */
|
||||||
|
if (ret == 0) {
|
||||||
|
if (mp_mul(&dh->q, &tmp2, &dh->p) != MP_OKAY)
|
||||||
|
ret = MP_MUL_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* p = random * q + 1, so q is a prime divisor of p-1 */
|
||||||
|
if (ret == 0) {
|
||||||
|
if (mp_add_d(&dh->p, 1, &dh->p) != MP_OKAY)
|
||||||
|
ret = MP_ADD_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tmp = 2q */
|
||||||
|
if (ret == 0) {
|
||||||
|
if (mp_add(&dh->q, &dh->q, &tmp) != MP_OKAY)
|
||||||
|
ret = MP_ADD_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* loop until p is prime */
|
||||||
|
if (ret == 0) {
|
||||||
|
do {
|
||||||
|
if (mp_prime_is_prime(&dh->p, 8, &primeCheck) != MP_OKAY)
|
||||||
|
ret = PRIME_GEN_E;
|
||||||
|
|
||||||
|
if (primeCheck != MP_YES) {
|
||||||
|
/* p += 2q */
|
||||||
|
if (mp_add(&tmp, &dh->p, &dh->p) != MP_OKAY)
|
||||||
|
ret = MP_ADD_E;
|
||||||
|
else
|
||||||
|
primeCheckCount++;
|
||||||
|
}
|
||||||
|
} while (ret == 0 && primeCheck == MP_NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tmp2 += (2*loop_check_prime)
|
||||||
|
* to have p = (q * tmp2) + 1 prime
|
||||||
|
*/
|
||||||
|
if (primeCheckCount) {
|
||||||
|
if (mp_add_d(&tmp2, 2 * primeCheckCount, &tmp2) != MP_OKAY)
|
||||||
|
ret = MP_ADD_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find a value g for which g^tmp2 != 1 */
|
||||||
|
if (mp_set(&dh->g, 1) != MP_OKAY)
|
||||||
|
ret = MP_ZERO_E;
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
do {
|
||||||
|
if (mp_add_d(&dh->g, 1, &dh->g) != MP_OKAY)
|
||||||
|
ret = MP_ADD_E;
|
||||||
|
else if (mp_exptmod(&dh->g, &tmp2, &dh->p, &tmp) != MP_OKAY)
|
||||||
|
ret = MP_EXPTMOD_E;
|
||||||
|
} while (ret == 0 && mp_cmp_d(&tmp, 1) == MP_EQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* at this point tmp generates a group of order q mod p */
|
||||||
|
mp_exch(&tmp, &dh->g);
|
||||||
|
|
||||||
|
/* clear the parameters if there was an error */
|
||||||
|
if (ret != 0) {
|
||||||
|
mp_clear(&dh->q);
|
||||||
|
mp_clear(&dh->p);
|
||||||
|
mp_clear(&dh->g);
|
||||||
|
}
|
||||||
|
|
||||||
|
ForceZero(buf, bufSz);
|
||||||
|
XFREE(buf, dh->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
mp_clear(&tmp);
|
||||||
|
mp_clear(&tmp2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Export raw DH parameters from DhKey structure
|
||||||
|
*
|
||||||
|
* dh - pointer to initialized DhKey structure
|
||||||
|
* p - output location for DH (p) parameter
|
||||||
|
* pSz - [IN/OUT] size of output buffer for p, size of p
|
||||||
|
* q - output location for DH (q) parameter
|
||||||
|
* qSz - [IN/OUT] size of output buffer for q, size of q
|
||||||
|
* g - output location for DH (g) parameter
|
||||||
|
* gSz - [IN/OUT] size of output buffer for g, size of g
|
||||||
|
*
|
||||||
|
* If p, q, and g pointers are all passed in as NULL, the function
|
||||||
|
* will set pSz, qSz, and gSz to the required output buffer sizes for p,
|
||||||
|
* q, and g. In this case, the function will return LENGTH_ONLY_E.
|
||||||
|
*
|
||||||
|
* returns 0 on success, negative upon failure
|
||||||
|
*/
|
||||||
|
int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz,
|
||||||
|
byte* q, word32* qSz, byte* g, word32* gSz)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
word32 pLen, qLen, gLen;
|
||||||
|
|
||||||
|
if (dh == NULL || pSz == NULL || qSz == NULL || gSz == NULL)
|
||||||
|
ret = BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* get required output buffer sizes */
|
||||||
|
if (ret == 0) {
|
||||||
|
pLen = mp_unsigned_bin_size(&dh->p);
|
||||||
|
qLen = mp_unsigned_bin_size(&dh->q);
|
||||||
|
gLen = mp_unsigned_bin_size(&dh->g);
|
||||||
|
|
||||||
|
/* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */
|
||||||
|
if (p == NULL && q == NULL && g == NULL) {
|
||||||
|
*pSz = pLen;
|
||||||
|
*qSz = qLen;
|
||||||
|
*gSz = gLen;
|
||||||
|
ret = LENGTH_ONLY_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
if (p == NULL || q == NULL || g == NULL)
|
||||||
|
ret = BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* export p */
|
||||||
|
if (ret == 0) {
|
||||||
|
if (*pSz < pLen) {
|
||||||
|
WOLFSSL_MSG("Output buffer for DH p parameter too small, "
|
||||||
|
"required size placed into pSz");
|
||||||
|
*pSz = pLen;
|
||||||
|
ret = BUFFER_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
*pSz = pLen;
|
||||||
|
if (mp_to_unsigned_bin(&dh->p, p) != MP_OKAY)
|
||||||
|
ret = MP_TO_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* export q */
|
||||||
|
if (ret == 0) {
|
||||||
|
if (*qSz < qLen) {
|
||||||
|
WOLFSSL_MSG("Output buffer for DH q parameter too small, "
|
||||||
|
"required size placed into qSz");
|
||||||
|
*qSz = qLen;
|
||||||
|
ret = BUFFER_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
*qSz = qLen;
|
||||||
|
if (mp_to_unsigned_bin(&dh->q, q) != MP_OKAY)
|
||||||
|
ret = MP_TO_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* export g */
|
||||||
|
if (ret == 0) {
|
||||||
|
if (*gSz < gLen) {
|
||||||
|
WOLFSSL_MSG("Output buffer for DH g parameter too small, "
|
||||||
|
"required size placed into gSz");
|
||||||
|
*gSz = gLen;
|
||||||
|
ret = BUFFER_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
*gSz = gLen;
|
||||||
|
if (mp_to_unsigned_bin(&dh->g, g) != MP_OKAY)
|
||||||
|
ret = MP_TO_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WOLFSSL_KEY_GEN */
|
||||||
|
|
||||||
#endif /* NO_DH */
|
#endif /* NO_DH */
|
||||||
|
@ -10569,6 +10569,25 @@ static int dh_fips_generate_test(WC_RNG *rng)
|
|||||||
ret = -5727;
|
ret = -5727;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_KEY_GEN
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_DhGenerateParams(rng, 2048, &key);
|
||||||
|
if (ret != 0) {
|
||||||
|
ERROR_OUT(-8226, exit_gen_test);
|
||||||
|
}
|
||||||
|
|
||||||
|
privSz = sizeof(priv);
|
||||||
|
pubSz = sizeof(pub);
|
||||||
|
|
||||||
|
ret = wc_DhGenerateKeyPair(&key, rng, priv, &privSz, pub, &pubSz);
|
||||||
|
if (ret != 0) {
|
||||||
|
ret = -8227;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WOLFSSL_KEY_GEN */
|
||||||
|
|
||||||
exit_gen_test:
|
exit_gen_test:
|
||||||
wc_FreeDhKey(&key);
|
wc_FreeDhKey(&key);
|
||||||
|
|
||||||
|
@ -99,6 +99,10 @@ WOLFSSL_API int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p,
|
|||||||
WOLFSSL_API int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz);
|
WOLFSSL_API int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz);
|
||||||
WOLFSSL_API int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
|
WOLFSSL_API int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
|
||||||
const byte* prime, word32 primeSz);
|
const byte* prime, word32 primeSz);
|
||||||
|
WOLFSSL_API int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh);
|
||||||
|
WOLFSSL_API int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz,
|
||||||
|
byte* q, word32* qSz, byte* g, word32* gSz);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
Reference in New Issue
Block a user