|
|
18cffa |
diff -up ./lib/freebl/dh.c.fips-review ./lib/freebl/dh.c
|
|
|
18cffa |
--- ./lib/freebl/dh.c.fips-review 2022-05-26 02:54:33.000000000 -0700
|
|
|
4e8b4d |
+++ ./lib/freebl/dh.c 2023-03-17 10:53:23.552658592 -0700
|
|
|
18cffa |
@@ -445,7 +445,7 @@ cleanup:
|
|
|
18cffa |
PRBool
|
|
|
18cffa |
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
|
|
|
18cffa |
{
|
|
|
18cffa |
- mp_int p, q, y, r;
|
|
|
18cffa |
+ mp_int p, q, y, r, psub1;
|
|
|
18cffa |
mp_err err;
|
|
|
18cffa |
int cmp = 1; /* default is false */
|
|
|
18cffa |
if (!Y || !prime || !subPrime) {
|
|
|
18cffa |
@@ -456,13 +456,30 @@ KEA_Verify(SECItem *Y, SECItem *prime, S
|
|
|
18cffa |
MP_DIGITS(&q) = 0;
|
|
|
18cffa |
MP_DIGITS(&y) = 0;
|
|
|
18cffa |
MP_DIGITS(&r) = 0;
|
|
|
18cffa |
+ MP_DIGITS(&psub1) = 0;
|
|
|
18cffa |
CHECK_MPI_OK(mp_init(&p);;
|
|
|
18cffa |
CHECK_MPI_OK(mp_init(&q);;
|
|
|
18cffa |
CHECK_MPI_OK(mp_init(&y);;
|
|
|
18cffa |
CHECK_MPI_OK(mp_init(&r);;
|
|
|
18cffa |
+ CHECK_MPI_OK(mp_init(&psub1));
|
|
|
18cffa |
SECITEM_TO_MPINT(*prime, &p);
|
|
|
18cffa |
SECITEM_TO_MPINT(*subPrime, &q);
|
|
|
18cffa |
SECITEM_TO_MPINT(*Y, &y);
|
|
|
18cffa |
+ CHECK_MPI_OK(mp_sub_d(&p, 1, &psub1));
|
|
|
18cffa |
+ /*
|
|
|
18cffa |
+ * We check that the public value isn't zero (which isn't in the
|
|
|
18cffa |
+ * group), one (subgroup of order one) or p-1 (subgroup of order 2). We
|
|
|
18cffa |
+ * also check that the public value is less than p, to avoid being fooled
|
|
|
18cffa |
+ * by values like p+1 or 2*p-1.
|
|
|
18cffa |
+ * This check is required by SP-800-56Ar3. It's also done in derive,
|
|
|
18cffa |
+ * but this is only called in various FIPS cases, so put it here to help
|
|
|
18cffa |
+ * reviewers find it.
|
|
|
18cffa |
+ */
|
|
|
18cffa |
+ if (mp_cmp_d(&y, 1) <= 0 ||
|
|
|
18cffa |
+ mp_cmp(&y, &psub1) >= 0) {
|
|
|
18cffa |
+ err = MP_BADARG;
|
|
|
18cffa |
+ goto cleanup;
|
|
|
18cffa |
+ }
|
|
|
18cffa |
/* compute r = y**q mod p */
|
|
|
18cffa |
CHECK_MPI_OK(mp_exptmod(&y, &q, &p, &r);;
|
|
|
18cffa |
/* compare to 1 */
|
|
|
18cffa |
@@ -472,6 +489,7 @@ cleanup:
|
|
|
18cffa |
mp_clear(&q);
|
|
|
18cffa |
mp_clear(&y);
|
|
|
18cffa |
mp_clear(&r);
|
|
|
18cffa |
+ mp_clear(&psub1);
|
|
|
18cffa |
if (err) {
|
|
|
18cffa |
MP_TO_SEC_ERROR(err);
|
|
|
18cffa |
return PR_FALSE;
|
|
|
18cffa |
diff -up ./lib/softoken/pkcs11c.c.fips-review ./lib/softoken/pkcs11c.c
|
|
|
4e8b4d |
--- ./lib/softoken/pkcs11c.c.fips-review 2023-03-17 10:53:13.569590567 -0700
|
|
|
4e8b4d |
+++ ./lib/softoken/pkcs11c.c 2023-03-17 10:53:23.552658592 -0700
|
|
|
18cffa |
@@ -4780,6 +4780,10 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi
|
|
|
18cffa |
* handle the base object stuff
|
|
|
18cffa |
*/
|
|
|
18cffa |
crv = sftk_handleObject(key, session);
|
|
|
18cffa |
+ /* we need to do this check at the end, so we can check the generated
|
|
|
18cffa |
+ * key length against fips requirements */
|
|
|
18cffa |
+ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, key);
|
|
|
18cffa |
+ session->lastOpWasFIPS = key->isFIPS;
|
|
|
18cffa |
sftk_FreeSession(session);
|
|
|
18cffa |
if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) {
|
|
|
18cffa |
crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
|
|
|
18cffa |
@@ -4787,9 +4791,6 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi
|
|
|
18cffa |
if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) {
|
|
|
18cffa |
crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
|
|
|
18cffa |
}
|
|
|
18cffa |
- /* we need to do this check at the end, so we can check the generated key length against
|
|
|
18cffa |
- * fips requirements */
|
|
|
18cffa |
- key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, key);
|
|
|
18cffa |
if (crv == CKR_OK) {
|
|
|
18cffa |
*phKey = key->handle;
|
|
|
18cffa |
}
|
|
|
18cffa |
@@ -5093,60 +5094,67 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
|
|
|
18cffa |
|
|
|
18cffa |
if (isDerivable) {
|
|
|
18cffa |
SFTKAttribute *pubAttribute = NULL;
|
|
|
18cffa |
- CK_OBJECT_HANDLE newKey;
|
|
|
18cffa |
PRBool isFIPS = sftk_isFIPS(slot->slotID);
|
|
|
18cffa |
- CK_RV crv2;
|
|
|
18cffa |
- CK_OBJECT_CLASS secret = CKO_SECRET_KEY;
|
|
|
18cffa |
- CK_KEY_TYPE generic = CKK_GENERIC_SECRET;
|
|
|
18cffa |
- CK_ULONG keyLen = 128;
|
|
|
18cffa |
- CK_BBOOL ckTrue = CK_TRUE;
|
|
|
18cffa |
- CK_ATTRIBUTE template[] = {
|
|
|
18cffa |
- { CKA_CLASS, &secret, sizeof(secret) },
|
|
|
18cffa |
- { CKA_KEY_TYPE, &generic, sizeof(generic) },
|
|
|
18cffa |
- { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
|
|
|
18cffa |
- { CKA_DERIVE, &ckTrue, sizeof(ckTrue) }
|
|
|
18cffa |
- };
|
|
|
18cffa |
- CK_ULONG templateCount = PR_ARRAY_SIZE(template);
|
|
|
18cffa |
- CK_ECDH1_DERIVE_PARAMS ecParams;
|
|
|
18cffa |
+ NSSLOWKEYPrivateKey *lowPrivKey = NULL;
|
|
|
18cffa |
+ ECPrivateKey *ecPriv;
|
|
|
18cffa |
+ SECItem *lowPubValue = NULL;
|
|
|
18cffa |
+ SECItem item;
|
|
|
18cffa |
+ SECStatus rv;
|
|
|
18cffa |
|
|
|
18cffa |
crv = CKR_OK; /*paranoia, already get's set before we drop to the end */
|
|
|
18cffa |
- /* FIPS 140-2 requires we verify that the resulting key is a valid key.
|
|
|
18cffa |
- * The easiest way to do this is to do a derive operation, which checks
|
|
|
18cffa |
- * the validity of the key */
|
|
|
18cffa |
-
|
|
|
18cffa |
+ /* FIPS 140-3 requires we verify that the resulting key is a valid key
|
|
|
18cffa |
+ * by recalculating the public can an compare it to our own public
|
|
|
18cffa |
+ * key. */
|
|
|
18cffa |
+ lowPrivKey = sftk_GetPrivKey(privateKey, keyType, &crv;;
|
|
|
18cffa |
+ if (lowPrivKey == NULL) {
|
|
|
18cffa |
+ return sftk_MapCryptError(PORT_GetError());
|
|
|
18cffa |
+ }
|
|
|
18cffa |
+ /* recalculate the public key from the private key */
|
|
|
18cffa |
switch (keyType) {
|
|
|
18cffa |
- case CKK_DH:
|
|
|
18cffa |
- mech.mechanism = CKM_DH_PKCS_DERIVE;
|
|
|
18cffa |
- pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
|
|
|
18cffa |
- if (pubAttribute == NULL) {
|
|
|
18cffa |
- return CKR_DEVICE_ERROR;
|
|
|
18cffa |
- }
|
|
|
18cffa |
- mech.pParameter = pubAttribute->attrib.pValue;
|
|
|
18cffa |
- mech.ulParameterLen = pubAttribute->attrib.ulValueLen;
|
|
|
18cffa |
- break;
|
|
|
18cffa |
- case CKK_EC:
|
|
|
18cffa |
- mech.mechanism = CKM_ECDH1_DERIVE;
|
|
|
18cffa |
- pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
|
|
|
18cffa |
- if (pubAttribute == NULL) {
|
|
|
18cffa |
- return CKR_DEVICE_ERROR;
|
|
|
18cffa |
- }
|
|
|
18cffa |
- ecParams.kdf = CKD_NULL;
|
|
|
18cffa |
- ecParams.ulSharedDataLen = 0;
|
|
|
18cffa |
- ecParams.pSharedData = NULL;
|
|
|
18cffa |
- ecParams.ulPublicDataLen = pubAttribute->attrib.ulValueLen;
|
|
|
18cffa |
- ecParams.pPublicData = pubAttribute->attrib.pValue;
|
|
|
18cffa |
- mech.pParameter = &ecParams;
|
|
|
18cffa |
- mech.ulParameterLen = sizeof(ecParams);
|
|
|
18cffa |
- break;
|
|
|
18cffa |
- default:
|
|
|
18cffa |
- return CKR_DEVICE_ERROR;
|
|
|
18cffa |
+ case CKK_DH:
|
|
|
18cffa |
+ rv = DH_Derive(&lowPrivKey->u.dh.base, &lowPrivKey->u.dh.prime,
|
|
|
18cffa |
+ &lowPrivKey->u.dh.privateValue, &item, 0);
|
|
|
18cffa |
+ if (rv != SECSuccess) {
|
|
|
18cffa |
+ return CKR_GENERAL_ERROR;
|
|
|
18cffa |
+ }
|
|
|
18cffa |
+ lowPubValue = SECITEM_DupItem(&item);
|
|
|
18cffa |
+ SECITEM_ZfreeItem(&item, PR_FALSE);
|
|
|
18cffa |
+ pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
|
|
|
18cffa |
+ break;
|
|
|
18cffa |
+ case CKK_EC:
|
|
|
18cffa |
+ rv = EC_NewKeyFromSeed(&lowPrivKey->u.ec.ecParams, &ecPriv,
|
|
|
18cffa |
+ lowPrivKey->u.ec.privateValue.data,
|
|
|
18cffa |
+ lowPrivKey->u.ec.privateValue.len);
|
|
|
18cffa |
+ if (rv != SECSuccess) {
|
|
|
18cffa |
+ return CKR_GENERAL_ERROR;
|
|
|
18cffa |
+ }
|
|
|
18cffa |
+ /* make sure it has the same encoding */
|
|
|
18cffa |
+ if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
|
|
|
18cffa |
+ lowPrivKey->u.ec.ecParams.fieldID.type == ec_field_plain) {
|
|
|
18cffa |
+ lowPubValue = SECITEM_DupItem(&ecPriv->publicValue);
|
|
|
18cffa |
+ } else {
|
|
|
18cffa |
+ lowPubValue = SEC_ASN1EncodeItem(NULL, NULL, &ecPriv->publicValue,
|
|
|
18cffa |
+ SEC_ASN1_GET(SEC_OctetStringTemplate));;
|
|
|
18cffa |
+ }
|
|
|
18cffa |
+ pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
|
|
|
18cffa |
+ /* clear out our generated private key */
|
|
|
18cffa |
+ PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
|
|
|
18cffa |
+ break;
|
|
|
18cffa |
+ default:
|
|
|
18cffa |
+ return CKR_DEVICE_ERROR;
|
|
|
18cffa |
}
|
|
|
18cffa |
-
|
|
|
18cffa |
- crv = NSC_DeriveKey(hSession, &mech, privateKey->handle, template, templateCount, &newKey);
|
|
|
18cffa |
- if (crv != CKR_OK) {
|
|
|
18cffa |
- sftk_FreeAttribute(pubAttribute);
|
|
|
18cffa |
- return crv;
|
|
|
18cffa |
+ /* now compare new public key with our already generated key */
|
|
|
18cffa |
+ if ((pubAttribute == NULL) || (lowPubValue == NULL) ||
|
|
|
18cffa |
+ (pubAttribute->attrib.ulValueLen != lowPubValue->len) ||
|
|
|
18cffa |
+ (PORT_Memcmp(pubAttribute->attrib.pValue, lowPubValue->data,
|
|
|
18cffa |
+ lowPubValue->len) != 0)) {
|
|
|
18cffa |
+ if (pubAttribute) sftk_FreeAttribute(pubAttribute);
|
|
|
18cffa |
+ if (lowPubValue) SECITEM_ZfreeItem(lowPubValue, PR_TRUE);
|
|
|
18cffa |
+ PORT_SetError(SEC_ERROR_BAD_KEY);
|
|
|
18cffa |
+ return CKR_GENERAL_ERROR;
|
|
|
18cffa |
}
|
|
|
18cffa |
+ SECITEM_ZfreeItem(lowPubValue, PR_TRUE);
|
|
|
18cffa |
+
|
|
|
18cffa |
/* FIPS requires full validation, but in fipx mode NSC_Derive
|
|
|
18cffa |
* only does partial validation with approved primes, now handle
|
|
|
18cffa |
* full validation */
|
|
|
4e8b4d |
@@ -5154,44 +5162,78 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
|
|
|
4e8b4d |
SECItem pubKey;
|
|
|
4e8b4d |
SECItem prime;
|
|
|
4e8b4d |
SECItem subPrime;
|
|
|
4e8b4d |
+ SECItem base;
|
|
|
4e8b4d |
+ SECItem generator;
|
|
|
4e8b4d |
const SECItem *subPrimePtr = &subPrime;
|
|
|
4e8b4d |
|
|
|
4e8b4d |
pubKey.data = pubAttribute->attrib.pValue;
|
|
|
4e8b4d |
pubKey.len = pubAttribute->attrib.ulValueLen;
|
|
|
4e8b4d |
- prime.data = subPrime.data = NULL;
|
|
|
4e8b4d |
- prime.len = subPrime.len = 0;
|
|
|
4e8b4d |
+ base.data = prime.data = subPrime.data = NULL;
|
|
|
4e8b4d |
+ base.len = prime.len = subPrime.len = 0;
|
|
|
18cffa |
crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
|
|
|
4e8b4d |
if (crv != CKR_OK) {
|
|
|
4e8b4d |
goto done;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
- crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
|
|
|
4e8b4d |
+ crv = sftk_Attribute2SecItem(NULL, &base, privateKey, CKA_BASE);
|
|
|
4e8b4d |
+ if (crv != CKR_OK) {
|
|
|
4e8b4d |
+ goto done;
|
|
|
4e8b4d |
+ }
|
|
|
18cffa |
/* we ignore the return code an only look at the length */
|
|
|
18cffa |
- if (subPrime.len == 0) {
|
|
|
18cffa |
- /* subprime not supplied, In this case look it up.
|
|
|
18cffa |
- * This only works with approved primes, but in FIPS mode
|
|
|
18cffa |
- * that's the only kine of prime that will get here */
|
|
|
18cffa |
- subPrimePtr = sftk_VerifyDH_Prime(&prime, isFIPS);
|
|
|
18cffa |
- if (subPrimePtr == NULL) {
|
|
|
18cffa |
- crv = CKR_GENERAL_ERROR;
|
|
|
18cffa |
+ /* do we have a known prime ? */
|
|
|
4e8b4d |
+ subPrimePtr = sftk_VerifyDH_Prime(&prime, &generator, isFIPS);
|
|
|
18cffa |
+ if (subPrimePtr == NULL) {
|
|
|
18cffa |
+ if (subPrime.len == 0) {
|
|
|
18cffa |
+ /* if not a known prime, subprime must be supplied */
|
|
|
18cffa |
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
4e8b4d |
+ goto done;
|
|
|
18cffa |
+ } else {
|
|
|
18cffa |
+ /* not a known prime, check for primality of prime
|
|
|
18cffa |
+ * and subPrime */
|
|
|
18cffa |
+ if (!KEA_PrimeCheck(&prime)) {
|
|
|
18cffa |
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
18cffa |
+ goto done;
|
|
|
18cffa |
+ }
|
|
|
18cffa |
+ if (!KEA_PrimeCheck(&subPrime)) {
|
|
|
18cffa |
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
18cffa |
+ goto done;
|
|
|
18cffa |
+ }
|
|
|
4e8b4d |
+ /* if we aren't using a defined group, make sure base is in the
|
|
|
4e8b4d |
+ * subgroup. If it's not, then our key could fail or succeed sometimes.
|
|
|
4e8b4d |
+ * This makes the failure reliable */
|
|
|
4e8b4d |
+ if (!KEA_Verify(&base, &prime, (SECItem *)subPrimePtr)) {
|
|
|
4e8b4d |
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
4e8b4d |
+ }
|
|
|
4e8b4d |
+ }
|
|
|
18cffa |
+ subPrimePtr = &subPrime;
|
|
|
18cffa |
+ } else {
|
|
|
4e8b4d |
+ /* we're using a known group, make sure we are using the known generator for that group */
|
|
|
4e8b4d |
+ if (SECITEM_CompareItem(&generator, &base) != 0) {
|
|
|
4e8b4d |
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
4e8b4d |
goto done;
|
|
|
4e8b4d |
}
|
|
|
18cffa |
+ if (subPrime.len != 0) {
|
|
|
18cffa |
+ /* we have a known prime and a supplied subPrime,
|
|
|
18cffa |
+ * make sure the subPrime matches the subPrime for
|
|
|
18cffa |
+ * the known Prime */
|
|
|
4e8b4d |
+ if (SECITEM_CompareItem(subPrimePtr, &subPrime) != 0) {
|
|
|
18cffa |
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
18cffa |
+ goto done;
|
|
|
18cffa |
+ }
|
|
|
18cffa |
+ }
|
|
|
18cffa |
}
|
|
|
18cffa |
if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) {
|
|
|
18cffa |
- crv = CKR_GENERAL_ERROR;
|
|
|
18cffa |
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
18cffa |
}
|
|
|
18cffa |
done:
|
|
|
4e8b4d |
+ SECITEM_ZfreeItem(&base, PR_FALSE);
|
|
|
18cffa |
SECITEM_ZfreeItem(&subPrime, PR_FALSE);
|
|
|
4e8b4d |
SECITEM_ZfreeItem(&prime, PR_FALSE);
|
|
|
18cffa |
}
|
|
|
18cffa |
/* clean up before we return */
|
|
|
18cffa |
sftk_FreeAttribute(pubAttribute);
|
|
|
18cffa |
- crv2 = NSC_DestroyObject(hSession, newKey);
|
|
|
18cffa |
if (crv != CKR_OK) {
|
|
|
18cffa |
return crv;
|
|
|
18cffa |
}
|
|
|
18cffa |
- if (crv2 != CKR_OK) {
|
|
|
18cffa |
- return crv2;
|
|
|
18cffa |
- }
|
|
|
18cffa |
}
|
|
|
18cffa |
|
|
|
18cffa |
return CKR_OK;
|
|
|
4e8b4d |
@@ -5709,8 +5751,8 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
|
|
|
18cffa |
* created and linked.
|
|
|
18cffa |
*/
|
|
|
18cffa |
crv = sftk_handleObject(publicKey, session);
|
|
|
18cffa |
- sftk_FreeSession(session);
|
|
|
18cffa |
if (crv != CKR_OK) {
|
|
|
18cffa |
+ sftk_FreeSession(session);
|
|
|
18cffa |
sftk_FreeObject(publicKey);
|
|
|
18cffa |
NSC_DestroyObject(hSession, privateKey->handle);
|
|
|
18cffa |
sftk_FreeObject(privateKey);
|
|
|
4e8b4d |
@@ -5752,6 +5794,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
|
|
|
18cffa |
}
|
|
|
18cffa |
|
|
|
18cffa |
if (crv != CKR_OK) {
|
|
|
18cffa |
+ sftk_FreeSession(session);
|
|
|
18cffa |
NSC_DestroyObject(hSession, publicKey->handle);
|
|
|
18cffa |
sftk_FreeObject(publicKey);
|
|
|
18cffa |
NSC_DestroyObject(hSession, privateKey->handle);
|
|
|
4e8b4d |
@@ -5761,6 +5804,8 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
|
|
|
18cffa |
/* we need to do this check at the end to make sure the generated key meets the key length requirements */
|
|
|
18cffa |
privateKey->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE_KEY_PAIR, privateKey);
|
|
|
18cffa |
publicKey->isFIPS = privateKey->isFIPS;
|
|
|
18cffa |
+ session->lastOpWasFIPS = privateKey->isFIPS;
|
|
|
18cffa |
+ sftk_FreeSession(session);
|
|
|
18cffa |
|
|
|
18cffa |
*phPrivateKey = privateKey->handle;
|
|
|
18cffa |
*phPublicKey = publicKey->handle;
|
|
|
4e8b4d |
@@ -8381,7 +8426,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
|
|
|
4e8b4d |
|
|
|
4e8b4d |
/* if the prime is an approved prime, we can skip all the other
|
|
|
4e8b4d |
* checks. */
|
|
|
4e8b4d |
- subPrime = sftk_VerifyDH_Prime(&dhPrime, isFIPS);
|
|
|
4e8b4d |
+ subPrime = sftk_VerifyDH_Prime(&dhPrime, NULL, isFIPS);
|
|
|
4e8b4d |
if (subPrime == NULL) {
|
|
|
4e8b4d |
SECItem dhSubPrime;
|
|
|
4e8b4d |
/* If the caller set the subprime value, it means that
|
|
|
4e8b4d |
@@ -8563,6 +8608,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
|
|
|
18cffa |
secretlen = tmp.len;
|
|
|
18cffa |
} else {
|
|
|
18cffa |
secretlen = keySize;
|
|
|
18cffa |
+ key->isFIPS = PR_FALSE;
|
|
|
18cffa |
crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
|
|
|
18cffa |
&tmp, mechParams->pSharedData,
|
|
|
18cffa |
mechParams->ulSharedDataLen, mechParams->kdf);
|
|
|
18cffa |
diff -up ./lib/softoken/pkcs11.c.fips-review ./lib/softoken/pkcs11.c
|
|
|
18cffa |
--- ./lib/softoken/pkcs11.c.fips-review 2022-05-26 02:54:33.000000000 -0700
|
|
|
4e8b4d |
+++ ./lib/softoken/pkcs11.c 2023-03-17 10:53:23.553658599 -0700
|
|
|
18cffa |
@@ -4599,7 +4599,10 @@ NSC_CreateObject(CK_SESSION_HANDLE hSess
|
|
|
18cffa |
if (object == NULL) {
|
|
|
18cffa |
return CKR_HOST_MEMORY;
|
|
|
18cffa |
}
|
|
|
18cffa |
- object->isFIPS = PR_FALSE; /* if we created the object on the fly,
|
|
|
18cffa |
+ /* object types that we aren't allowed to create in FIPS mode are
|
|
|
18cffa |
+ * already rejected explicitly. If we get here, then the object is
|
|
|
18cffa |
+ * FIPS OK (most notably public key objects )*/
|
|
|
18cffa |
+ /* object->isFIPS = PR_FALSE; if we created the object on the fly,
|
|
|
18cffa |
* it's not a FIPS object */
|
|
|
18cffa |
|
|
|
18cffa |
/*
|
|
|
4e8b4d |
diff -up ./lib/softoken/pkcs11i.h.fips-review ./lib/softoken/pkcs11i.h
|
|
|
4e8b4d |
--- ./lib/softoken/pkcs11i.h.fips-review 2023-03-17 10:53:13.569590567 -0700
|
|
|
4e8b4d |
+++ ./lib/softoken/pkcs11i.h 2023-03-17 10:53:23.553658599 -0700
|
|
|
4e8b4d |
@@ -971,7 +971,7 @@ char **NSC_ModuleDBFunc(unsigned long fu
|
|
|
4e8b4d |
/* dh verify functions */
|
|
|
4e8b4d |
/* verify that dhPrime matches one of our known primes, and if so return
|
|
|
4e8b4d |
* it's subprime value */
|
|
|
4e8b4d |
-const SECItem *sftk_VerifyDH_Prime(SECItem *dhPrime, PRBool isFIPS);
|
|
|
4e8b4d |
+const SECItem *sftk_VerifyDH_Prime(SECItem *dhPrime, SECItem *generator, PRBool isFIPS);
|
|
|
4e8b4d |
/* check if dhSubPrime claims dhPrime is a safe prime. */
|
|
|
4e8b4d |
SECStatus sftk_IsSafePrime(SECItem *dhPrime, SECItem *dhSubPrime, PRBool *isSafe);
|
|
|
4e8b4d |
/* map an operation Attribute to a Mechanism flag */
|
|
|
4e8b4d |
diff -up ./lib/softoken/pkcs11u.c.fips-review ./lib/softoken/pkcs11u.c
|
|
|
4e8b4d |
--- ./lib/softoken/pkcs11u.c.fips-review 2023-03-17 10:53:13.570590574 -0700
|
|
|
4e8b4d |
+++ ./lib/softoken/pkcs11u.c 2023-03-17 10:54:53.009268164 -0700
|
|
|
4e8b4d |
@@ -2404,15 +2404,27 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
|
|
|
4e8b4d |
switch (mechInfo->special) {
|
|
|
4e8b4d |
case SFTKFIPSDH: {
|
|
|
4e8b4d |
SECItem dhPrime;
|
|
|
4e8b4d |
+ SECItem dhBase;
|
|
|
4e8b4d |
+ SECItem dhGenerator;
|
|
|
4e8b4d |
+ PRBool val = PR_FALSE;
|
|
|
4e8b4d |
const SECItem *dhSubPrime;
|
|
|
4e8b4d |
CK_RV crv = sftk_Attribute2SecItem(NULL, &dhPrime,
|
|
|
4e8b4d |
source, CKA_PRIME);
|
|
|
4e8b4d |
if (crv != CKR_OK) {
|
|
|
4e8b4d |
return PR_FALSE;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
- dhSubPrime = sftk_VerifyDH_Prime(&dhPrime, PR_TRUE);
|
|
|
4e8b4d |
+ crv = sftk_Attribute2SecItem(NULL, &dhBase, source, CKA_BASE);
|
|
|
4e8b4d |
+ if (crv != CKR_OK) {
|
|
|
4e8b4d |
+ return PR_FALSE;
|
|
|
4e8b4d |
+ }
|
|
|
4e8b4d |
+ dhSubPrime = sftk_VerifyDH_Prime(&dhPrime, &dhGenerator, PR_TRUE);
|
|
|
4e8b4d |
+ val = (dhSubPrime) ? PR_TRUE : PR_FALSE;
|
|
|
4e8b4d |
+ if (val && (SECITEM_CompareItem(&dhBase, &dhGenerator) != 0)) {
|
|
|
4e8b4d |
+ val = PR_FALSE;
|
|
|
4e8b4d |
+ }
|
|
|
4e8b4d |
SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
|
|
|
4e8b4d |
- return (dhSubPrime) ? PR_TRUE : PR_FALSE;
|
|
|
4e8b4d |
+ SECITEM_ZfreeItem(&dhBase, PR_FALSE);
|
|
|
4e8b4d |
+ return val;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
case SFTKFIPSNone:
|
|
|
4e8b4d |
return PR_FALSE;
|
|
|
4e8b4d |
diff -up ./lib/softoken/sftkdhverify.c.fips-review ./lib/softoken/sftkdhverify.c
|
|
|
4e8b4d |
--- ./lib/softoken/sftkdhverify.c.fips-review 2022-05-26 02:54:33.000000000 -0700
|
|
|
4e8b4d |
+++ ./lib/softoken/sftkdhverify.c 2023-03-17 10:53:23.553658599 -0700
|
|
|
4e8b4d |
@@ -1167,11 +1167,20 @@ static const SECItem subprime_tls_8192 =
|
|
|
4e8b4d |
(unsigned char *)subprime_tls_8192_data,
|
|
|
4e8b4d |
sizeof(subprime_tls_8192_data) };
|
|
|
4e8b4d |
|
|
|
4e8b4d |
+/* generator for all the groups is 2 */
|
|
|
4e8b4d |
+static const unsigned char generator_2_data[] = { 2 };
|
|
|
4e8b4d |
+
|
|
|
4e8b4d |
+
|
|
|
4e8b4d |
+static const SECItem generator_2 =
|
|
|
4e8b4d |
+ { siBuffer,
|
|
|
4e8b4d |
+ (unsigned char *)generator_2_data,
|
|
|
4e8b4d |
+ sizeof(generator_2_data) };
|
|
|
4e8b4d |
+
|
|
|
4e8b4d |
/*
|
|
|
4e8b4d |
* verify that dhPrime matches one of our known primes
|
|
|
4e8b4d |
*/
|
|
|
4e8b4d |
const SECItem *
|
|
|
4e8b4d |
-sftk_VerifyDH_Prime(SECItem *dhPrime, PRBool isFIPS)
|
|
|
4e8b4d |
+sftk_VerifyDH_Prime(SECItem *dhPrime, SECItem *g, PRBool isFIPS)
|
|
|
4e8b4d |
{
|
|
|
4e8b4d |
/* use the length to decide which primes to check */
|
|
|
4e8b4d |
switch (dhPrime->len) {
|
|
|
4e8b4d |
@@ -1182,56 +1191,67 @@ sftk_VerifyDH_Prime(SECItem *dhPrime, PR
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_ike_1536,
|
|
|
4e8b4d |
sizeof(prime_ike_1536)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_ike_1536;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
break;
|
|
|
4e8b4d |
case 2048 / PR_BITS_PER_BYTE:
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_tls_2048,
|
|
|
4e8b4d |
sizeof(prime_tls_2048)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_tls_2048;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_ike_2048,
|
|
|
4e8b4d |
sizeof(prime_ike_2048)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_ike_2048;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
break;
|
|
|
4e8b4d |
case 3072 / PR_BITS_PER_BYTE:
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_tls_3072,
|
|
|
4e8b4d |
sizeof(prime_tls_3072)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_tls_3072;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_ike_3072,
|
|
|
4e8b4d |
sizeof(prime_ike_3072)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_ike_3072;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
break;
|
|
|
4e8b4d |
case 4096 / PR_BITS_PER_BYTE:
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_tls_4096,
|
|
|
4e8b4d |
sizeof(prime_tls_4096)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_tls_4096;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_ike_4096,
|
|
|
4e8b4d |
sizeof(prime_ike_4096)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_ike_4096;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
break;
|
|
|
4e8b4d |
case 6144 / PR_BITS_PER_BYTE:
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_tls_6144,
|
|
|
4e8b4d |
sizeof(prime_tls_6144)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_tls_6144;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_ike_6144,
|
|
|
4e8b4d |
sizeof(prime_ike_6144)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_ike_6144;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
break;
|
|
|
4e8b4d |
case 8192 / PR_BITS_PER_BYTE:
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_tls_8192,
|
|
|
4e8b4d |
sizeof(prime_tls_8192)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_tls_8192;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
if (PORT_Memcmp(dhPrime->data, prime_ike_8192,
|
|
|
4e8b4d |
sizeof(prime_ike_8192)) == 0) {
|
|
|
4e8b4d |
+ if (g) *g = generator_2;
|
|
|
4e8b4d |
return &subprime_ike_8192;
|
|
|
4e8b4d |
}
|
|
|
4e8b4d |
break;
|
|
|
18cffa |
diff -up ./lib/softoken/sftkike.c.fips-review ./lib/softoken/sftkike.c
|
|
|
18cffa |
--- ./lib/softoken/sftkike.c.fips-review 2022-05-26 02:54:33.000000000 -0700
|
|
|
4e8b4d |
+++ ./lib/softoken/sftkike.c 2023-03-17 10:53:23.553658599 -0700
|
|
|
18cffa |
@@ -516,6 +516,11 @@ sftk_ike_prf(CK_SESSION_HANDLE hSession,
|
|
|
18cffa |
goto fail;
|
|
|
18cffa |
}
|
|
|
18cffa |
} else {
|
|
|
18cffa |
+ /* ikev1 isn't validated, if we use this function in ikev1 mode,
|
|
|
18cffa |
+ * mark the resulting key as not FIPS */
|
|
|
18cffa |
+ if (!params->bRekey) {
|
|
|
18cffa |
+ outKey->isFIPS = PR_FALSE;
|
|
|
18cffa |
+ }
|
|
|
18cffa |
crv = prf_init(&context, inKey->attrib.pValue,
|
|
|
18cffa |
inKey->attrib.ulValueLen);
|
|
|
18cffa |
if (crv != CKR_OK) {
|