18cffa
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
18cffa
--- a/lib/softoken/pkcs11c.c
18cffa
+++ b/lib/softoken/pkcs11c.c
18cffa
@@ -232,57 +232,26 @@ NSC_DestroyObject(CK_SESSION_HANDLE hSes
18cffa
      * be in the data base.
18cffa
      */
18cffa
     status = sftk_FreeObject(object);
18cffa
 
18cffa
     return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
18cffa
 }
18cffa
 
18cffa
 /*
18cffa
- ************** Crypto Functions:     Utilities ************************
18cffa
- */
18cffa
-/*
18cffa
- * Utility function for converting PSS/OAEP parameter types into
18cffa
- * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447.
18cffa
- */
18cffa
-static HASH_HashType
18cffa
-GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)
18cffa
-{
18cffa
-    switch (mech) {
18cffa
-        case CKM_SHA_1:
18cffa
-        case CKG_MGF1_SHA1:
18cffa
-            return HASH_AlgSHA1;
18cffa
-        case CKM_SHA224:
18cffa
-        case CKG_MGF1_SHA224:
18cffa
-            return HASH_AlgSHA224;
18cffa
-        case CKM_SHA256:
18cffa
-        case CKG_MGF1_SHA256:
18cffa
-            return HASH_AlgSHA256;
18cffa
-        case CKM_SHA384:
18cffa
-        case CKG_MGF1_SHA384:
18cffa
-            return HASH_AlgSHA384;
18cffa
-        case CKM_SHA512:
18cffa
-        case CKG_MGF1_SHA512:
18cffa
-            return HASH_AlgSHA512;
18cffa
-        default:
18cffa
-            return HASH_AlgNULL;
18cffa
-    }
18cffa
-}
18cffa
-
18cffa
-/*
18cffa
  * Returns true if "params" contains a valid set of PSS parameters
18cffa
  */
18cffa
 static PRBool
18cffa
 sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params)
18cffa
 {
18cffa
     if (!params) {
18cffa
         return PR_FALSE;
18cffa
     }
18cffa
-    if (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
18cffa
-        GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
18cffa
+    if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
18cffa
+        sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
18cffa
         return PR_FALSE;
18cffa
     }
18cffa
     return PR_TRUE;
18cffa
 }
18cffa
 
18cffa
 /*
18cffa
  * Returns true if "params" contains a valid set of OAEP parameters
18cffa
  */
18cffa
@@ -293,18 +262,18 @@ sftk_ValidateOaepParams(const CK_RSA_PKC
18cffa
         return PR_FALSE;
18cffa
     }
18cffa
     /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which
18cffa
      * state:
18cffa
      *   If the parameter is empty, pSourceData must be NULL and
18cffa
      *   ulSourceDataLen must be zero.
18cffa
      */
