add DSA 186-4 key generation

This commit is contained in:
Chris Conlon
2018-01-04 10:11:23 -07:00
parent 3f53e8d1dd
commit 61f6b9ce0f

View File

@@ -99,64 +99,126 @@ void wc_FreeDsaKey(DsaKey* key)
#ifdef WOLFSSL_KEY_GEN #ifdef WOLFSSL_KEY_GEN
/* validate that (L,N) match allowed sizes from FIPS 186-4, Section 4.2.
* l - represents L, the size of p in bits
* n - represents N, the size of q in bits
* return 0 on success, -1 on error */
static int CheckDsaLN(int l, int n)
{
int ret = -1;
switch (l) {
case 1024:
if (n == 160)
ret = 0;
break;
case 2048:
if (n == 224 || n == 256)
ret = 0;
break;
case 3072:
if (n == 256)
ret = 0;
break;
default:
break;
}
return ret;
}
/* Create DSA key pair (&dsa->x, &dsa->y)
*
* Based on NIST FIPS 186-4,
* "B.1.1 Key Pair Generation Using Extra Random Bits"
*
* rng - pointer to initialized WC_RNG structure
* dsa - pointer to initialized DsaKey structure, will hold generated key
*
* return 0 on success, negative on error */
int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa) int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa)
{ {
unsigned char *buf; byte* cBuf;
int qsize, err; int qSz, pSz, cSz, err;
mp_int tmpQ;
if (rng == NULL || dsa == NULL) if (rng == NULL || dsa == NULL)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
qsize = mp_unsigned_bin_size(&dsa->q); qSz = mp_unsigned_bin_size(&dsa->q);
if (qsize == 0) pSz = mp_unsigned_bin_size(&dsa->p);
/* verify (L,N) pair bit lengths */
if (CheckDsaLN(pSz * 8, qSz * 8) != 0)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
/* allocate ram */ /* generate extra 64 bits so that bias from mod function is negligible */
buf = (unsigned char *)XMALLOC(qsize, dsa->heap, cSz = qSz + 8;
DYNAMIC_TYPE_TMP_BUFFER); cBuf = (byte*)XMALLOC(cSz, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (buf == NULL) if (cBuf == NULL) {
return MEMORY_E; return MEMORY_E;
if (mp_init(&dsa->x) != MP_OKAY) {
XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
return MP_INIT_E;
} }
do { if ((err = mp_init_multi(&dsa->x, &dsa->y, &tmpQ, NULL, NULL, NULL))
/* make a random exponent mod q */ != MP_OKAY) {
err = wc_RNG_GenerateBlock(rng, buf, qsize); XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (err != MP_OKAY) {
mp_clear(&dsa->x);
XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
return err; return err;
} }
err = mp_read_unsigned_bin(&dsa->x, buf, qsize); do {
/* generate N+64 bits (c) from RBG into &dsa->x, making sure positive.
* Hash_DRBG uses SHA-256 which matches maximum
* requested_security_strength of (L,N) */
err = wc_RNG_GenerateBlock(rng, cBuf, cSz);
if (err != MP_OKAY) { if (err != MP_OKAY) {
mp_clear(&dsa->x); mp_clear(&dsa->x);
XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); mp_clear(&dsa->y);
mp_clear(&tmpQ);
XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
return err;
}
err = mp_read_unsigned_bin(&dsa->x, cBuf, cSz);
if (err != MP_OKAY) {
mp_clear(&dsa->x);
mp_clear(&dsa->y);
mp_clear(&tmpQ);
XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
return err; return err;
} }
} while (mp_cmp_d(&dsa->x, 1) != MP_GT); } while (mp_cmp_d(&dsa->x, 1) != MP_GT);
XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (mp_init(&dsa->y) != MP_OKAY) { /* tmpQ = q - 1 */
mp_clear(&dsa->x); if (err == MP_OKAY)
return MP_INIT_E; err = mp_copy(&dsa->q, &tmpQ);
}
if (err == MP_OKAY)
err = mp_sub_d(&tmpQ, 1, &tmpQ);
/* x = c mod (q-1), &dsa->x holds c */
if (err == MP_OKAY)
err = mp_mod(&dsa->x, &tmpQ, &dsa->x);
/* x = c mod (q-1) + 1 */
if (err == MP_OKAY)
err = mp_add_d(&dsa->x, 1, &dsa->x);
/* public key : y = g^x mod p */ /* public key : y = g^x mod p */
if (err == MP_OKAY)
err = mp_exptmod(&dsa->g, &dsa->x, &dsa->p, &dsa->y); err = mp_exptmod(&dsa->g, &dsa->x, &dsa->p, &dsa->y);
if (err == MP_OKAY)
dsa->type = DSA_PRIVATE;
if (err != MP_OKAY) { if (err != MP_OKAY) {
mp_clear(&dsa->x); mp_clear(&dsa->x);
mp_clear(&dsa->y); mp_clear(&dsa->y);
return err;
} }
mp_clear(&tmpQ);
dsa->type = DSA_PRIVATE; return err;
return MP_OKAY;
} }
/* modulus_size in bits */ /* modulus_size in bits */