diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-01-04 14:24:24 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-01-04 14:24:24 +0000 |
commit | dc1565216a5d20ae0d75872151523252309a1292 (patch) | |
tree | d57454ba9a40386552179eddf60d28bd1e8f3d54 /nss/lib/freebl/dh.c | |
parent | 26c046fbc57d53136b4fb3b5e0d18298318125d4 (diff) | |
download | nss-dc1565216a5d20ae0d75872151523252309a1292.tar.gz |
nss-3.28.1nss-3.28.1
Diffstat (limited to 'nss/lib/freebl/dh.c')
-rw-r--r-- | nss/lib/freebl/dh.c | 322 |
1 files changed, 172 insertions, 150 deletions
diff --git a/nss/lib/freebl/dh.c b/nss/lib/freebl/dh.c index 66c1101..97025c7 100644 --- a/nss/lib/freebl/dh.c +++ b/nss/lib/freebl/dh.c @@ -27,21 +27,21 @@ dh_GetSecretKeyLen(unsigned int primeLen) { /* Based on Table 2 in NIST SP 800-57. */ if (primeLen >= 1920) { /* 15360 bits */ - return 64; /* 512 bits */ + return 64; /* 512 bits */ } if (primeLen >= 960) { /* 7680 bits */ - return 48; /* 384 bits */ + return 48; /* 384 bits */ } if (primeLen >= 384) { /* 3072 bits */ - return 32; /* 256 bits */ + return 32; /* 256 bits */ } if (primeLen >= 256) { /* 2048 bits */ - return 28; /* 224 bits */ + return 28; /* 224 bits */ } - return 20; /* 160 bits */ + return 20; /* 160 bits */ } -SECStatus +SECStatus DH_GenParam(int primeLen, DHParams **params) { PLArenaPool *arena; @@ -53,19 +53,19 @@ DH_GenParam(int primeLen, DHParams **params) mp_err err = MP_OKAY; SECStatus rv = SECSuccess; if (!params || primeLen < 0) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE); if (!arena) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; } dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams)); if (!dhparams) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - PORT_FreeArena(arena, PR_TRUE); - return SECFailure; + PORT_SetError(SEC_ERROR_NO_MEMORY); + PORT_FreeArena(arena, PR_TRUE); + return SECFailure; } dhparams->arena = arena; MP_DIGITS(&p) = 0; @@ -74,42 +74,42 @@ DH_GenParam(int primeLen, DHParams **params) MP_DIGITS(&h) = 0; MP_DIGITS(&psub1) = 0; MP_DIGITS(&test) = 0; - CHECK_MPI_OK( mp_init(&p) ); - CHECK_MPI_OK( mp_init(&q) ); - CHECK_MPI_OK( mp_init(&a) ); - CHECK_MPI_OK( mp_init(&h) ); - CHECK_MPI_OK( mp_init(&psub1) ); - CHECK_MPI_OK( mp_init(&test) ); + CHECK_MPI_OK(mp_init(&p)); + CHECK_MPI_OK(mp_init(&q)); + CHECK_MPI_OK(mp_init(&a)); + CHECK_MPI_OK(mp_init(&h)); + CHECK_MPI_OK(mp_init(&psub1)); + CHECK_MPI_OK(mp_init(&test)); /* generate prime with MPI, uses Miller-Rabin to generate strong prime. */ pb = PORT_Alloc(primeLen); - CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) ); - pb[0] |= 0x80; /* set high-order bit */ - pb[primeLen-1] |= 0x01; /* set low-order bit */ - CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) ); - CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter) ); + CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(pb, primeLen)); + pb[0] |= 0x80; /* set high-order bit */ + pb[primeLen - 1] |= 0x01; /* set low-order bit */ + CHECK_MPI_OK(mp_read_unsigned_octets(&p, pb, primeLen)); + CHECK_MPI_OK(mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter)); /* construct Sophie-Germain prime q = (p-1)/2. */ - CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) ); - CHECK_MPI_OK( mp_div_2(&psub1, &q) ); + CHECK_MPI_OK(mp_sub_d(&p, 1, &psub1)); + CHECK_MPI_OK(mp_div_2(&psub1, &q)); /* construct a generator from the prime. */ ab = PORT_Alloc(primeLen); /* generate a candidate number a in p's field */ - CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(ab, primeLen) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&a, ab, primeLen) ); + CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(ab, primeLen)); + CHECK_MPI_OK(mp_read_unsigned_octets(&a, ab, primeLen)); /* force a < p (note that quot(a/p) <= 1) */ - if ( mp_cmp(&a, &p) > 0 ) - CHECK_MPI_OK( mp_sub(&a, &p, &a) ); + if (mp_cmp(&a, &p) > 0) + CHECK_MPI_OK(mp_sub(&a, &p, &a)); do { - /* check that a is in the range [2..p-1] */ - if ( mp_cmp_d(&a, 2) < 0 || mp_cmp(&a, &psub1) >= 0) { - /* a is outside of the allowed range. Set a=3 and keep going. */ + /* check that a is in the range [2..p-1] */ + if (mp_cmp_d(&a, 2) < 0 || mp_cmp(&a, &psub1) >= 0) { + /* a is outside of the allowed range. Set a=3 and keep going. */ mp_set(&a, 3); - } - /* if a**q mod p != 1 then a is a generator */ - CHECK_MPI_OK( mp_exptmod(&a, &q, &p, &test) ); - if ( mp_cmp_d(&test, 1) != 0 ) - break; - /* increment the candidate and try again. */ - CHECK_MPI_OK( mp_add_d(&a, 1, &a) ); + } + /* if a**q mod p != 1 then a is a generator */ + CHECK_MPI_OK(mp_exptmod(&a, &q, &p, &test)); + if (mp_cmp_d(&test, 1) != 0) + break; + /* increment the candidate and try again. */ + CHECK_MPI_OK(mp_add_d(&a, 1, &a)); } while (PR_TRUE); MPINT_TO_SECITEM(&p, &dhparams->prime, arena); MPINT_TO_SECITEM(&a, &dhparams->base, arena); @@ -121,65 +121,67 @@ cleanup: mp_clear(&h); mp_clear(&psub1); mp_clear(&test); - if (pb) PORT_ZFree(pb, primeLen); - if (ab) PORT_ZFree(ab, primeLen); + if (pb) + PORT_ZFree(pb, primeLen); + if (ab) + PORT_ZFree(ab, primeLen); if (err) { - MP_TO_SEC_ERROR(err); - rv = SECFailure; + MP_TO_SEC_ERROR(err); + rv = SECFailure; } if (rv) - PORT_FreeArena(arena, PR_TRUE); + PORT_FreeArena(arena, PR_TRUE); return rv; } -SECStatus +SECStatus DH_NewKey(DHParams *params, DHPrivateKey **privKey) { PLArenaPool *arena; DHPrivateKey *key; mp_int g, xa, p, Ya; - mp_err err = MP_OKAY; + mp_err err = MP_OKAY; SECStatus rv = SECSuccess; if (!params || !privKey) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE); if (!arena) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; } key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey)); if (!key) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - PORT_FreeArena(arena, PR_TRUE); - return SECFailure; + PORT_SetError(SEC_ERROR_NO_MEMORY); + PORT_FreeArena(arena, PR_TRUE); + return SECFailure; } key->arena = arena; - MP_DIGITS(&g) = 0; + MP_DIGITS(&g) = 0; MP_DIGITS(&xa) = 0; - MP_DIGITS(&p) = 0; + MP_DIGITS(&p) = 0; MP_DIGITS(&Ya) = 0; - CHECK_MPI_OK( mp_init(&g) ); - CHECK_MPI_OK( mp_init(&xa) ); - CHECK_MPI_OK( mp_init(&p) ); - CHECK_MPI_OK( mp_init(&Ya) ); + CHECK_MPI_OK(mp_init(&g)); + CHECK_MPI_OK(mp_init(&xa)); + CHECK_MPI_OK(mp_init(&p)); + CHECK_MPI_OK(mp_init(&Ya)); /* Set private key's p */ - CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->prime, ¶ms->prime) ); + CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->prime, ¶ms->prime)); SECITEM_TO_MPINT(key->prime, &p); /* Set private key's g */ - CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, ¶ms->base) ); + CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->base, ¶ms->base)); SECITEM_TO_MPINT(key->base, &g); /* Generate private key xa */ SECITEM_AllocItem(arena, &key->privateValue, dh_GetSecretKeyLen(params->prime.len)); - RNG_GenerateGlobalRandomBytes(key->privateValue.data, - key->privateValue.len); - SECITEM_TO_MPINT( key->privateValue, &xa ); + CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(key->privateValue.data, + key->privateValue.len)); + SECITEM_TO_MPINT(key->privateValue, &xa); /* xa < p */ - CHECK_MPI_OK( mp_mod(&xa, &p, &xa) ); + CHECK_MPI_OK(mp_mod(&xa, &p, &xa)); /* Compute public key Ya = g ** xa mod p */ - CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) ); + CHECK_MPI_OK(mp_exptmod(&g, &xa, &p, &Ya)); MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena); *privKey = key; cleanup: @@ -188,19 +190,21 @@ cleanup: mp_clear(&p); mp_clear(&Ya); if (err) { - MP_TO_SEC_ERROR(err); - rv = SECFailure; + MP_TO_SEC_ERROR(err); + rv = SECFailure; + } + if (rv) { + *privKey = NULL; + PORT_FreeArena(arena, PR_TRUE); } - if (rv) - PORT_FreeArena(arena, PR_TRUE); return rv; } -SECStatus -DH_Derive(SECItem *publicValue, - SECItem *prime, - SECItem *privateValue, - SECItem *derivedSecret, +SECStatus +DH_Derive(SECItem *publicValue, + SECItem *prime, + SECItem *privateValue, + SECItem *derivedSecret, unsigned int outBytes) { mp_int p, Xa, Yb, ZZ, psub1; @@ -209,24 +213,24 @@ DH_Derive(SECItem *publicValue, unsigned int nb; unsigned char *secret = NULL; if (!publicValue || !prime || !privateValue || !derivedSecret) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } memset(derivedSecret, 0, sizeof *derivedSecret); - MP_DIGITS(&p) = 0; + MP_DIGITS(&p) = 0; MP_DIGITS(&Xa) = 0; MP_DIGITS(&Yb) = 0; MP_DIGITS(&ZZ) = 0; MP_DIGITS(&psub1) = 0; - CHECK_MPI_OK( mp_init(&p) ); - CHECK_MPI_OK( mp_init(&Xa) ); - CHECK_MPI_OK( mp_init(&Yb) ); - CHECK_MPI_OK( mp_init(&ZZ) ); - CHECK_MPI_OK( mp_init(&psub1) ); - SECITEM_TO_MPINT(*publicValue, &Yb); + CHECK_MPI_OK(mp_init(&p)); + CHECK_MPI_OK(mp_init(&Xa)); + CHECK_MPI_OK(mp_init(&Yb)); + CHECK_MPI_OK(mp_init(&ZZ)); + CHECK_MPI_OK(mp_init(&psub1)); + SECITEM_TO_MPINT(*publicValue, &Yb); SECITEM_TO_MPINT(*privateValue, &Xa); - SECITEM_TO_MPINT(*prime, &p); - CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) ); + SECITEM_TO_MPINT(*prime, &p); + CHECK_MPI_OK(mp_sub_d(&p, 1, &psub1)); /* We assume that the modulus, p, is a safe prime. That is, p = 2q+1 where * q is also a prime. Thus the orders of the subgroups are factors of 2q: @@ -239,13 +243,13 @@ DH_Derive(SECItem *publicValue, * * Thus we must be operating in the subgroup of size q or 2q. */ if (mp_cmp_d(&Yb, 1) <= 0 || - mp_cmp(&Yb, &psub1) >= 0) { - err = MP_BADARG; - goto cleanup; + mp_cmp(&Yb, &psub1) >= 0) { + err = MP_BADARG; + goto cleanup; } /* ZZ = (Yb)**Xa mod p */ - CHECK_MPI_OK( mp_exptmod(&Yb, &Xa, &p, &ZZ) ); + CHECK_MPI_OK(mp_exptmod(&Yb, &Xa, &p, &ZZ)); /* number of bytes in the derived secret */ len = mp_unsigned_octet_size(&ZZ); if (len <= 0) { @@ -272,26 +276,34 @@ DH_Derive(SECItem *publicValue, /* allocate a buffer which can hold the entire derived secret. */ secret = PORT_Alloc(len); + if (secret == NULL) { + err = MP_MEM; + goto cleanup; + } /* grab the derived secret */ err = mp_to_unsigned_octets(&ZZ, secret, len); - if (err >= 0) err = MP_OKAY; - /* + if (err >= 0) + err = MP_OKAY; + /* ** if outBytes is 0 take all of the bytes from the derived secret. ** if outBytes is not 0 take exactly outBytes from the derived secret, zero - ** pad at the beginning if necessary, and truncate beginning bytes + ** pad at the beginning if necessary, and truncate beginning bytes ** if necessary. */ if (outBytes > 0) - nb = outBytes; + nb = outBytes; else - nb = len; - SECITEM_AllocItem(NULL, derivedSecret, nb); + nb = len; + if (SECITEM_AllocItem(NULL, derivedSecret, nb) == NULL) { + err = MP_MEM; + goto cleanup; + } if (len < nb) { - unsigned int offset = nb - len; - memset(derivedSecret->data, 0, offset); - memcpy(derivedSecret->data + offset, secret, len); + unsigned int offset = nb - len; + memset(derivedSecret->data, 0, offset); + memcpy(derivedSecret->data + offset, secret, len); } else { - memcpy(derivedSecret->data, secret + len - nb, nb); + memcpy(derivedSecret->data, secret + len - nb, nb); } cleanup: mp_clear(&p); @@ -300,23 +312,23 @@ cleanup: mp_clear(&ZZ); mp_clear(&psub1); if (secret) { - /* free the buffer allocated for the full secret. */ - PORT_ZFree(secret, len); + /* free the buffer allocated for the full secret. */ + PORT_ZFree(secret, len); } if (err) { - MP_TO_SEC_ERROR(err); - if (derivedSecret->data) - PORT_ZFree(derivedSecret->data, derivedSecret->len); - return SECFailure; + MP_TO_SEC_ERROR(err); + if (derivedSecret->data) + PORT_ZFree(derivedSecret->data, derivedSecret->len); + return SECFailure; } return SECSuccess; } -SECStatus -KEA_Derive(SECItem *prime, - SECItem *public1, - SECItem *public2, - SECItem *private1, +SECStatus +KEA_Derive(SECItem *prime, + SECItem *public1, + SECItem *public2, + SECItem *private1, SECItem *private2, SECItem *derivedSecret) { @@ -326,8 +338,8 @@ KEA_Derive(SECItem *prime, unsigned int len = 0, offset; if (!prime || !public1 || !public2 || !private1 || !private2 || !derivedSecret) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } memset(derivedSecret, 0, sizeof *derivedSecret); MP_DIGITS(&p) = 0; @@ -338,41 +350,49 @@ KEA_Derive(SECItem *prime, MP_DIGITS(&t) = 0; MP_DIGITS(&u) = 0; MP_DIGITS(&w) = 0; - CHECK_MPI_OK( mp_init(&p) ); - CHECK_MPI_OK( mp_init(&Y) ); - CHECK_MPI_OK( mp_init(&R) ); - CHECK_MPI_OK( mp_init(&r) ); - CHECK_MPI_OK( mp_init(&x) ); - CHECK_MPI_OK( mp_init(&t) ); - CHECK_MPI_OK( mp_init(&u) ); - CHECK_MPI_OK( mp_init(&w) ); - SECITEM_TO_MPINT(*prime, &p); - SECITEM_TO_MPINT(*public1, &Y); - SECITEM_TO_MPINT(*public2, &R); + CHECK_MPI_OK(mp_init(&p)); + CHECK_MPI_OK(mp_init(&Y)); + CHECK_MPI_OK(mp_init(&R)); + CHECK_MPI_OK(mp_init(&r)); + CHECK_MPI_OK(mp_init(&x)); + CHECK_MPI_OK(mp_init(&t)); + CHECK_MPI_OK(mp_init(&u)); + CHECK_MPI_OK(mp_init(&w)); + SECITEM_TO_MPINT(*prime, &p); + SECITEM_TO_MPINT(*public1, &Y); + SECITEM_TO_MPINT(*public2, &R); SECITEM_TO_MPINT(*private1, &r); SECITEM_TO_MPINT(*private2, &x); /* t = DH(Y, r, p) = Y ** r mod p */ - CHECK_MPI_OK( mp_exptmod(&Y, &r, &p, &t) ); + CHECK_MPI_OK(mp_exptmod(&Y, &r, &p, &t)); /* u = DH(R, x, p) = R ** x mod p */ - CHECK_MPI_OK( mp_exptmod(&R, &x, &p, &u) ); + CHECK_MPI_OK(mp_exptmod(&R, &x, &p, &u)); /* w = (t + u) mod p */ - CHECK_MPI_OK( mp_addmod(&t, &u, &p, &w) ); + CHECK_MPI_OK(mp_addmod(&t, &u, &p, &w)); /* allocate a buffer for the full derived secret */ len = mp_unsigned_octet_size(&w); secret = PORT_Alloc(len); + if (secret == NULL) { + err = MP_MEM; + goto cleanup; + } /* grab the secret */ err = mp_to_unsigned_octets(&w, secret, len); - if (err > 0) err = MP_OKAY; + if (err > 0) + err = MP_OKAY; /* allocate output buffer */ - SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN); + if (SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN) == NULL) { + err = MP_MEM; + goto cleanup; + } memset(derivedSecret->data, 0, derivedSecret->len); /* copy in the 128 lsb of the secret */ if (len >= KEA_DERIVED_SECRET_LEN) { - memcpy(derivedSecret->data, secret + (len - KEA_DERIVED_SECRET_LEN), - KEA_DERIVED_SECRET_LEN); + memcpy(derivedSecret->data, secret + (len - KEA_DERIVED_SECRET_LEN), + KEA_DERIVED_SECRET_LEN); } else { - offset = KEA_DERIVED_SECRET_LEN - len; - memcpy(derivedSecret->data + offset, secret, len); + offset = KEA_DERIVED_SECRET_LEN - len; + memcpy(derivedSecret->data + offset, secret, len); } cleanup: mp_clear(&p); @@ -384,37 +404,39 @@ cleanup: mp_clear(&u); mp_clear(&w); if (secret) - PORT_ZFree(secret, len); + PORT_ZFree(secret, len); if (err) { - MP_TO_SEC_ERROR(err); - return SECFailure; + MP_TO_SEC_ERROR(err); + if (derivedSecret->data) + PORT_ZFree(derivedSecret->data, derivedSecret->len); + return SECFailure; } return SECSuccess; } -PRBool +PRBool KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime) { mp_int p, q, y, r; mp_err err; - int cmp = 1; /* default is false */ + int cmp = 1; /* default is false */ if (!Y || !prime || !subPrime) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } MP_DIGITS(&p) = 0; MP_DIGITS(&q) = 0; MP_DIGITS(&y) = 0; MP_DIGITS(&r) = 0; - CHECK_MPI_OK( mp_init(&p) ); - CHECK_MPI_OK( mp_init(&q) ); - CHECK_MPI_OK( mp_init(&y) ); - CHECK_MPI_OK( mp_init(&r) ); - SECITEM_TO_MPINT(*prime, &p); + CHECK_MPI_OK(mp_init(&p)); + CHECK_MPI_OK(mp_init(&q)); + CHECK_MPI_OK(mp_init(&y)); + CHECK_MPI_OK(mp_init(&r)); + SECITEM_TO_MPINT(*prime, &p); SECITEM_TO_MPINT(*subPrime, &q); - SECITEM_TO_MPINT(*Y, &y); + SECITEM_TO_MPINT(*Y, &y); /* compute r = y**q mod p */ - CHECK_MPI_OK( mp_exptmod(&y, &q, &p, &r) ); + CHECK_MPI_OK(mp_exptmod(&y, &q, &p, &r)); /* compare to 1 */ cmp = mp_cmp_d(&r, 1); cleanup: @@ -423,8 +445,8 @@ cleanup: mp_clear(&y); mp_clear(&r); if (err) { - MP_TO_SEC_ERROR(err); - return PR_FALSE; + MP_TO_SEC_ERROR(err); + return PR_FALSE; } return (cmp == 0) ? PR_TRUE : PR_FALSE; } |