18cffa
     if (params->source != CKZ_DATA_SPECIFIED ||
18cffa
-        (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
18cffa
-        (GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
18cffa
+        (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
18cffa
+        (sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
18cffa
         (params->ulSourceDataLen == 0 && params->pSourceData != NULL) ||
18cffa
         (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) {
18cffa
         return PR_FALSE;
18cffa
     }
18cffa
     return PR_TRUE;
18cffa
 }
18cffa
 
18cffa
 /*
18cffa
@@ -606,18 +575,18 @@ sftk_RSAEncryptOAEP(SFTKOAEPInfo *info, 
18cffa
     HASH_HashType maskHashAlg;
18cffa
 
18cffa
     PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey);
18cffa
     if (info->key.pub->keyType != NSSLOWKEYRSAKey) {
18cffa
         PORT_SetError(SEC_ERROR_INVALID_KEY);
18cffa
         return SECFailure;
18cffa
     }
18cffa
 
18cffa
-    hashAlg = GetHashTypeFromMechanism(info->params.hashAlg);
18cffa
-    maskHashAlg = GetHashTypeFromMechanism(info->params.mgf);
18cffa
+    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
18cffa
+    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
18cffa
 
18cffa
     return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg,
18cffa
                            (const unsigned char *)info->params.pSourceData,
18cffa
                            info->params.ulSourceDataLen, NULL, 0,
18cffa
                            output, outputLen, maxLen, input, inputLen);
18cffa
 }
18cffa
 
18cffa
 static SECStatus
18cffa
@@ -630,18 +599,18 @@ sftk_RSADecryptOAEP(SFTKOAEPInfo *info, 
18cffa
     HASH_HashType maskHashAlg;
18cffa
 
18cffa
     PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey);
18cffa
     if (info->key.priv->keyType != NSSLOWKEYRSAKey) {
18cffa
         PORT_SetError(SEC_ERROR_INVALID_KEY);
18cffa
         return SECFailure;
18cffa
     }
18cffa
 
18cffa
-    hashAlg = GetHashTypeFromMechanism(info->params.hashAlg);
18cffa
-    maskHashAlg = GetHashTypeFromMechanism(info->params.mgf);
18cffa
+    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
18cffa
+    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
18cffa
 
18cffa
     rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg,
18cffa
                          (const unsigned char *)info->params.pSourceData,
18cffa
                          info->params.ulSourceDataLen,
18cffa
                          output, outputLen, maxLen, input, inputLen);
18cffa
     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
18cffa
         sftk_fatalError = PR_TRUE;
18cffa
     }
18cffa
@@ -2646,18 +2615,18 @@ sftk_RSASignPSS(SFTKPSSSignInfo *info, u
18cffa
     CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
18cffa
 
18cffa
     PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
18cffa
     if (info->key->keyType != NSSLOWKEYRSAKey) {
18cffa
         PORT_SetError(SEC_ERROR_INVALID_KEY);
18cffa
         return SECFailure;
18cffa
     }
18cffa
 
18cffa
-    hashAlg = GetHashTypeFromMechanism(params->hashAlg);
18cffa
-    maskHashAlg = GetHashTypeFromMechanism(params->mgf);
18cffa
+    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
18cffa
+    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
18cffa
 
18cffa
     rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL,
18cffa
                      params->sLen, sig, sigLen, maxLen, hash, hashLen);
18cffa
     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
18cffa
         sftk_fatalError = PR_TRUE;
18cffa
     }
18cffa
     return rv;
18cffa
 }
18cffa
@@ -3021,17 +2990,17 @@ NSC_SignInit(CK_SESSION_HANDLE hSession,
18cffa
                 tlsPrfHash = HASH_AlgNULL;
18cffa
                 if (tls12_mac_params->ulMacLength != 12) {
18cffa
                     crv = CKR_MECHANISM_PARAM_INVALID;
18cffa
                     break;
18cffa
                 }
18cffa
             } else {
18cffa
                 /* The hash function for the TLS 1.2 PRF */
18cffa
                 tlsPrfHash =
18cffa
-                    GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
18cffa
+                    sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
18cffa
                 if (tlsPrfHash == HASH_AlgNULL ||
18cffa
                     tls12_mac_params->ulMacLength < 12) {
18cffa
                     crv = CKR_MECHANISM_PARAM_INVALID;
18cffa
                     break;
18cffa
                 }
18cffa
             }
18cffa
             if (tls12_mac_params->ulServerOrClient == 1) {
18cffa
                 label = "server finished";
18cffa
@@ -3539,18 +3508,18 @@ sftk_RSACheckSignPSS(SFTKPSSVerifyInfo *
18cffa
     CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
18cffa
 
18cffa
     PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
18cffa
     if (info->key->keyType != NSSLOWKEYRSAKey) {
18cffa
         PORT_SetError(SEC_ERROR_INVALID_KEY);
18cffa
         return SECFailure;
18cffa
     }
18cffa
 
18cffa
-    hashAlg = GetHashTypeFromMechanism(params->hashAlg);
18cffa
-    maskHashAlg = GetHashTypeFromMechanism(params->mgf);
18cffa
+    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
18cffa
+    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
18cffa
 
18cffa
     return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg,
18cffa
                             params->sLen, sig, sigLen, digest, digestLen);
18cffa
 }
18cffa
 
18cffa
 /* NSC_VerifyInit initializes a verification operation,
18cffa
  * where the signature is an appendix to the data,
18cffa
  * and plaintext cannot be recovered from the signature (e.g. DSA) */
18cffa
@@ -6951,17 +6920,17 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
18cffa
     unsigned genLen = 0;
18cffa
     unsigned char hashbuf[HASH_LENGTH_MAX];
18cffa
     unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH];
18cffa
     unsigned char *keyBlockAlloc = NULL;    /* allocated keyBlock */
18cffa
     unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */
18cffa
     const unsigned char *prk;               /* psuedo-random key */
18cffa
     CK_ULONG prkLen;
18cffa
     const unsigned char *okm; /* output keying material */
18cffa
-    HASH_HashType hashType = GetHashTypeFromMechanism(params->prfHashMechanism);
18cffa
+    HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism);
18cffa
     SFTKObject *saltKey = NULL;
18cffa
     CK_RV crv = CKR_OK;
18cffa
 
18cffa
     /* Spec says it should be the base hash, but also accept the HMAC */
18cffa
     if (hashType == HASH_AlgNULL) {
18cffa
         hashType = sftk_HMACMechanismToHash(params->prfHashMechanism);
18cffa
     }
18cffa
     rawHash = HASH_GetRawHashObject(hashType);
18cffa
@@ -7389,17 +7358,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
18cffa
             if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) ||
