parent
3db5bbbbb7
commit
6452df6570
@ -0,0 +1,92 @@
|
||||
diff --git a/lib/pkcs12/p12d.c b/lib/pkcs12/p12d.c
|
||||
--- a/lib/pkcs12/p12d.c
|
||||
+++ b/lib/pkcs12/p12d.c
|
||||
@@ -335,35 +335,42 @@
|
||||
sec_PKCS12SafeContentsContext *safeContentsCtx =
|
||||
(sec_PKCS12SafeContentsContext *)arg;
|
||||
SEC_PKCS12DecoderContext *p12dcx;
|
||||
SECStatus rv;
|
||||
|
||||
- /* make sure that we are not skipping the current safeBag,
|
||||
- * and that there are no errors. If so, just return rather
|
||||
- * than continuing to process.
|
||||
- */
|
||||
- if (!safeContentsCtx || !safeContentsCtx->p12dcx ||
|
||||
- safeContentsCtx->p12dcx->error || safeContentsCtx->skipCurrentSafeBag) {
|
||||
+ if (!safeContentsCtx || !safeContentsCtx->p12dcx || !safeContentsCtx->currentSafeBagA1Dcx) {
|
||||
return;
|
||||
}
|
||||
p12dcx = safeContentsCtx->p12dcx;
|
||||
|
||||
+ /* make sure that there are no errors and we are not skipping the current safeBag */
|
||||
+ if (p12dcx->error || safeContentsCtx->skipCurrentSafeBag) {
|
||||
+ goto loser;
|
||||
+ }
|
||||
+
|
||||
rv = SEC_ASN1DecoderUpdate(safeContentsCtx->currentSafeBagA1Dcx, data, len);
|
||||
if (rv != SECSuccess) {
|
||||
p12dcx->errorValue = PORT_GetError();
|
||||
+ p12dcx->error = PR_TRUE;
|
||||
+ goto loser;
|
||||
+ }
|
||||
+
|
||||
+ /* The update may have set safeContentsCtx->skipCurrentSafeBag, and we
|
||||
+ * may not get another opportunity to clean up the decoder context.
|
||||
+ */
|
||||
+ if (safeContentsCtx->skipCurrentSafeBag) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
loser:
|
||||
- /* set the error, and finish the decoder context. because there
|
||||
+ /* Finish the decoder context. Because there
|
||||
* is not a way of returning an error message, it may be worth
|
||||
* while to do a check higher up and finish any decoding contexts
|
||||
* that are still open.
|
||||
*/
|
||||
- p12dcx->error = PR_TRUE;
|
||||
SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagA1Dcx);
|
||||
safeContentsCtx->currentSafeBagA1Dcx = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
diff --git a/lib/pkcs12/p12t.h b/lib/pkcs12/p12t.h
|
||||
--- a/lib/pkcs12/p12t.h
|
||||
+++ b/lib/pkcs12/p12t.h
|
||||
@@ -71,10 +71,11 @@
|
||||
SECKEYEncryptedPrivateKeyInfo *pkcs8ShroudedKeyBag;
|
||||
sec_PKCS12CertBag *certBag;
|
||||
sec_PKCS12CRLBag *crlBag;
|
||||
sec_PKCS12SecretBag *secretBag;
|
||||
sec_PKCS12SafeContents *safeContents;
|
||||
+ SECItem *unknownBag;
|
||||
} safeBagContent;
|
||||
|
||||
sec_PKCS12Attribute **attribs;
|
||||
|
||||
/* used locally */
|
||||
diff --git a/lib/pkcs12/p12tmpl.c b/lib/pkcs12/p12tmpl.c
|
||||
--- a/lib/pkcs12/p12tmpl.c
|
||||
+++ b/lib/pkcs12/p12tmpl.c
|
||||
@@ -28,16 +28,16 @@
|
||||
|
||||
safeBag = (sec_PKCS12SafeBag *)src_or_dest;
|
||||
|
||||
oiddata = SECOID_FindOID(&safeBag->safeBagType);
|
||||
if (oiddata == NULL) {
|
||||
- return SEC_ASN1_GET(SEC_AnyTemplate);
|
||||
+ return SEC_ASN1_GET(SEC_PointerToAnyTemplate);
|
||||
}
|
||||
|
||||
switch (oiddata->offset) {
|
||||
default:
|
||||
- theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
|
||||
+ theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
|
||||
break;
|
||||
case SEC_OID_PKCS12_V1_KEY_BAG_ID:
|
||||
theTemplate = SEC_ASN1_GET(SECKEY_PointerToPrivateKeyInfoTemplate);
|
||||
break;
|
||||
case SEC_OID_PKCS12_V1_CERT_BAG_ID:
|
||||
|
@ -0,0 +1,320 @@
|
||||
diff -up ./lib/freebl/dh.c.fips-review ./lib/freebl/dh.c
|
||||
--- ./lib/freebl/dh.c.fips-review 2022-05-26 02:54:33.000000000 -0700
|
||||
+++ ./lib/freebl/dh.c 2023-03-16 11:54:37.839935303 -0700
|
||||
@@ -445,7 +445,7 @@ cleanup:
|
||||
PRBool
|
||||
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
|
||||
{
|
||||
- mp_int p, q, y, r;
|
||||
+ mp_int p, q, y, r, psub1;
|
||||
mp_err err;
|
||||
int cmp = 1; /* default is false */
|
||||
if (!Y || !prime || !subPrime) {
|
||||
@@ -456,13 +456,30 @@ KEA_Verify(SECItem *Y, SECItem *prime, S
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
+ MP_DIGITS(&psub1) = 0;
|
||||
CHECK_MPI_OK(mp_init(&p));
|
||||
CHECK_MPI_OK(mp_init(&q));
|
||||
CHECK_MPI_OK(mp_init(&y));
|
||||
CHECK_MPI_OK(mp_init(&r));
|
||||
+ CHECK_MPI_OK(mp_init(&psub1));
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
SECITEM_TO_MPINT(*subPrime, &q);
|
||||
SECITEM_TO_MPINT(*Y, &y);
|
||||
+ CHECK_MPI_OK(mp_sub_d(&p, 1, &psub1));
|
||||
+ /*
|
||||
+ * We check that the public value isn't zero (which isn't in the
|
||||
+ * group), one (subgroup of order one) or p-1 (subgroup of order 2). We
|
||||
+ * also check that the public value is less than p, to avoid being fooled
|
||||
+ * by values like p+1 or 2*p-1.
|
||||
+ * This check is required by SP-800-56Ar3. It's also done in derive,
|
||||
+ * but this is only called in various FIPS cases, so put it here to help
|
||||
+ * reviewers find it.
|
||||
+ */
|
||||
+ if (mp_cmp_d(&y, 1) <= 0 ||
|
||||
+ mp_cmp(&y, &psub1) >= 0) {
|
||||
+ err = MP_BADARG;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
/* compute r = y**q mod p */
|
||||
CHECK_MPI_OK(mp_exptmod(&y, &q, &p, &r));
|
||||
/* compare to 1 */
|
||||
@@ -472,6 +489,7 @@ cleanup:
|
||||
mp_clear(&q);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r);
|
||||
+ mp_clear(&psub1);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return PR_FALSE;
|
||||
diff -up ./lib/softoken/pkcs11c.c.fips-review ./lib/softoken/pkcs11c.c
|
||||
--- ./lib/softoken/pkcs11c.c.fips-review 2023-03-16 11:53:04.703068972 -0700
|
||||
+++ ./lib/softoken/pkcs11c.c 2023-03-16 11:55:23.498360007 -0700
|
||||
@@ -4780,6 +4780,10 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi
|
||||
* handle the base object stuff
|
||||
*/
|
||||
crv = sftk_handleObject(key, session);
|
||||
+ /* we need to do this check at the end, so we can check the generated
|
||||
+ * key length against fips requirements */
|
||||
+ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, key);
|
||||
+ session->lastOpWasFIPS = key->isFIPS;
|
||||
sftk_FreeSession(session);
|
||||
if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) {
|
||||
crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
|
||||
@@ -4787,9 +4791,6 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi
|
||||
if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) {
|
||||
crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
|
||||
}
|
||||
- /* we need to do this check at the end, so we can check the generated key length against
|
||||
- * fips requirements */
|
||||
- key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, key);
|
||||
if (crv == CKR_OK) {
|
||||
*phKey = key->handle;
|
||||
}
|
||||
@@ -5093,60 +5094,67 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
|
||||
|
||||
if (isDerivable) {
|
||||
SFTKAttribute *pubAttribute = NULL;
|
||||
- CK_OBJECT_HANDLE newKey;
|
||||
PRBool isFIPS = sftk_isFIPS(slot->slotID);
|
||||
- CK_RV crv2;
|
||||
- CK_OBJECT_CLASS secret = CKO_SECRET_KEY;
|
||||
- CK_KEY_TYPE generic = CKK_GENERIC_SECRET;
|
||||
- CK_ULONG keyLen = 128;
|
||||
- CK_BBOOL ckTrue = CK_TRUE;
|
||||
- CK_ATTRIBUTE template[] = {
|
||||
- { CKA_CLASS, &secret, sizeof(secret) },
|
||||
- { CKA_KEY_TYPE, &generic, sizeof(generic) },
|
||||
- { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
|
||||
- { CKA_DERIVE, &ckTrue, sizeof(ckTrue) }
|
||||
- };
|
||||
- CK_ULONG templateCount = PR_ARRAY_SIZE(template);
|
||||
- CK_ECDH1_DERIVE_PARAMS ecParams;
|
||||
+ NSSLOWKEYPrivateKey *lowPrivKey = NULL;
|
||||
+ ECPrivateKey *ecPriv;
|
||||
+ SECItem *lowPubValue = NULL;
|
||||
+ SECItem item;
|
||||
+ SECStatus rv;
|
||||
|
||||
crv = CKR_OK; /*paranoia, already get's set before we drop to the end */
|
||||
- /* FIPS 140-2 requires we verify that the resulting key is a valid key.
|
||||
- * The easiest way to do this is to do a derive operation, which checks
|
||||
- * the validity of the key */
|
||||
-
|
||||
+ /* FIPS 140-3 requires we verify that the resulting key is a valid key
|
||||
+ * by recalculating the public can an compare it to our own public
|
||||
+ * key. */
|
||||
+ lowPrivKey = sftk_GetPrivKey(privateKey, keyType, &crv);
|
||||
+ if (lowPrivKey == NULL) {
|
||||
+ return sftk_MapCryptError(PORT_GetError());
|
||||
+ }
|
||||
+ /* recalculate the public key from the private key */
|
||||
switch (keyType) {
|
||||
- case CKK_DH:
|
||||
- mech.mechanism = CKM_DH_PKCS_DERIVE;
|
||||
- pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
|
||||
- if (pubAttribute == NULL) {
|
||||
- return CKR_DEVICE_ERROR;
|
||||
- }
|
||||
- mech.pParameter = pubAttribute->attrib.pValue;
|
||||
- mech.ulParameterLen = pubAttribute->attrib.ulValueLen;
|
||||
- break;
|
||||
- case CKK_EC:
|
||||
- mech.mechanism = CKM_ECDH1_DERIVE;
|
||||
- pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
|
||||
- if (pubAttribute == NULL) {
|
||||
- return CKR_DEVICE_ERROR;
|
||||
- }
|
||||
- ecParams.kdf = CKD_NULL;
|
||||
- ecParams.ulSharedDataLen = 0;
|
||||
- ecParams.pSharedData = NULL;
|
||||
- ecParams.ulPublicDataLen = pubAttribute->attrib.ulValueLen;
|
||||
- ecParams.pPublicData = pubAttribute->attrib.pValue;
|
||||
- mech.pParameter = &ecParams;
|
||||
- mech.ulParameterLen = sizeof(ecParams);
|
||||
- break;
|
||||
- default:
|
||||
- return CKR_DEVICE_ERROR;
|
||||
+ case CKK_DH:
|
||||
+ rv = DH_Derive(&lowPrivKey->u.dh.base, &lowPrivKey->u.dh.prime,
|
||||
+ &lowPrivKey->u.dh.privateValue, &item, 0);
|
||||
+ if (rv != SECSuccess) {
|
||||
+ return CKR_GENERAL_ERROR;
|
||||
+ }
|
||||
+ lowPubValue = SECITEM_DupItem(&item);
|
||||
+ SECITEM_ZfreeItem(&item, PR_FALSE);
|
||||
+ pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
|
||||
+ break;
|
||||
+ case CKK_EC:
|
||||
+ rv = EC_NewKeyFromSeed(&lowPrivKey->u.ec.ecParams, &ecPriv,
|
||||
+ lowPrivKey->u.ec.privateValue.data,
|
||||
+ lowPrivKey->u.ec.privateValue.len);
|
||||
+ if (rv != SECSuccess) {
|
||||
+ return CKR_GENERAL_ERROR;
|
||||
+ }
|
||||
+ /* make sure it has the same encoding */
|
||||
+ if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
|
||||
+ lowPrivKey->u.ec.ecParams.fieldID.type == ec_field_plain) {
|
||||
+ lowPubValue = SECITEM_DupItem(&ecPriv->publicValue);
|
||||
+ } else {
|
||||
+ lowPubValue = SEC_ASN1EncodeItem(NULL, NULL, &ecPriv->publicValue,
|
||||
+ SEC_ASN1_GET(SEC_OctetStringTemplate));;
|
||||
+ }
|
||||
+ pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
|
||||
+ /* clear out our generated private key */
|
||||
+ PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
|
||||
+ break;
|
||||
+ default:
|
||||
+ return CKR_DEVICE_ERROR;
|
||||
}
|
||||
-
|
||||
- crv = NSC_DeriveKey(hSession, &mech, privateKey->handle, template, templateCount, &newKey);
|
||||
- if (crv != CKR_OK) {
|
||||
- sftk_FreeAttribute(pubAttribute);
|
||||
- return crv;
|
||||
+ /* now compare new public key with our already generated key */
|
||||
+ if ((pubAttribute == NULL) || (lowPubValue == NULL) ||
|
||||
+ (pubAttribute->attrib.ulValueLen != lowPubValue->len) ||
|
||||
+ (PORT_Memcmp(pubAttribute->attrib.pValue, lowPubValue->data,
|
||||
+ lowPubValue->len) != 0)) {
|
||||
+ if (pubAttribute) sftk_FreeAttribute(pubAttribute);
|
||||
+ if (lowPubValue) SECITEM_ZfreeItem(lowPubValue, PR_TRUE);
|
||||
+ PORT_SetError(SEC_ERROR_BAD_KEY);
|
||||
+ return CKR_GENERAL_ERROR;
|
||||
}
|
||||
+ SECITEM_ZfreeItem(lowPubValue, PR_TRUE);
|
||||
+
|
||||
/* FIPS requires full validation, but in fipx mode NSC_Derive
|
||||
* only does partial validation with approved primes, now handle
|
||||
* full validation */
|
||||
@@ -5166,18 +5174,41 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
|
||||
}
|
||||
crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
|
||||
/* we ignore the return code an only look at the length */
|
||||
- if (subPrime.len == 0) {
|
||||
- /* subprime not supplied, In this case look it up.
|
||||
- * This only works with approved primes, but in FIPS mode
|
||||
- * that's the only kine of prime that will get here */
|
||||
- subPrimePtr = sftk_VerifyDH_Prime(&prime, isFIPS);
|
||||
- if (subPrimePtr == NULL) {
|
||||
- crv = CKR_GENERAL_ERROR;
|
||||
+ /* do we have a known prime ? */
|
||||
+ subPrimePtr = sftk_VerifyDH_Prime(&prime, isFIPS);
|
||||
+ if (subPrimePtr == NULL) {
|
||||
+ if (subPrime.len == 0) {
|
||||
+ /* if not a known prime, subprime must be supplied */
|
||||
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
goto done;
|
||||
+ } else {
|
||||
+ /* not a known prime, check for primality of prime
|
||||
+ * and subPrime */
|
||||
+ if (!KEA_PrimeCheck(&prime)) {
|
||||
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ if (!KEA_PrimeCheck(&subPrime)) {
|
||||
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
+ goto done;
|
||||
+ }
|
||||
}
|
||||
+ subPrimePtr = &subPrime;
|
||||
+ } else {
|
||||
+ if (subPrime.len != 0) {
|
||||
+ /* we have a known prime and a supplied subPrime,
|
||||
+ * make sure the subPrime matches the subPrime for
|
||||
+ * the known Prime */
|
||||
+ if ((subPrimePtr->len != subPrimeLen) ||
|
||||
+ (PORT_Memcmp(subPrimePtr->data, subPrime.data,
|
||||
+ subPrime.len) != 0)) {
|
||||
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) {
|
||||
- crv = CKR_GENERAL_ERROR;
|
||||
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
done:
|
||||
SECITEM_ZfreeItem(&subPrime, PR_FALSE);
|
||||
@@ -5185,13 +5216,9 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
|
||||
}
|
||||
/* clean up before we return */
|
||||
sftk_FreeAttribute(pubAttribute);
|
||||
- crv2 = NSC_DestroyObject(hSession, newKey);
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
- if (crv2 != CKR_OK) {
|
||||
- return crv2;
|
||||
- }
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
@@ -5709,8 +5736,8 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
|
||||
* created and linked.
|
||||
*/
|
||||
crv = sftk_handleObject(publicKey, session);
|
||||
- sftk_FreeSession(session);
|
||||
if (crv != CKR_OK) {
|
||||
+ sftk_FreeSession(session);
|
||||
sftk_FreeObject(publicKey);
|
||||
NSC_DestroyObject(hSession, privateKey->handle);
|
||||
sftk_FreeObject(privateKey);
|
||||
@@ -5752,6 +5779,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
|
||||
}
|
||||
|
||||
if (crv != CKR_OK) {
|
||||
+ sftk_FreeSession(session);
|
||||
NSC_DestroyObject(hSession, publicKey->handle);
|
||||
sftk_FreeObject(publicKey);
|
||||
NSC_DestroyObject(hSession, privateKey->handle);
|
||||
@@ -5761,6 +5789,8 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
|
||||
/* we need to do this check at the end to make sure the generated key meets the key length requirements */
|
||||
privateKey->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE_KEY_PAIR, privateKey);
|
||||
publicKey->isFIPS = privateKey->isFIPS;
|
||||
+ session->lastOpWasFIPS = privateKey->isFIPS;
|
||||
+ sftk_FreeSession(session);
|
||||
|
||||
*phPrivateKey = privateKey->handle;
|
||||
*phPublicKey = publicKey->handle;
|
||||
@@ -8563,6 +8593,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
|
||||
secretlen = tmp.len;
|
||||
} else {
|
||||
secretlen = keySize;
|
||||
+ key->isFIPS = PR_FALSE;
|
||||
crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
|
||||
&tmp, mechParams->pSharedData,
|
||||
mechParams->ulSharedDataLen, mechParams->kdf);
|
||||
diff -up ./lib/softoken/pkcs11.c.fips-review ./lib/softoken/pkcs11.c
|
||||
--- ./lib/softoken/pkcs11.c.fips-review 2022-05-26 02:54:33.000000000 -0700
|
||||
+++ ./lib/softoken/pkcs11.c 2023-03-16 11:54:37.840935312 -0700
|
||||
@@ -4599,7 +4599,10 @@ NSC_CreateObject(CK_SESSION_HANDLE hSess
|
||||
if (object == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
- object->isFIPS = PR_FALSE; /* if we created the object on the fly,
|
||||
+ /* object types that we aren't allowed to create in FIPS mode are
|
||||
+ * already rejected explicitly. If we get here, then the object is
|
||||
+ * FIPS OK (most notably public key objects )*/
|
||||
+ /* object->isFIPS = PR_FALSE; if we created the object on the fly,
|
||||
* it's not a FIPS object */
|
||||
|
||||
/*
|
||||
diff -up ./lib/softoken/sftkike.c.fips-review ./lib/softoken/sftkike.c
|
||||
--- ./lib/softoken/sftkike.c.fips-review 2022-05-26 02:54:33.000000000 -0700
|
||||
+++ ./lib/softoken/sftkike.c 2023-03-16 11:54:37.840935312 -0700
|
||||
@@ -516,6 +516,11 @@ sftk_ike_prf(CK_SESSION_HANDLE hSession,
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
+ /* ikev1 isn't validated, if we use this function in ikev1 mode,
|
||||
+ * mark the resulting key as not FIPS */
|
||||
+ if (!params->bRekey) {
|
||||
+ outKey->isFIPS = PR_FALSE;
|
||||
+ }
|
||||
crv = prf_init(&context, inKey->attrib.pValue,
|
||||
inKey->attrib.ulValueLen);
|
||||
if (crv != CKR_OK) {
|
@ -0,0 +1,397 @@
|
||||
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
|
||||
--- a/lib/softoken/pkcs11c.c
|
||||
+++ b/lib/softoken/pkcs11c.c
|
||||
@@ -232,57 +232,26 @@ NSC_DestroyObject(CK_SESSION_HANDLE hSes
|
||||
* be in the data base.
|
||||
*/
|
||||
status = sftk_FreeObject(object);
|
||||
|
||||
return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
- ************** Crypto Functions: Utilities ************************
|
||||
- */
|
||||
-/*
|
||||
- * Utility function for converting PSS/OAEP parameter types into
|
||||
- * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447.
|
||||
- */
|
||||
-static HASH_HashType
|
||||
-GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)
|
||||
-{
|
||||
- switch (mech) {
|
||||
- case CKM_SHA_1:
|
||||
- case CKG_MGF1_SHA1:
|
||||
- return HASH_AlgSHA1;
|
||||
- case CKM_SHA224:
|
||||
- case CKG_MGF1_SHA224:
|
||||
- return HASH_AlgSHA224;
|
||||
- case CKM_SHA256:
|
||||
- case CKG_MGF1_SHA256:
|
||||
- return HASH_AlgSHA256;
|
||||
- case CKM_SHA384:
|
||||
- case CKG_MGF1_SHA384:
|
||||
- return HASH_AlgSHA384;
|
||||
- case CKM_SHA512:
|
||||
- case CKG_MGF1_SHA512:
|
||||
- return HASH_AlgSHA512;
|
||||
- default:
|
||||
- return HASH_AlgNULL;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
* Returns true if "params" contains a valid set of PSS parameters
|
||||
*/
|
||||
static PRBool
|
||||
sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params)
|
||||
{
|
||||
if (!params) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
- if (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
|
||||
- GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
|
||||
+ if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
|
||||
+ sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if "params" contains a valid set of OAEP parameters
|
||||
*/
|
||||
@@ -293,18 +262,18 @@ sftk_ValidateOaepParams(const CK_RSA_PKC
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* The requirements of ulSourceLen/pSourceData come from PKCS #11, which
|
||||
* state:
|
||||
* If the parameter is empty, pSourceData must be NULL and
|
||||
* ulSourceDataLen must be zero.
|
||||
*/
|
||||
if (params->source != CKZ_DATA_SPECIFIED ||
|
||||
- (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
|
||||
- (GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
|
||||
+ (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
|
||||
+ (sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
|
||||
(params->ulSourceDataLen == 0 && params->pSourceData != NULL) ||
|
||||
(params->ulSourceDataLen != 0 && params->pSourceData == NULL)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -606,18 +575,18 @@ sftk_RSAEncryptOAEP(SFTKOAEPInfo *info,
|
||||
HASH_HashType maskHashAlg;
|
||||
|
||||
PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey);
|
||||
if (info->key.pub->keyType != NSSLOWKEYRSAKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_KEY);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
- hashAlg = GetHashTypeFromMechanism(info->params.hashAlg);
|
||||
- maskHashAlg = GetHashTypeFromMechanism(info->params.mgf);
|
||||
+ hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
|
||||
+ maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
|
||||
|
||||
return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg,
|
||||
(const unsigned char *)info->params.pSourceData,
|
||||
info->params.ulSourceDataLen, NULL, 0,
|
||||
output, outputLen, maxLen, input, inputLen);
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
@@ -630,18 +599,18 @@ sftk_RSADecryptOAEP(SFTKOAEPInfo *info,
|
||||
HASH_HashType maskHashAlg;
|
||||
|
||||
PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey);
|
||||
if (info->key.priv->keyType != NSSLOWKEYRSAKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_KEY);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
- hashAlg = GetHashTypeFromMechanism(info->params.hashAlg);
|
||||
- maskHashAlg = GetHashTypeFromMechanism(info->params.mgf);
|
||||
+ hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
|
||||
+ maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
|
||||
|
||||
rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg,
|
||||
(const unsigned char *)info->params.pSourceData,
|
||||
info->params.ulSourceDataLen,
|
||||
output, outputLen, maxLen, input, inputLen);
|
||||
if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
|
||||
sftk_fatalError = PR_TRUE;
|
||||
}
|
||||
@@ -2646,18 +2615,18 @@ sftk_RSASignPSS(SFTKPSSSignInfo *info, u
|
||||
CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
|
||||
|
||||
PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
|
||||
if (info->key->keyType != NSSLOWKEYRSAKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_KEY);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
- hashAlg = GetHashTypeFromMechanism(params->hashAlg);
|
||||
- maskHashAlg = GetHashTypeFromMechanism(params->mgf);
|
||||
+ hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
|
||||
+ maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
|
||||
|
||||
rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL,
|
||||
params->sLen, sig, sigLen, maxLen, hash, hashLen);
|
||||
if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
|
||||
sftk_fatalError = PR_TRUE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -3021,17 +2990,17 @@ NSC_SignInit(CK_SESSION_HANDLE hSession,
|
||||
tlsPrfHash = HASH_AlgNULL;
|
||||
if (tls12_mac_params->ulMacLength != 12) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* The hash function for the TLS 1.2 PRF */
|
||||
tlsPrfHash =
|
||||
- GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
|
||||
+ sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
|
||||
if (tlsPrfHash == HASH_AlgNULL ||
|
||||
tls12_mac_params->ulMacLength < 12) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tls12_mac_params->ulServerOrClient == 1) {
|
||||
label = "server finished";
|
||||
@@ -3539,18 +3508,18 @@ sftk_RSACheckSignPSS(SFTKPSSVerifyInfo *
|
||||
CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
|
||||
|
||||
PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
|
||||
if (info->key->keyType != NSSLOWKEYRSAKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_KEY);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
- hashAlg = GetHashTypeFromMechanism(params->hashAlg);
|
||||
- maskHashAlg = GetHashTypeFromMechanism(params->mgf);
|
||||
+ hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
|
||||
+ maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
|
||||
|
||||
return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg,
|
||||
params->sLen, sig, sigLen, digest, digestLen);
|
||||
}
|
||||
|
||||
/* NSC_VerifyInit initializes a verification operation,
|
||||
* where the signature is an appendix to the data,
|
||||
* and plaintext cannot be recovered from the signature (e.g. DSA) */
|
||||
@@ -6951,17 +6920,17 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
|
||||
unsigned genLen = 0;
|
||||
unsigned char hashbuf[HASH_LENGTH_MAX];
|
||||
unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH];
|
||||
unsigned char *keyBlockAlloc = NULL; /* allocated keyBlock */
|
||||
unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */
|
||||
const unsigned char *prk; /* psuedo-random key */
|
||||
CK_ULONG prkLen;
|
||||
const unsigned char *okm; /* output keying material */
|
||||
- HASH_HashType hashType = GetHashTypeFromMechanism(params->prfHashMechanism);
|
||||
+ HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism);
|
||||
SFTKObject *saltKey = NULL;
|
||||
CK_RV crv = CKR_OK;
|
||||
|
||||
/* Spec says it should be the base hash, but also accept the HMAC */
|
||||
if (hashType == HASH_AlgNULL) {
|
||||
hashType = sftk_HMACMechanismToHash(params->prfHashMechanism);
|
||||
}
|
||||
rawHash = HASH_GetRawHashObject(hashType);
|
||||
@@ -7389,17 +7358,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
|
||||
if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) ||
|
||||
(mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master =
|
||||
(CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter;
|
||||
- tlsPrfHash = GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
|
||||
+ tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
|
||||
if (tlsPrfHash == HASH_AlgNULL) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
} else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) ||
|
||||
(mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
|
||||
tlsPrfHash = HASH_AlgSHA256;
|
||||
}
|
||||
@@ -7607,17 +7576,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
|
||||
break;
|
||||
}
|
||||
|
||||
status = TLS_PRF(&pms, "extended master secret",
|
||||
&seed, &master, isFIPS);
|
||||
} else {
|
||||
const SECHashObject *hashObj;
|
||||
|
||||
- tlsPrfHash = GetHashTypeFromMechanism(ems_params->prfHashMechanism);
|
||||
+ tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism);
|
||||
if (tlsPrfHash == HASH_AlgNULL) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
hashObj = HASH_GetRawHashObject(tlsPrfHash);
|
||||
if (seed.len != hashObj->length) {
|
||||
crv = CKR_TEMPLATE_INCONSISTENT;
|
||||
@@ -7665,17 +7634,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
|
||||
|
||||
if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) {
|
||||
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
CK_TLS12_KEY_MAT_PARAMS *tls12_keys =
|
||||
(CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter;
|
||||
- tlsPrfHash = GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
|
||||
+ tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
|
||||
if (tlsPrfHash == HASH_AlgNULL) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
} else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
|
||||
tlsPrfHash = HASH_AlgSHA256;
|
||||
}
|
||||
|
||||
diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h
|
||||
--- a/lib/softoken/pkcs11i.h
|
||||
+++ b/lib/softoken/pkcs11i.h
|
||||
@@ -908,16 +908,19 @@ sftk_MACConstantTimeCtx *sftk_HMACConsta
|
||||
sftk_MACConstantTimeCtx *sftk_SSLv3MACConstantTime_New(
|
||||
CK_MECHANISM_PTR mech, SFTKObject *key);
|
||||
void sftk_HMACConstantTime_Update(void *pctx, const void *data, unsigned int len);
|
||||
void sftk_SSLv3MACConstantTime_Update(void *pctx, const void *data, unsigned int len);
|
||||
void sftk_MACConstantTime_EndHash(
|
||||
void *pctx, void *out, unsigned int *outLength, unsigned int maxLength);
|
||||
void sftk_MACConstantTime_DestroyContext(void *pctx, PRBool);
|
||||
|
||||
+/* Crypto Utilities */
|
||||
+HASH_HashType sftk_GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech);
|
||||
+
|
||||
/****************************************
|
||||
* implement TLS Pseudo Random Function (PRF)
|
||||
*/
|
||||
|
||||
extern CK_RV
|
||||
sftk_TLSPRFInit(SFTKSessionContext *context,
|
||||
SFTKObject *key,
|
||||
CK_KEY_TYPE key_type,
|
||||
diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c
|
||||
--- a/lib/softoken/pkcs11u.c
|
||||
+++ b/lib/softoken/pkcs11u.c
|
||||
@@ -95,16 +95,17 @@ CK_RV
|
||||
sftk_MapVerifyError(int error)
|
||||
{
|
||||
CK_RV crv = sftk_MapCryptError(error);
|
||||
if (crv == CKR_DEVICE_ERROR)
|
||||
crv = CKR_SIGNATURE_INVALID;
|
||||
return crv;
|
||||
}
|
||||
|
||||
+
|
||||
/*
|
||||
* ******************** Attribute Utilities *******************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* create a new attribute with type, value, and length. Space is allocated
|
||||
* to hold value.
|
||||
*/
|
||||
@@ -2243,17 +2244,49 @@ sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE
|
||||
flags = CKF_MESSAGE_VERIFY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * ******************** Hash Utilities **************************
|
||||
+ */
|
||||
+/*
|
||||
+ * Utility function for converting PSS/OAEP parameter types into
|
||||
+ * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447.
|
||||
+ */
|
||||
+HASH_HashType
|
||||
+sftk_GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)
|
||||
+{
|
||||
+ switch (mech) {
|
||||
+ case CKM_SHA_1:
|
||||
+ case CKG_MGF1_SHA1:
|
||||
+ return HASH_AlgSHA1;
|
||||
+ case CKM_SHA224:
|
||||
+ case CKG_MGF1_SHA224:
|
||||
+ return HASH_AlgSHA224;
|
||||
+ case CKM_SHA256:
|
||||
+ case CKG_MGF1_SHA256:
|
||||
+ return HASH_AlgSHA256;
|
||||
+ case CKM_SHA384:
|
||||
+ case CKG_MGF1_SHA384:
|
||||
+ return HASH_AlgSHA384;
|
||||
+ case CKM_SHA512:
|
||||
+ case CKG_MGF1_SHA512:
|
||||
+ return HASH_AlgSHA512;
|
||||
+ default:
|
||||
+ return HASH_AlgNULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#ifdef NSS_HAS_FIPS_INDICATORS
|
||||
+/**************** FIPS Indicator Utilities *************************/
|
||||
/* sigh, we probably need a version of this in secutil so that both
|
||||
* softoken and NSS can use it */
|
||||
static SECOidTag
|
||||
sftk_quickGetECCCurveOid(SFTKObject *source)
|
||||
{
|
||||
SFTKAttribute *attribute = sftk_FindAttribute(source, CKA_EC_PARAMS);
|
||||
unsigned char *encoded;
|
||||
int len;
|
||||
@@ -2379,16 +2412,39 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
|
||||
if (mech->ulParameterLen == 0) {
|
||||
/* AEAD ciphers are only in FIPS mode if we are using the
|
||||
* MESSAGE interface. This takes an empty parameter
|
||||
* in the init function */
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
+ case SFTKFIPSRSAPSS: {
|
||||
+ /* PSS salt must not be greater than the length of the
|
||||
+ * underlying hash. We verify that the underlying hash of the
|
||||
+ * parameters matches Hash of the combined hash mechanisms, so
|
||||
+ * we don't need to look at the specific PSS mechanism */
|
||||
+ CK_RSA_PKCS_PSS_PARAMS *pss = (CK_RSA_PKCS_PSS_PARAMS *)
|
||||
+ mech->pParameter;
|
||||
+ const SECHashObject *hashObj = NULL;
|
||||
+ if (mech->ulParameterLen != sizeof(*pss)) {
|
||||
+ return PR_FALSE;
|
||||
+ }
|
||||
+ /* we use the existing hash utilities to find the length of
|
||||
+ * the hash */
|
||||
+ hashObj = HASH_GetRawHashObject(sftk_GetHashTypeFromMechanism(
|
||||
+ pss->hashAlg));
|
||||
+ if (hashObj == NULL) {
|
||||
+ return PR_FALSE;
|
||||
+ }
|
||||
+ if (pss->sLen > hashObj->length) {
|
||||
+ return PR_FALSE;
|
||||
+ }
|
||||
+ return PR_TRUE;
|
||||
+ }
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* if we didn't understand the special processing, mark it non-fips */
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in new issue