Blame SOURCES/nss-3.79-fips-review.patches

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