18cffa
                 (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
18cffa
                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) {
18cffa
                     crv = CKR_MECHANISM_PARAM_INVALID;
18cffa
                     break;
18cffa
                 }
18cffa
                 CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master =
18cffa
                     (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter;
18cffa
-                tlsPrfHash = GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
18cffa
+                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
18cffa
                 if (tlsPrfHash == HASH_AlgNULL) {
18cffa
                     crv = CKR_MECHANISM_PARAM_INVALID;
18cffa
                     break;
18cffa
                 }
18cffa
             } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) ||
18cffa
                        (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
18cffa
                 tlsPrfHash = HASH_AlgSHA256;
18cffa
             }
18cffa
@@ -7607,17 +7576,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
18cffa
                     break;
18cffa
                 }
18cffa
 
18cffa
                 status = TLS_PRF(&pms, "extended master secret",
18cffa
                                  &seed, &master, isFIPS);
18cffa
             } else {
18cffa
                 const SECHashObject *hashObj;
18cffa
 
18cffa
-                tlsPrfHash = GetHashTypeFromMechanism(ems_params->prfHashMechanism);
18cffa
+                tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism);
18cffa
                 if (tlsPrfHash == HASH_AlgNULL) {
18cffa
                     crv = CKR_MECHANISM_PARAM_INVALID;
18cffa
                     break;
18cffa
                 }
18cffa
 
18cffa
                 hashObj = HASH_GetRawHashObject(tlsPrfHash);
18cffa
                 if (seed.len != hashObj->length) {
18cffa
                     crv = CKR_TEMPLATE_INCONSISTENT;
18cffa
@@ -7665,17 +7634,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
18cffa
 
18cffa
             if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) {
18cffa
                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) {
18cffa
                     crv = CKR_MECHANISM_PARAM_INVALID;
18cffa
                     break;
18cffa
                 }
18cffa
                 CK_TLS12_KEY_MAT_PARAMS *tls12_keys =
18cffa
                     (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter;
18cffa
-                tlsPrfHash = GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
18cffa
+                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
18cffa
                 if (tlsPrfHash == HASH_AlgNULL) {
18cffa
                     crv = CKR_MECHANISM_PARAM_INVALID;
18cffa
                     break;
18cffa
                 }
18cffa
             } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
18cffa
                 tlsPrfHash = HASH_AlgSHA256;
18cffa
             }
18cffa
 
18cffa
diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h
18cffa
--- a/lib/softoken/pkcs11i.h
18cffa
+++ b/lib/softoken/pkcs11i.h
18cffa
@@ -908,16 +908,19 @@ sftk_MACConstantTimeCtx *sftk_HMACConsta
18cffa
 sftk_MACConstantTimeCtx *sftk_SSLv3MACConstantTime_New(
18cffa
     CK_MECHANISM_PTR mech, SFTKObject *key);
18cffa
 void sftk_HMACConstantTime_Update(void *pctx, const void *data, unsigned int len);
18cffa
 void sftk_SSLv3MACConstantTime_Update(void *pctx, const void *data, unsigned int len);
18cffa
 void sftk_MACConstantTime_EndHash(
18cffa
     void *pctx, void *out, unsigned int *outLength, unsigned int maxLength);
18cffa
 void sftk_MACConstantTime_DestroyContext(void *pctx, PRBool);
18cffa
 
18cffa
+/* Crypto Utilities */
18cffa
+HASH_HashType sftk_GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech);
18cffa
+
18cffa
 /****************************************
18cffa
  * implement TLS Pseudo Random Function (PRF)
18cffa
  */
18cffa
 
18cffa
 extern CK_RV
