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