static SECStatus generate_prime(mp_int *prime, int primeLen) { mp_err err = MP_OKAY; SECStatus rv = SECSuccess; unsigned long counter = 0; int piter; unsigned char *pb = NULL; pb = PORT_Alloc(primeLen); if (!pb) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto cleanup; } for (piter = 0; piter < MAX_PRIME_GEN_ATTEMPTS; piter++) { CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) ); pb[0] |= 0xC0; /* set two high-order bits */ pb[primeLen-1] |= 0x01; /* set low-order bit */ CHECK_MPI_OK( mp_read_unsigned_octets(prime, pb, primeLen) ); err = mpp_make_prime(prime, primeLen * 8, PR_FALSE, &counter); if (err != MP_NO) goto cleanup; /* keep going while err == MP_NO */ } cleanup: if (pb) PORT_ZFree(pb, primeLen); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
/* Generates a new EC key pair. The private key is a random value and * the public key is the result of performing a scalar point multiplication * of that value with the curve's base point. */ SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey, const unsigned char* random, int randomlen, int kmflag) { SECStatus rv = SECFailure; int len; unsigned char *privKeyBytes = NULL; if (!ecParams) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } len = ecParams->order.len; privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len, random, randomlen, kmflag); if (privKeyBytes == NULL) goto cleanup; /* generate public key */ CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len, kmflag) ); cleanup: if (privKeyBytes) { PORT_ZFree(privKeyBytes, len * 2); } #if EC_DEBUG printf("EC_NewKey returning %s\n", (rv == SECSuccess) ? "success" : "failure"); #endif return rv; }
/* ** An attack against RSA CRT was described by Boneh, DeMillo, and Lipton in: ** "On the Importance of Eliminating Errors in Cryptographic Computations", ** http://theory.stanford.edu/~dabo/papers/faults.ps.gz ** ** As a defense against the attack, carry out the private key operation, ** followed up with a public key operation to invert the result. ** Verify that result against the input. */ static SECStatus rsa_PrivateKeyOpCRTCheckedPubKey(RSAPrivateKey *key, mp_int *m, mp_int *c) { mp_int n, e, v; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; MP_DIGITS(&n) = 0; MP_DIGITS(&e) = 0; MP_DIGITS(&v) = 0; CHECK_MPI_OK( mp_init(&n) ); CHECK_MPI_OK( mp_init(&e) ); CHECK_MPI_OK( mp_init(&v) ); CHECK_SEC_OK( rsa_PrivateKeyOpCRTNoCheck(key, m, c) ); SECITEM_TO_MPINT(key->modulus, &n); SECITEM_TO_MPINT(key->publicExponent, &e); /* Perform a public key operation v = m ** e mod n */ CHECK_MPI_OK( mp_exptmod(m, &e, &n, &v) ); if (mp_cmp(&v, c) != 0) { rv = SECFailure; } cleanup: mp_clear(&n); mp_clear(&e); mp_clear(&v); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
/* Generates a new EC key pair. The private key is a random value and * the public key is the result of performing a scalar point multiplication * of that value with the curve's base point. */ SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey) { SECStatus rv = SECFailure; #ifndef NSS_DISABLE_ECC int len; unsigned char *privKeyBytes = NULL; if (!ecParams) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } len = ecParams->order.len; privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len); if (privKeyBytes == NULL) goto cleanup; /* generate public key */ CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len) ); cleanup: if (privKeyBytes) { PORT_ZFree(privKeyBytes, len); } #if EC_DEBUG printf("EC_NewKey returning %s\n", (rv == SECSuccess) ? "success" : "failure"); #endif #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); #endif /* NSS_DISABLE_ECC */ return rv; }
/* Copy all of the fields from srcParams into dstParams */ SECStatus EC_CopyParams(PLArenaPool *arena, ECParams *dstParams, const ECParams *srcParams) { SECStatus rv = SECFailure; dstParams->arena = arena; dstParams->type = srcParams->type; dstParams->fieldID.size = srcParams->fieldID.size; dstParams->fieldID.type = srcParams->fieldID.type; dstParams->pointSize = srcParams->pointSize; if (srcParams->fieldID.type == ec_field_GFp || srcParams->fieldID.type == ec_field_plain) { CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime, &srcParams->fieldID.u.prime)); } else { CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly, &srcParams->fieldID.u.poly)); } dstParams->fieldID.k1 = srcParams->fieldID.k1; dstParams->fieldID.k2 = srcParams->fieldID.k2; dstParams->fieldID.k3 = srcParams->fieldID.k3; CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.a, &srcParams->curve.a)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.b, &srcParams->curve.b)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.seed, &srcParams->curve.seed)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->base, &srcParams->base)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->order, &srcParams->order)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->DEREncoding, &srcParams->DEREncoding)); dstParams->name = srcParams->name; CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curveOID, &srcParams->curveOID)); dstParams->cofactor = srcParams->cofactor; return SECSuccess; cleanup: return SECFailure; }
/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62, * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the * random number generator. * * Parameters * - order: a buffer that holds the curve's group order * - len: the length in octets of the order buffer * * Return Value * Returns a buffer of len octets that holds the private key. The caller * is responsible for freeing the buffer with PORT_ZFree. */ static unsigned char * ec_GenerateRandomPrivateKey(const unsigned char *order, int len, int kmflag) { SECStatus rv = SECSuccess; mp_err err; unsigned char *privKeyBytes = NULL; mp_int privKeyVal, order_1, one; MP_DIGITS(&privKeyVal) = 0; MP_DIGITS(&order_1) = 0; MP_DIGITS(&one) = 0; CHECK_MPI_OK( mp_init(&privKeyVal) ); CHECK_MPI_OK( mp_init(&order_1) ); CHECK_MPI_OK( mp_init(&one) ); /* Generates 2*len random bytes using the global random bit generator * (which implements Algorithm 1 of FIPS 186-2 Change Notice 1) then * reduces modulo the group order. */ if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup; CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) ); CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) ); CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) ); CHECK_MPI_OK( mp_set_int(&one, 1) ); CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) ); CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) ); CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) ); CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) ); memset(privKeyBytes+len, 0, len); cleanup: mp_clear(&privKeyVal); mp_clear(&order_1); mp_clear(&one); if (err < MP_OKAY) { MP_TO_SEC_ERROR(err); rv = SECFailure; } if (rv != SECSuccess && privKeyBytes) { #ifdef _KERNEL kmem_free(privKeyBytes, 2*len); #else free(privKeyBytes); #endif privKeyBytes = NULL; } return privKeyBytes; }
static SECStatus generate_blinding_params(struct RSABlindingParamsStr *rsabp, RSAPrivateKey *key, mp_int *n, unsigned int modLen) { SECStatus rv = SECSuccess; mp_int e, k; mp_err err = MP_OKAY; unsigned char *kb = NULL; MP_DIGITS(&e) = 0; MP_DIGITS(&k) = 0; CHECK_MPI_OK( mp_init(&e) ); CHECK_MPI_OK( mp_init(&k) ); SECITEM_TO_MPINT(key->publicExponent, &e); /* generate random k < n */ kb = PORT_Alloc(modLen); if (!kb) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto cleanup; } CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(kb, modLen) ); CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, modLen) ); /* k < n */ CHECK_MPI_OK( mp_mod(&k, n, &k) ); /* f = k**e mod n */ CHECK_MPI_OK( mp_exptmod(&k, &e, n, &rsabp->f) ); /* g = k**-1 mod n */ CHECK_MPI_OK( mp_invmod(&k, n, &rsabp->g) ); /* Initialize the counter for this (f, g) */ rsabp->counter = RSA_BLINDING_PARAMS_MAX_REUSE; cleanup: if (kb) PORT_ZFree(kb, modLen); mp_clear(&k); mp_clear(&e); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
static SECStatus generate_blinding_params(RSAPrivateKey *key, mp_int* f, mp_int* g, mp_int *n, unsigned int modLen) { SECStatus rv = SECSuccess; mp_int e, k; mp_err err = MP_OKAY; unsigned char *kb = NULL; MP_DIGITS(&e) = 0; MP_DIGITS(&k) = 0; CHECK_MPI_OK( mp_init(&e) ); CHECK_MPI_OK( mp_init(&k) ); SECITEM_TO_MPINT(key->publicExponent, &e); /* generate random k < n */ kb = PORT_Alloc(modLen); if (!kb) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto cleanup; } CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(kb, modLen) ); CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, modLen) ); /* k < n */ CHECK_MPI_OK( mp_mod(&k, n, &k) ); /* f = k**e mod n */ CHECK_MPI_OK( mp_exptmod(&k, &e, n, f) ); /* g = k**-1 mod n */ CHECK_MPI_OK( mp_invmod(&k, n, g) ); cleanup: if (kb) PORT_ZFree(kb, modLen); mp_clear(&k); mp_clear(&e); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
static SECStatus init_blinding_params(struct RSABlindingParamsStr *rsabp, RSAPrivateKey *key, mp_int *n, unsigned int modLen) { SECStatus rv = SECSuccess; mp_err err = MP_OKAY; MP_DIGITS(&rsabp->f) = 0; MP_DIGITS(&rsabp->g) = 0; /* initialize blinding parameters */ CHECK_MPI_OK( mp_init(&rsabp->f) ); CHECK_MPI_OK( mp_init(&rsabp->g) ); /* List elements are keyed using the modulus */ SECITEM_CopyItem(NULL, &rsabp->modulus, &key->modulus); CHECK_SEC_OK( generate_blinding_params(rsabp, key, n, modLen) ); return SECSuccess; cleanup: mp_clear(&rsabp->f); mp_clear(&rsabp->g); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
static SECStatus get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen, mp_int *f, mp_int *g) { RSABlindingParams *rsabp = NULL; blindingParams *bpUnlinked = NULL; blindingParams *bp, *prevbp = NULL; PRCList *el; SECStatus rv = SECSuccess; mp_err err = MP_OKAY; int cmp = -1; PRBool holdingLock = PR_FALSE; do { if (blindingParamsList.lock == NULL) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } /* Acquire the list lock */ PZ_Lock(blindingParamsList.lock); holdingLock = PR_TRUE; /* Walk the list looking for the private key */ for (el = PR_NEXT_LINK(&blindingParamsList.head); el != &blindingParamsList.head; el = PR_NEXT_LINK(el)) { rsabp = (RSABlindingParams *)el; cmp = SECITEM_CompareItem(&rsabp->modulus, &key->modulus); if (cmp >= 0) { /* The key is found or not in the list. */ break; } } if (cmp) { /* At this point, the key is not in the list. el should point to ** the list element before which this key should be inserted. */ rsabp = PORT_ZNew(RSABlindingParams); if (!rsabp) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto cleanup; } rv = init_blinding_params(rsabp, key, n, modLen); if (rv != SECSuccess) { PORT_ZFree(rsabp, sizeof(RSABlindingParams)); goto cleanup; } /* Insert the new element into the list ** If inserting in the middle of the list, el points to the link ** to insert before. Otherwise, the link needs to be appended to ** the end of the list, which is the same as inserting before the ** head (since el would have looped back to the head). */ PR_INSERT_BEFORE(&rsabp->link, el); } /* We've found (or created) the RSAblindingParams struct for this key. * Now, search its list of ready blinding params for a usable one. */ while (0 != (bp = rsabp->bp)) { if (--(bp->counter) > 0) { /* Found a match and there are still remaining uses left */ /* Return the parameters */ CHECK_MPI_OK( mp_copy(&bp->f, f) ); CHECK_MPI_OK( mp_copy(&bp->g, g) ); PZ_Unlock(blindingParamsList.lock); return SECSuccess; } /* exhausted this one, give its values to caller, and * then retire it. */ mp_exch(&bp->f, f); mp_exch(&bp->g, g); mp_clear( &bp->f ); mp_clear( &bp->g ); bp->counter = 0; /* Move to free list */ rsabp->bp = bp->next; bp->next = rsabp->free; rsabp->free = bp; /* In case there're threads waiting for new blinding * value - notify 1 thread the value is ready */ if (blindingParamsList.waitCount > 0) { PR_NotifyCondVar( blindingParamsList.cVar ); blindingParamsList.waitCount--; } PZ_Unlock(blindingParamsList.lock); return SECSuccess; } /* We did not find a usable set of blinding params. Can we make one? */ /* Find a free bp struct. */ prevbp = NULL; if ((bp = rsabp->free) != NULL) { /* unlink this bp */ rsabp->free = bp->next; bp->next = NULL; bpUnlinked = bp; /* In case we fail */ PZ_Unlock(blindingParamsList.lock); holdingLock = PR_FALSE; /* generate blinding parameter values for the current thread */ CHECK_SEC_OK( generate_blinding_params(key, f, g, n, modLen ) ); /* put the blinding parameter values into cache */ CHECK_MPI_OK( mp_init( &bp->f) ); CHECK_MPI_OK( mp_init( &bp->g) ); CHECK_MPI_OK( mp_copy( f, &bp->f) ); CHECK_MPI_OK( mp_copy( g, &bp->g) ); /* Put this at head of queue of usable params. */ PZ_Lock(blindingParamsList.lock); holdingLock = PR_TRUE; /* initialize RSABlindingParamsStr */ bp->counter = RSA_BLINDING_PARAMS_MAX_REUSE; bp->next = rsabp->bp; rsabp->bp = bp; bpUnlinked = NULL; /* In case there're threads waiting for new blinding value * just notify them the value is ready */ if (blindingParamsList.waitCount > 0) { PR_NotifyAllCondVar( blindingParamsList.cVar ); blindingParamsList.waitCount = 0; } PZ_Unlock(blindingParamsList.lock); return SECSuccess; } /* Here, there are no usable blinding parameters available, * and no free bp blocks, presumably because they're all * actively having parameters generated for them. * So, we need to wait here and not eat up CPU until some * change happens. */ blindingParamsList.waitCount++; PR_WaitCondVar( blindingParamsList.cVar, PR_INTERVAL_NO_TIMEOUT ); PZ_Unlock(blindingParamsList.lock); holdingLock = PR_FALSE; } while (1); cleanup: /* It is possible to reach this after the lock is already released. */ if (bpUnlinked) { if (!holdingLock) { PZ_Lock(blindingParamsList.lock); holdingLock = PR_TRUE; } bp = bpUnlinked; mp_clear( &bp->f ); mp_clear( &bp->g ); bp->counter = 0; /* Must put the unlinked bp back on the free list */ bp->next = rsabp->free; rsabp->free = bp; } if (holdingLock) { PZ_Unlock(blindingParamsList.lock); holdingLock = PR_FALSE; } if (err) { MP_TO_SEC_ERROR(err); } return SECFailure; }
SECStatus EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams, ECParams *params) { SECStatus rv = SECFailure; SECOidTag tag; SECItem oid = { siBuffer, NULL, 0 }; #if EC_DEBUG int i; printf("Encoded params in EC_DecodeParams: "); for (i = 0; i < encodedParams->len; i++) { printf("%02x:", encodedParams->data[i]); } printf("\n"); #endif if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) && (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) && (encodedParams->len != PKIX_NEWCURVES_OID_TOTAL_LEN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; }; oid.len = encodedParams->len - 2; oid.data = encodedParams->data + 2; if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; } params->arena = arena; params->cofactor = 0; params->type = ec_params_named; params->name = ECCurve_noName; /* Fill out curveOID */ params->curveOID.len = oid.len; params->curveOID.data = (unsigned char *)PORT_ArenaAlloc(arena, oid.len); if (params->curveOID.data == NULL) goto cleanup; memcpy(params->curveOID.data, oid.data, oid.len); #if EC_DEBUG printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag)); #endif switch (tag) { case SEC_OID_ANSIX962_EC_PRIME256V1: /* Populate params for prime256v1 aka secp256r1 * (the NIST P-256 curve) */ CHECK_SEC_OK(gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp, params)); break; case SEC_OID_SECG_EC_SECP384R1: /* Populate params for secp384r1 * (the NIST P-384 curve) */ CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp, params)); break; case SEC_OID_SECG_EC_SECP521R1: /* Populate params for secp521r1 * (the NIST P-521 curve) */ CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp, params)); break; case SEC_OID_CURVE25519: /* Populate params for Curve25519 */ CHECK_SEC_OK(gf_populate_params(ECCurve25519, ec_field_plain, params)); break; default: break; }; cleanup: if (!params->cofactor) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); #if EC_DEBUG printf("Unrecognized curve, returning NULL params\n"); #endif } return rv; }
SECStatus DH_GenParam(int primeLen, DHParams **params) { PLArenaPool *arena; DHParams *dhparams; unsigned char *pb = NULL; unsigned char *ab = NULL; unsigned long counter = 0; mp_int p, q, a, h, psub1, test; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; if (!params || primeLen < 0) { 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; } dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams)); if (!dhparams) { PORT_SetError(SEC_ERROR_NO_MEMORY); PORT_FreeArena(arena, PR_TRUE); return SECFailure; } dhparams->arena = arena; MP_DIGITS(&p) = 0; MP_DIGITS(&q) = 0; MP_DIGITS(&a) = 0; 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) ); /* 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) ); /* 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) ); /* 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) ); /* force a < p (note that quot(a/p) <= 1) */ 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. */ 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) ); } while (PR_TRUE); MPINT_TO_SECITEM(&p, &dhparams->prime, arena); MPINT_TO_SECITEM(&a, &dhparams->base, arena); *params = dhparams; cleanup: mp_clear(&p); mp_clear(&q); mp_clear(&a); mp_clear(&h); mp_clear(&psub1); mp_clear(&test); if (pb) PORT_ZFree(pb, primeLen); if (ab) PORT_ZFree(ab, primeLen); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } if (rv) PORT_FreeArena(arena, PR_TRUE); return rv; }
SECStatus DH_NewKey(DHParams *params, DHPrivateKey **privKey) { PLArenaPool *arena; DHPrivateKey *key; mp_int g, xa, p, Ya; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; if (!params || !privKey) { 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; } key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey)); if (!key) { PORT_SetError(SEC_ERROR_NO_MEMORY); PORT_FreeArena(arena, PR_TRUE); return SECFailure; } key->arena = arena; MP_DIGITS(&g) = 0; MP_DIGITS(&xa) = 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) ); /* Set private key's p */ 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) ); SECITEM_TO_MPINT(key->base, &g); /* Generate private key xa */ SECITEM_AllocItem(arena, &key->privateValue, dh_GetSecretKeyLen(params->prime.len)); 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) ); /* Compute public key Ya = g ** xa mod p */ CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) ); MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena); *privKey = key; cleanup: mp_clear(&g); mp_clear(&xa); mp_clear(&p); mp_clear(&Ya); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } if (rv) { *privKey = NULL; PORT_FreeArena(arena, PR_TRUE); } return rv; }
/* ** Generate and return a new RSA public and private key. ** Both keys are encoded in a single RSAPrivateKey structure. ** "cx" is the random number generator context ** "keySizeInBits" is the size of the key to be generated, in bits. ** 512, 1024, etc. ** "publicExponent" when not NULL is a pointer to some data that ** represents the public exponent to use. The data is a byte ** encoded integer, in "big endian" order. */ RSAPrivateKey * RSA_NewKey(int keySizeInBits, SECItem *publicExponent) { unsigned int primeLen; mp_int p, q, e, d; int kiter; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; int prerr = 0; RSAPrivateKey *key = NULL; PLArenaPool *arena = NULL; /* Require key size to be a multiple of 16 bits. */ if (!publicExponent || keySizeInBits % 16 != 0 || BAD_RSA_KEY_SIZE(keySizeInBits/8, publicExponent->len)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } /* 1. Allocate arena & key */ arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE); if (!arena) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } key = PORT_ArenaZNew(arena, RSAPrivateKey); if (!key) { PORT_SetError(SEC_ERROR_NO_MEMORY); PORT_FreeArena(arena, PR_TRUE); return NULL; } key->arena = arena; /* length of primes p and q (in bytes) */ primeLen = keySizeInBits / (2 * PR_BITS_PER_BYTE); MP_DIGITS(&p) = 0; MP_DIGITS(&q) = 0; MP_DIGITS(&e) = 0; MP_DIGITS(&d) = 0; CHECK_MPI_OK( mp_init(&p) ); CHECK_MPI_OK( mp_init(&q) ); CHECK_MPI_OK( mp_init(&e) ); CHECK_MPI_OK( mp_init(&d) ); /* 2. Set the version number (PKCS1 v1.5 says it should be zero) */ SECITEM_AllocItem(arena, &key->version, 1); key->version.data[0] = 0; /* 3. Set the public exponent */ SECITEM_TO_MPINT(*publicExponent, &e); kiter = 0; do { prerr = 0; PORT_SetError(0); CHECK_SEC_OK( generate_prime(&p, primeLen) ); CHECK_SEC_OK( generate_prime(&q, primeLen) ); /* Assure q < p */ if (mp_cmp(&p, &q) < 0) mp_exch(&p, &q); /* Attempt to use these primes to generate a key */ rv = rsa_build_from_primes(&p, &q, &e, PR_FALSE, /* needPublicExponent=false */ &d, PR_TRUE, /* needPrivateExponent=true */ key, keySizeInBits); if (rv == SECSuccess) break; /* generated two good primes */ prerr = PORT_GetError(); kiter++; /* loop until have primes */ } while (prerr == SEC_ERROR_NEED_RANDOM && kiter < MAX_KEY_GEN_ATTEMPTS); if (prerr) goto cleanup; cleanup: mp_clear(&p); mp_clear(&q); mp_clear(&e); mp_clear(&d); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } if (rv && arena) { PORT_FreeArena(arena, PR_TRUE); key = NULL; } return key; }
static SECStatus get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen, mp_int *f, mp_int *g) { SECStatus rv = SECSuccess; mp_err err = MP_OKAY; int cmp; PRCList *el; struct RSABlindingParamsStr *rsabp = NULL; /* Init the list if neccessary (the init function is only called once!) */ if (blindingParamsList.lock == NULL) { if (PR_CallOnce(&coBPInit, init_blinding_params_list) != PR_SUCCESS) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } } /* Acquire the list lock */ PZ_Lock(blindingParamsList.lock); /* Walk the list looking for the private key */ for (el = PR_NEXT_LINK(&blindingParamsList.head); el != &blindingParamsList.head; el = PR_NEXT_LINK(el)) { rsabp = (struct RSABlindingParamsStr *)el; cmp = SECITEM_CompareItem(&rsabp->modulus, &key->modulus); if (cmp == 0) { /* Check the usage counter for the parameters */ if (--rsabp->counter <= 0) { /* Regenerate the blinding parameters */ CHECK_SEC_OK( generate_blinding_params(rsabp, key, n, modLen) ); } /* Return the parameters */ CHECK_MPI_OK( mp_copy(&rsabp->f, f) ); CHECK_MPI_OK( mp_copy(&rsabp->g, g) ); /* Now that the params are located, release the list lock. */ PZ_Unlock(blindingParamsList.lock); /* XXX when fails? */ return SECSuccess; } else if (cmp > 0) { /* The key is not in the list. Break to param creation. */ break; } } /* At this point, the key is not in the list. el should point to the ** list element that this key should be inserted before. NOTE: the list ** lock is still held, so there cannot be a race condition here. */ rsabp = (struct RSABlindingParamsStr *) PORT_ZAlloc(sizeof(struct RSABlindingParamsStr)); if (!rsabp) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto cleanup; } /* Initialize the list pointer for the element */ PR_INIT_CLIST(&rsabp->link); /* Initialize the blinding parameters ** This ties up the list lock while doing some heavy, element-specific ** operations, but we don't want to insert the element until it is valid, ** which requires computing the blinding params. If this proves costly, ** it could be done after the list lock is released, and then if it fails ** the lock would have to be reobtained and the invalid element removed. */ rv = init_blinding_params(rsabp, key, n, modLen); if (rv != SECSuccess) { PORT_ZFree(rsabp, sizeof(struct RSABlindingParamsStr)); goto cleanup; } /* Insert the new element into the list ** If inserting in the middle of the list, el points to the link ** to insert before. Otherwise, the link needs to be appended to ** the end of the list, which is the same as inserting before the ** head (since el would have looped back to the head). */ PR_INSERT_BEFORE(&rsabp->link, el); /* Return the parameters */ CHECK_MPI_OK( mp_copy(&rsabp->f, f) ); CHECK_MPI_OK( mp_copy(&rsabp->g, g) ); /* Release the list lock */ PZ_Unlock(blindingParamsList.lock); /* XXX when fails? */ return SECSuccess; cleanup: /* It is possible to reach this after the lock is already released. ** Ignore the error in that case. */ PZ_Unlock(blindingParamsList.lock); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return SECFailure; }
/* Generates a new EC key pair. The private key is a supplied * value and the public key is the result of performing a scalar * point multiplication of that value with the curve's base point. */ SECStatus ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, const unsigned char *privKeyBytes, int privKeyLen) { SECStatus rv = SECFailure; #ifndef NSS_DISABLE_ECC PLArenaPool *arena; ECPrivateKey *key; mp_int k; mp_err err = MP_OKAY; int len; #if EC_DEBUG printf("ec_NewKey called\n"); #endif MP_DIGITS(&k) = 0; if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } /* Initialize an arena for the EC key. */ if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE))) return SECFailure; key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey)); if (!key) { PORT_FreeArena(arena, PR_TRUE); return SECFailure; } /* Set the version number (SEC 1 section C.4 says it should be 1) */ SECITEM_AllocItem(arena, &key->version, 1); key->version.data[0] = 1; /* Copy all of the fields from the ECParams argument to the * ECParams structure within the private key. */ key->ecParams.arena = arena; key->ecParams.type = ecParams->type; key->ecParams.fieldID.size = ecParams->fieldID.size; key->ecParams.fieldID.type = ecParams->fieldID.type; if (ecParams->fieldID.type == ec_field_GFp) { CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime, &ecParams->fieldID.u.prime)); } else { CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly, &ecParams->fieldID.u.poly)); } key->ecParams.fieldID.k1 = ecParams->fieldID.k1; key->ecParams.fieldID.k2 = ecParams->fieldID.k2; key->ecParams.fieldID.k3 = ecParams->fieldID.k3; CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a, &ecParams->curve.a)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b, &ecParams->curve.b)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed, &ecParams->curve.seed)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base, &ecParams->base)); CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order, &ecParams->order)); key->ecParams.cofactor = ecParams->cofactor; CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding, &ecParams->DEREncoding)); key->ecParams.name = ecParams->name; CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID, &ecParams->curveOID)); len = (ecParams->fieldID.size + 7) >> 3; SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1); len = ecParams->order.len; SECITEM_AllocItem(arena, &key->privateValue, len); /* Copy private key */ if (privKeyLen >= len) { memcpy(key->privateValue.data, privKeyBytes, len); } else { memset(key->privateValue.data, 0, (len - privKeyLen)); memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen); } /* Compute corresponding public key */ CHECK_MPI_OK( mp_init(&k) ); CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data, (mp_size) len) ); rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue)); if (rv != SECSuccess) goto cleanup; *privKey = key; cleanup: mp_clear(&k); if (rv) PORT_FreeArena(arena, PR_TRUE); #if EC_DEBUG printf("ec_NewKey returning %s\n", (rv == SECSuccess) ? "success" : "failure"); #endif #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); #endif /* NSS_DISABLE_ECC */ return rv; }
SECStatus RSA_PrivateKeyCheck(RSAPrivateKey *key) { mp_int p, q, n, psub1, qsub1, e, d, d_p, d_q, qInv, res; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; MP_DIGITS(&n) = 0; MP_DIGITS(&psub1)= 0; MP_DIGITS(&qsub1)= 0; MP_DIGITS(&e) = 0; MP_DIGITS(&d) = 0; MP_DIGITS(&d_p) = 0; MP_DIGITS(&d_q) = 0; MP_DIGITS(&qInv) = 0; MP_DIGITS(&res) = 0; CHECK_MPI_OK( mp_init(&n) ); CHECK_MPI_OK( mp_init(&p) ); CHECK_MPI_OK( mp_init(&q) ); CHECK_MPI_OK( mp_init(&psub1)); CHECK_MPI_OK( mp_init(&qsub1)); CHECK_MPI_OK( mp_init(&e) ); CHECK_MPI_OK( mp_init(&d) ); CHECK_MPI_OK( mp_init(&d_p) ); CHECK_MPI_OK( mp_init(&d_q) ); CHECK_MPI_OK( mp_init(&qInv) ); CHECK_MPI_OK( mp_init(&res) ); SECITEM_TO_MPINT(key->modulus, &n); SECITEM_TO_MPINT(key->prime1, &p); SECITEM_TO_MPINT(key->prime2, &q); SECITEM_TO_MPINT(key->publicExponent, &e); SECITEM_TO_MPINT(key->privateExponent, &d); SECITEM_TO_MPINT(key->exponent1, &d_p); SECITEM_TO_MPINT(key->exponent2, &d_q); SECITEM_TO_MPINT(key->coefficient, &qInv); /* p > q */ if (mp_cmp(&p, &q) <= 0) { /* mind the p's and q's (and d_p's and d_q's) */ SECItem tmp; mp_exch(&p, &q); mp_exch(&d_p,&d_q); tmp = key->prime1; key->prime1 = key->prime2; key->prime2 = tmp; tmp = key->exponent1; key->exponent1 = key->exponent2; key->exponent2 = tmp; } #define VERIFY_MPI_EQUAL(m1, m2) \ if (mp_cmp(m1, m2) != 0) { \ rv = SECFailure; \ goto cleanup; \ } #define VERIFY_MPI_EQUAL_1(m) \ if (mp_cmp_d(m, 1) != 0) { \ rv = SECFailure; \ goto cleanup; \ } /* * The following errors cannot be recovered from. */ /* n == p * q */ CHECK_MPI_OK( mp_mul(&p, &q, &res) ); VERIFY_MPI_EQUAL(&res, &n); /* gcd(e, p-1) == 1 */ CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) ); CHECK_MPI_OK( mp_gcd(&e, &psub1, &res) ); VERIFY_MPI_EQUAL_1(&res); /* gcd(e, q-1) == 1 */ CHECK_MPI_OK( mp_sub_d(&q, 1, &qsub1) ); CHECK_MPI_OK( mp_gcd(&e, &qsub1, &res) ); VERIFY_MPI_EQUAL_1(&res); /* d*e == 1 mod p-1 */ CHECK_MPI_OK( mp_mulmod(&d, &e, &psub1, &res) ); VERIFY_MPI_EQUAL_1(&res); /* d*e == 1 mod q-1 */ CHECK_MPI_OK( mp_mulmod(&d, &e, &qsub1, &res) ); VERIFY_MPI_EQUAL_1(&res); /* * The following errors can be recovered from. */ /* d_p == d mod p-1 */ CHECK_MPI_OK( mp_mod(&d, &psub1, &res) ); if (mp_cmp(&d_p, &res) != 0) { /* swap in the correct value */ CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent1) ); } /* d_q == d mod q-1 */ CHECK_MPI_OK( mp_mod(&d, &qsub1, &res) ); if (mp_cmp(&d_q, &res) != 0) { /* swap in the correct value */ CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent2) ); } /* q * q**-1 == 1 mod p */ CHECK_MPI_OK( mp_mulmod(&q, &qInv, &p, &res) ); if (mp_cmp_d(&res, 1) != 0) { /* compute the correct value */ CHECK_MPI_OK( mp_invmod(&q, &p, &qInv) ); CHECK_SEC_OK( swap_in_key_value(key->arena, &qInv, &key->coefficient) ); } cleanup: mp_clear(&n); mp_clear(&p); mp_clear(&q); mp_clear(&psub1); mp_clear(&qsub1); mp_clear(&e); mp_clear(&d); mp_clear(&d_p); mp_clear(&d_q); mp_clear(&qInv); mp_clear(&res); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
/* ** Perform a raw private-key operation ** Length of input and output buffers are equal to key's modulus len. */ static SECStatus rsa_PrivateKeyOp(RSAPrivateKey *key, unsigned char *output, const unsigned char *input, PRBool check) { unsigned int modLen; unsigned int offset; SECStatus rv = SECSuccess; mp_err err; mp_int n, c, m; mp_int f, g; if (!key || !output || !input) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } /* check input out of range (needs to be in range [0..n-1]) */ modLen = rsa_modulusLen(&key->modulus); offset = (key->modulus.data[0] == 0) ? 1 : 0; /* may be leading 0 */ if (memcmp(input, key->modulus.data + offset, modLen) >= 0) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } MP_DIGITS(&n) = 0; MP_DIGITS(&c) = 0; MP_DIGITS(&m) = 0; MP_DIGITS(&f) = 0; MP_DIGITS(&g) = 0; CHECK_MPI_OK( mp_init(&n) ); CHECK_MPI_OK( mp_init(&c) ); CHECK_MPI_OK( mp_init(&m) ); CHECK_MPI_OK( mp_init(&f) ); CHECK_MPI_OK( mp_init(&g) ); SECITEM_TO_MPINT(key->modulus, &n); OCTETS_TO_MPINT(input, &c, modLen); /* If blinding, compute pre-image of ciphertext by multiplying by ** blinding factor */ if (nssRSAUseBlinding) { CHECK_SEC_OK( get_blinding_params(key, &n, modLen, &f, &g) ); /* c' = c*f mod n */ CHECK_MPI_OK( mp_mulmod(&c, &f, &n, &c) ); } /* Do the private key operation m = c**d mod n */ if ( key->prime1.len == 0 || key->prime2.len == 0 || key->exponent1.len == 0 || key->exponent2.len == 0 || key->coefficient.len == 0) { CHECK_SEC_OK( rsa_PrivateKeyOpNoCRT(key, &m, &c, &n, modLen) ); } else if (check) { CHECK_SEC_OK( rsa_PrivateKeyOpCRTCheckedPubKey(key, &m, &c) ); } else { CHECK_SEC_OK( rsa_PrivateKeyOpCRTNoCheck(key, &m, &c) ); } /* If blinding, compute post-image of plaintext by multiplying by ** blinding factor */ if (nssRSAUseBlinding) { /* m = m'*g mod n */ CHECK_MPI_OK( mp_mulmod(&m, &g, &n, &m) ); } err = mp_to_fixlen_octets(&m, output, modLen); if (err >= 0) err = MP_OKAY; cleanup: mp_clear(&n); mp_clear(&c); mp_clear(&m); mp_clear(&f); mp_clear(&g); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
SECStatus EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams, ECParams *params, int kmflag) { SECStatus rv = SECFailure; ECCurveName tag; SECItem oid = { siBuffer, NULL, 0}; #if EC_DEBUG int i; printf("Encoded params in EC_DecodeParams: "); for (i = 0; i < encodedParams->len; i++) { printf("%02x:", encodedParams->data[i]); } printf("\n"); #endif if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) && (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; }; oid.len = encodedParams->len - 2; oid.data = encodedParams->data + 2; if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || ((tag = SECOID_FindOIDTag(&oid)) == ECCurve_noName)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; } params->arena = arena; params->cofactor = 0; params->type = ec_params_named; params->name = ECCurve_noName; /* For named curves, fill out curveOID */ params->curveOID.len = oid.len; params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(NULL, oid.len, kmflag); if (params->curveOID.data == NULL) goto cleanup; memcpy(params->curveOID.data, oid.data, oid.len); #if EC_DEBUG #ifndef SECOID_FindOIDTagDescription printf("Curve: %s\n", ecCurve_map[tag]->text); #else printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag)); #endif #endif switch (tag) { /* Binary curves */ case ECCurve_X9_62_CHAR2_PNB163V1: /* Populate params for c2pnb163v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB163V2: /* Populate params for c2pnb163v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB163V3: /* Populate params for c2pnb163v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V3, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB176V1: /* Populate params for c2pnb176v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB176V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB191V1: /* Populate params for c2tnb191v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB191V2: /* Populate params for c2tnb191v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB191V3: /* Populate params for c2tnb191v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V3, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB208W1: /* Populate params for c2pnb208w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB208W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB239V1: /* Populate params for c2tnb239v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB239V2: /* Populate params for c2tnb239v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB239V3: /* Populate params for c2tnb239v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V3, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB272W1: /* Populate params for c2pnb272w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB272W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB304W1: /* Populate params for c2pnb304w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB304W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB359V1: /* Populate params for c2tnb359v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB359V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB368W1: /* Populate params for c2pnb368w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB368W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB431R1: /* Populate params for c2tnb431r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB431R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_113R1: /* Populate params for sect113r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_113R2: /* Populate params for sect113r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_131R1: /* Populate params for sect131r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_131R2: /* Populate params for sect131r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_163K1: /* Populate params for sect163k1 * (the NIST K-163 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_163R1: /* Populate params for sect163r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_163R2: /* Populate params for sect163r2 * (the NIST B-163 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_193R1: /* Populate params for sect193r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_193R2: /* Populate params for sect193r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_233K1: /* Populate params for sect233k1 * (the NIST K-233 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_233R1: /* Populate params for sect233r1 * (the NIST B-233 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_239K1: /* Populate params for sect239k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_239K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_283K1: /* Populate params for sect283k1 * (the NIST K-283 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_283R1: /* Populate params for sect283r1 * (the NIST B-283 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_409K1: /* Populate params for sect409k1 * (the NIST K-409 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_409R1: /* Populate params for sect409r1 * (the NIST B-409 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_571K1: /* Populate params for sect571k1 * (the NIST K-571 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_571R1: /* Populate params for sect571r1 * (the NIST B-571 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571R1, ec_field_GF2m, params, kmflag) ); break; /* Prime curves */ case ECCurve_X9_62_PRIME_192V1: /* Populate params for prime192v1 aka secp192r1 * (the NIST P-192 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V1, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_192V2: /* Populate params for prime192v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V2, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_192V3: /* Populate params for prime192v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V3, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_239V1: /* Populate params for prime239v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V1, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_239V2: /* Populate params for prime239v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V2, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_239V3: /* Populate params for prime239v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V3, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_256V1: /* Populate params for prime256v1 aka secp256r1 * (the NIST P-256 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_112R1: /* Populate params for secp112r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_112R2: /* Populate params for secp112r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R2, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_128R1: /* Populate params for secp128r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_128R2: /* Populate params for secp128r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R2, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_160K1: /* Populate params for secp160k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_160R1: /* Populate params for secp160r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_160R2: /* Populate params for secp160r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R2, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_192K1: /* Populate params for secp192k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_192K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_224K1: /* Populate params for secp224k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_224R1: /* Populate params for secp224r1 * (the NIST P-224 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_256K1: /* Populate params for secp256k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_256K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_384R1: /* Populate params for secp384r1 * (the NIST P-384 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_521R1: /* Populate params for secp521r1 * (the NIST P-521 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp, params, kmflag) ); break; default: break; }; cleanup: if (!params->cofactor) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); #if EC_DEBUG printf("Unrecognized curve, returning NULL params\n"); #endif } return rv; }