18cffa
 sftk_TLSPRFInit(SFTKSessionContext *context,
18cffa
                 SFTKObject *key,
18cffa
                 CK_KEY_TYPE key_type,
18cffa
diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c
18cffa
--- a/lib/softoken/pkcs11u.c
18cffa
+++ b/lib/softoken/pkcs11u.c
18cffa
@@ -95,16 +95,17 @@ CK_RV
18cffa
 sftk_MapVerifyError(int error)
18cffa
 {
18cffa
     CK_RV crv = sftk_MapCryptError(error);
18cffa
     if (crv == CKR_DEVICE_ERROR)
18cffa
         crv = CKR_SIGNATURE_INVALID;
18cffa
     return crv;
18cffa
 }
18cffa
 
18cffa
+
18cffa
 /*
18cffa
  * ******************** Attribute Utilities *******************************
18cffa
  */
18cffa
 
18cffa
 /*
18cffa
  * create a new attribute with type, value, and length. Space is allocated
18cffa
  * to hold value.
18cffa
  */
18cffa
@@ -2243,17 +2244,49 @@ sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE 
18cffa
             flags = CKF_MESSAGE_VERIFY;
18cffa
             break;
18cffa
         default:
18cffa
             break;
18cffa
     }
18cffa
     return flags;
18cffa
 }
18cffa
 
18cffa
+/*
18cffa
+ * ******************** Hash Utilities **************************
18cffa
+ */
18cffa
+/*
18cffa
+ * Utility function for converting PSS/OAEP parameter types into
18cffa
+ * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447.
18cffa
+ */
18cffa
+HASH_HashType
18cffa
+sftk_GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)
18cffa
+{
18cffa
+    switch (mech) {
18cffa
+        case CKM_SHA_1:
18cffa
+        case CKG_MGF1_SHA1:
18cffa
+            return HASH_AlgSHA1;
18cffa
+        case CKM_SHA224:
18cffa
+        case CKG_MGF1_SHA224:
18cffa
+            return HASH_AlgSHA224;
18cffa
+        case CKM_SHA256:
18cffa
+        case CKG_MGF1_SHA256:
18cffa
+            return HASH_AlgSHA256;
18cffa
+        case CKM_SHA384:
18cffa
+        case CKG_MGF1_SHA384:
18cffa
+            return HASH_AlgSHA384;
18cffa
+        case CKM_SHA512:
18cffa
+        case CKG_MGF1_SHA512:
18cffa
+            return HASH_AlgSHA512;
18cffa
+        default:
18cffa
+            return HASH_AlgNULL;
18cffa
+    }
18cffa
+}
18cffa
+
18cffa
 #ifdef NSS_HAS_FIPS_INDICATORS
18cffa
+/**************** FIPS Indicator Utilities *************************/
18cffa
 /* sigh, we probably need a version of this in secutil so that both
18cffa
  * softoken and NSS can use it */
18cffa
 static SECOidTag
18cffa
 sftk_quickGetECCCurveOid(SFTKObject *source)
18cffa
 {
18cffa
     SFTKAttribute *attribute = sftk_FindAttribute(source, CKA_EC_PARAMS);
18cffa
     unsigned char *encoded;
18cffa
     int len;
18cffa
@@ -2379,16 +2412,39 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
18cffa
             if (mech->ulParameterLen == 0) {
18cffa
                 /* AEAD ciphers are only in FIPS mode if we are using the
18cffa
                  * MESSAGE interface. This takes an empty parameter
18cffa
                  * in the init function */
18cffa
                 return PR_TRUE;
18cffa
             }
18cffa
             return PR_FALSE;
18cffa
         }
18cffa
+        case SFTKFIPSRSAPSS: {
18cffa
+            /* PSS salt must not be greater than the length of the
18cffa
+             * underlying hash. We verify that the underlying hash of the
18cffa
+             * parameters matches Hash of the combined hash mechanisms, so
18cffa
+             * we don't need to look at the specific PSS mechanism */
18cffa
+            CK_RSA_PKCS_PSS_PARAMS *pss = (CK_RSA_PKCS_PSS_PARAMS *)
18cffa
+                                           mech->pParameter;
18cffa
+            const SECHashObject *hashObj = NULL;
18cffa
+            if (mech->ulParameterLen != sizeof(*pss)) {
18cffa
+                return PR_FALSE;
18cffa
+            }
18cffa
+            /* we use the existing hash utilities to find the length of
18cffa
+             * the hash */
18cffa
+            hashObj = HASH_GetRawHashObject(sftk_GetHashTypeFromMechanism(
18cffa
+                      pss->hashAlg));
18cffa
+            if (hashObj == NULL) {
18cffa
+                return PR_FALSE;
18cffa
+            }
18cffa
+            if (pss->sLen > hashObj->length) {
18cffa
+                return PR_FALSE;
18cffa
+            }
18cffa
+            return PR_TRUE;
18cffa
+        }
18cffa
         default:
18cffa
             break;
18cffa
     }
18cffa
     /* if we didn't understand the special processing, mark it non-fips */
18cffa
     return PR_FALSE;
18cffa
 }
18cffa
 #endif
18cffa