diff -Naur security/nss/lib/cryptohi/cryptohi.h security/nss/lib/cryptohi/cryptohi.h
--- security/nss/lib/cryptohi/cryptohi.h	2011-04-21 14:37:49.483603476 +0200
+++ security/nss/lib/cryptohi/cryptohi.h	2011-04-21 14:38:55.046296668 +0200
@@ -396,6 +396,9 @@
 				const SECAlgorithmID *algid, SECOidTag *hash,
 				void *wincx);
 
+extern SECStatus
+PSSU_DecodeDERPSSParams(CK_RSA_PKCS_PSS_PARAMS *dest, SECOidTag *hashAlg,
+	       const SECItem *in);
 
 SEC_END_PROTOS
 
diff -Naur security/nss/lib/cryptohi/keyi.h security/nss/lib/cryptohi/keyi.h
--- security/nss/lib/cryptohi/keyi.h	2011-04-21 14:37:49.483603476 +0200
+++ security/nss/lib/cryptohi/keyi.h	2011-04-21 14:38:55.046296668 +0200
@@ -50,7 +50,8 @@
  * algorithm, key and parameters (parameters is the parameters field
  * of a algorithm ID structure (SECAlgorithmID)*/
 SECStatus sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
-             const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg);
+             const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg,
+             void **outparam);
 
 SEC_END_PROTOS
 
diff -Naur security/nss/lib/cryptohi/manifest.mn security/nss/lib/cryptohi/manifest.mn
--- security/nss/lib/cryptohi/manifest.mn	2011-04-21 14:37:49.483603476 +0200
+++ security/nss/lib/cryptohi/manifest.mn	2011-04-21 14:38:55.047296662 +0200
@@ -58,6 +58,7 @@
 	secsign.c \
 	secvfy.c  \
 	dsautil.c \
+	pssutil.c \
 	$(NULL)
 
 # This part of the code, including all sub-dirs, can be optimized for size
diff -Naur security/nss/lib/cryptohi/pssutil.c security/nss/lib/cryptohi/pssutil.c
--- security/nss/lib/cryptohi/pssutil.c	1970-01-01 01:00:00.000000000 +0100
+++ security/nss/lib/cryptohi/pssutil.c	2011-04-21 14:38:55.049296650 +0200
@@ -0,0 +1,145 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Hanno Boeck <hanno@hboeck.de>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "cryptohi.h"
+#include "secasn1.h"
+#include "secitem.h"
+#include "secder.h"
+#include "secerr.h"
+#include "pkcs11t.h"
+#include "pk11pub.h"
+
+/*
+** Decode a DER encoded RSA-PSS parameter block to a PKCS #11 structure
+** and get OID tag of hash algorithm. The latter can be NULL if it's
+** not needed
+*/
+SECStatus
+PSSU_DecodeDERPSSParams(CK_RSA_PKCS_PSS_PARAMS *dest, SECOidTag *hashAlg, 
+               const SECItem *in)
+{
+    SECKEYRSAPSSParams pss_params;
+    PRArenaPool *arena;
+    SECStatus rv;
+    SECAlgorithmID algId;
+    SECOidTag oid, oid2;
+
+    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    if (!arena) {
+	PORT_SetError(SEC_ERROR_NO_MEMORY);
+	return SECFailure;
+    }
+    PORT_Memset(&pss_params, 0, sizeof pss_params);
+    rv = SEC_QuickDERDecodeItem(arena, &pss_params,
+				SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate),
+				in);
+    if (rv != SECSuccess) {
+	PORT_SetError(SEC_ERROR_INVALID_ARGS);
+	goto finish;
+    }
+
+    /* Hash algorithm */
+    if (pss_params.hashAlg) {
+	oid = SECOID_FindOIDTag(&pss_params.hashAlg->algorithm);
+    } else {
+	oid = SEC_OID_SHA1;
+    }
+    if (hashAlg!=NULL) {
+	*hashAlg = oid;
+    }
+
+    if (dest == NULL) {
+	rv = SECSuccess;
+	goto finish;
+    }
+
+    dest->hashAlg = PK11_AlgtagToMechanism(oid);
+
+    /* According to RFC 4055, only five algorithms supported */
+    if ((dest->hashAlg != CKM_SHA_1) && (dest->hashAlg != CKM_SHA256) &&
+       (dest->hashAlg != CKM_SHA384) && (dest->hashAlg != CKM_SHA512) &&
+       (dest->hashAlg != CKM_SHA224)) {
+	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+	rv = SECFailure;
+	goto finish;
+    }
+
+    /* Mask Generation Function */
+    if (pss_params.maskAlg) {
+	rv = SEC_QuickDERDecodeItem(arena, &algId,
+				    SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
+				    &pss_params.maskAlg->parameters);
+	if (rv != SECSuccess) {
+	    PORT_FreeArena(arena, PR_FALSE);
+	    rv = SECFailure;
+	    goto finish;
+	}
+
+	oid = SECOID_FindOIDTag(&pss_params.maskAlg->algorithm);
+	oid2 = SECOID_FindOIDTag(&algId.algorithm);
+	dest->mgf = PK11_MgfMap(oid, oid2);
+	if (dest->mgf == NULL) {
+	    PORT_FreeArena(arena, PR_FALSE);
+	    rv = SECFailure;
+	    goto finish;
+	}
+    } else {
+	dest->mgf = CKG_MGF1_SHA1;
+    }
+
+    /* Salt length */
+    if (pss_params.saltLength.len > 0) {
+	dest->sLen = DER_GetInteger(&pss_params.saltLength);
+    } else {
+	dest->sLen = 20;
+    }
+
+    /* Trailer field (must be absent or 1) */
+    if (pss_params.trailerField.len > 0) {
+	if (DER_GetInteger(&pss_params.trailerField) != 1) {
+	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
+	    rv = SECFailure;
+	    goto finish;
+	}
+    }
+
+    rv = SECSuccess;
+
+finish:
+    PORT_FreeArena(arena, PR_FALSE);
+
+    return rv;
+}
diff -Naur security/nss/lib/cryptohi/secsign.c security/nss/lib/cryptohi/secsign.c
--- security/nss/lib/cryptohi/secsign.c	2011-04-21 14:37:58.453561659 +0200
+++ security/nss/lib/cryptohi/secsign.c	2011-04-21 14:38:55.050296644 +0200
@@ -74,7 +74,7 @@
      * it may just support CKM_RSA_PKCS_WITH_SHA1 and/or CKM_RSA_PKCS_WITH_MD5.
      */
     /* we have a private key, not a public key, so don't pass it in */
-    rv =  sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg);
+    rv =  sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg, NULL);
     if (rv != SECSuccess) {
 	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
 	return 0;
diff -Naur security/nss/lib/cryptohi/secvfy.c security/nss/lib/cryptohi/secvfy.c
--- security/nss/lib/cryptohi/secvfy.c	2011-04-21 14:37:58.454561654 +0200
+++ security/nss/lib/cryptohi/secvfy.c	2011-04-21 14:41:33.252545354 +0200
@@ -140,11 +140,17 @@
 	/* the full ECDSA signature */
 	unsigned char ecdsasig[2 * MAX_ECKEY_LEN];
     } u;
+    /* For RSA-PSS, we use a pointer buffer, as there is no
+     * maximum size of a signature.
+     * TODO: convert DSA and ECDSA to also use pbuffer
+    */
+    unsigned char *pbuffer;
     unsigned int rsadigestlen;
     void * wincx;
     void *hashcx;
     const SECHashObject *hashobj;
     SECOidTag encAlg;  /* enc alg */
+    void *params;
     PRBool hasSignature;  /* true if the signature was provided in the
                            * VFY_CreateContext call.  If false, the
                            * signature must be provided with a
@@ -213,12 +219,14 @@
  */
 SECStatus
 sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg, 
-             const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg)
+             const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg,
+             void **outparam)
 {
     int len;
     PRArenaPool *arena;
     SECStatus rv;
     SECItem oid;
+    CK_RSA_PKCS_PSS_PARAMS *ck_pss;
 
     PR_ASSERT(hashalg!=NULL);
     PR_ASSERT(encalg!=NULL);
@@ -237,10 +245,30 @@
         *hashalg = SEC_OID_SHA1;
 	break;
       case SEC_OID_PKCS1_RSA_ENCRYPTION:
+	*hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
+	break;
       case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
-        *hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
+	if (param != NULL) {
+	    if (outparam != NULL) {
+		*outparam = PORT_Alloc(sizeof(CK_RSA_PKCS_PSS_PARAMS));
+		if (*outparam == NULL) {
+		    PORT_SetError(SEC_ERROR_NO_MEMORY);
+		    return SECFailure;
+		}
+		rv = PSSU_DecodeDERPSSParams(*outparam, hashalg, param);
+	    } else if (param == NULL) {
+		rv = PSSU_DecodeDERPSSParams(NULL, hashalg, param);
+	    }
+	    if (rv != SECSuccess) {
+		PORT_SetError(SEC_ERROR_INVALID_ARGS);
+		PORT_Free(*outparam);
+		return SECFailure;
+	    }
+	} else {
+	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
+	    return SECFailure;
+	}
 	break;
-
       case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
 	*hashalg = SEC_OID_SHA224;
 	break;
@@ -364,6 +392,17 @@
     return SECSuccess;
 }
 
+static SECStatus
+sec_KeyMatchAlg(KeyType key, KeyType alg)
+{
+    if ((key == alg) ||
+	((key == rsaKey) && (alg == rsaPssKey))) {
+	return SECSuccess;
+    }
+    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+    return SECFailure;
+}
+
 /*
  * we can verify signatures that come from 2 different sources:
  *  one in with the signature contains a signature oid, and the other
@@ -377,21 +416,19 @@
  * in the RSA signature block.
  */
 static VFYContext *
-vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig, 
-	SECOidTag encAlg, SECOidTag hashAlg, SECOidTag *hash, void *wincx)
+vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
+	SECOidTag encAlg, SECOidTag hashAlg, void *params, SECOidTag *hash,
+	void *wincx)
 {
     VFYContext *cx;
     SECStatus rv;
     unsigned int sigLen;
-    KeyType type;
+    KeyType algKeyType;
 
-    /* make sure the encryption algorithm matches the key type */
-    /* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */
-    type = seckey_GetKeyType(encAlg);
-    if ((key->keyType != type) &&
-	((key->keyType != rsaKey) || (type != rsaPssKey))) {
-	PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH);
-	return NULL;
+    algKeyType = seckey_GetKeyType(encAlg);
+    rv = sec_KeyMatchAlg(key->keyType, algKeyType);
+    if (rv != SECSuccess) {
+	goto loser;
     }
 
     cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext));
@@ -403,10 +440,11 @@
     cx->hasSignature = (sig != NULL);
     cx->encAlg = encAlg;
     cx->hashAlg = hashAlg;
+    cx->params = params;
     cx->key = SECKEY_CopyPublicKey(key);
     rv = SECSuccess;
     if (sig) {
-	switch (type) {
+	switch (algKeyType) {
 	case rsaKey:
 	    rv = DecryptSigBlock(&cx->hashAlg, cx->u.buffer, &cx->rsadigestlen,
 			HASH_LENGTH_MAX, cx->key, sig, (char*)wincx);
@@ -415,6 +453,10 @@
 		rv = SECFailure;	
 	    }
 	    break;
+	case rsaPssKey:
+	    cx->pbuffer = PORT_Alloc(sig->len);
+	    PORT_Memcpy(cx->pbuffer, sig->data, sig->len);
+	    break;
 	case dsaKey:
 	case ecKey:
 	    sigLen = SECKEY_SignatureLen(key);
@@ -457,11 +499,13 @@
 		  void *wincx)
 {
     SECOidTag encAlg, hashAlg;
-    SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg);
+    void *params = NULL;
+    SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg,
+				    &params);
     if (rv != SECSuccess) {
 	return NULL;
     }
-    return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
+    return vfy_CreateContext(key, sig, encAlg, hashAlg, params, NULL, wincx);
 }
 
 VFYContext *
@@ -469,7 +513,7 @@
 			SECOidTag encAlg, SECOidTag hashAlg, 
 			SECOidTag *hash, void *wincx)
 {
-  return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
+  return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, hash, wincx);
 }
 
 VFYContext *
@@ -477,13 +521,14 @@
 	      const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx)
 {
     SECOidTag encAlg, hashAlg;
+    void *params = NULL;
     SECStatus rv = sec_DecodeSigAlg(key, 
 		    SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm), 
-		    &sigAlgorithm->parameters, &encAlg, &hashAlg);
+		    &sigAlgorithm->parameters, &encAlg, &hashAlg, &params);
     if (rv != SECSuccess) {
 	return NULL;
     }
-    return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
+    return vfy_CreateContext(key, sig, encAlg, hashAlg, params, hash, wincx);
 }
 
 void
@@ -494,6 +539,12 @@
 	    (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
 	    cx->hashcx = NULL;
 	}
+	if (cx->params != NULL) {
+	    PORT_Free(cx->params);
+	}
+	if (cx->pbuffer != NULL) {
+	    PORT_Free(cx->pbuffer);
+	}
 	if (cx->key) {
 	    SECKEY_DestroyPublicKey(cx->key);
 	}
@@ -539,8 +590,15 @@
 {
     unsigned char final[HASH_LENGTH_MAX];
     unsigned part;
-    SECItem hash,dsasig; /* dsasig is also used for ECDSA */
+    SECItem hash,dsasig; /* dsasig is used for DSA, ECDSA and RSA-PSS */
     SECStatus rv;
+    KeyType algKeyType;
+
+    algKeyType = seckey_GetKeyType(cx->encAlg);
+    rv = sec_KeyMatchAlg(cx->key->keyType, algKeyType);
+    if (rv != SECSuccess) {
+	return rv;
+    }
 
     if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -552,7 +610,7 @@
 	return SECFailure;
     }
     (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
-    switch (cx->key->keyType) {
+    switch (algKeyType) {
       case ecKey:
       case dsaKey:
 	dsasig.data = cx->u.buffer;
@@ -591,6 +649,23 @@
 	    return SECFailure;
 	}
 	break;
+      case rsaPssKey:
+	if (sig) {
+	    cx->pbuffer = PORT_Alloc(sig->len);
+	    PORT_Memcpy(cx->pbuffer, sig->data, sig->len);
+	}
+	dsasig.data = cx->pbuffer;
+	dsasig.len = SECKEY_SignatureLen(cx->key);
+	hash.data = final;
+	hash.len = part;
+	if (PK11_VerifyWithSigAlg(cx->key, &dsasig, &hash,
+				SEC_OID_PKCS1_RSA_PSS_SIGNATURE, cx->params,
+				sizeof(CK_RSA_PKCS_PSS_PARAMS),
+				cx->wincx) != SECSuccess) {
+	    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+	    return SECFailure;
+	}
+	break;
       default:
 	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
 	return SECFailure; /* shouldn't happen */
@@ -611,17 +686,24 @@
 static SECStatus
 vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key, 
 		 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
-		 void *wincx)
+		 void *params, void *wincx)
 {
     SECStatus rv;
     VFYContext *cx;
-    SECItem dsasig; /* also used for ECDSA */
+    SECItem dsasig; /* used for DSA, ECDSA and RSA-PSS */
+    KeyType algKeyType;
+
+    algKeyType = seckey_GetKeyType(encAlg);
+    rv = sec_KeyMatchAlg(key->keyType, algKeyType);
+    if (rv != SECSuccess) {
+	return rv;
+    }
 
     rv = SECFailure;
 
-    cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
+    cx = vfy_CreateContext(key, sig, encAlg, hashAlg, params, NULL, wincx);
     if (cx != NULL) {
-	switch (key->keyType) {
+	switch (algKeyType) {
 	case rsaKey:
 	    if ((digest->len != cx->rsadigestlen) ||
 		PORT_Memcmp(digest->data, cx->u.buffer, digest->len)) {
@@ -644,6 +726,18 @@
 		rv = SECSuccess;
 	    }
 	    break;
+	case rsaPssKey:
+	    dsasig.data = cx->pbuffer;
+	    dsasig.len = SECKEY_SignatureLen(cx->key);
+	    if (PK11_VerifyWithSigAlg(cx->key, &dsasig, digest,
+				      SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
+				      cx->params,
+				      sizeof(CK_RSA_PKCS_PSS_PARAMS),
+				      cx->wincx) != SECSuccess) {
+	    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+	    return SECFailure;
+	    }
+	break;
 	default:
 	    break;
 	}
@@ -657,7 +751,7 @@
 		       const SECItem *sig, SECOidTag encAlg, 
 		       SECOidTag hashAlg, void *wincx)
 {
-    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
+    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, NULL, wincx);
 }
 
 SECStatus
@@ -665,11 +759,13 @@
 		 SECOidTag algid, void *wincx)
 {
     SECOidTag encAlg, hashAlg;
-    SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
+    void *params = NULL;
+    SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg,
+				    &params);
     if (rv != SECSuccess) {
 	return SECFailure;
     }
-    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
+    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, params, wincx);
 }
 
 /*
@@ -683,9 +779,10 @@
 		SECOidTag hashCmp, void *wincx)
 {
     SECOidTag encAlg, hashAlg;
+    void *params = NULL;
     SECStatus rv = sec_DecodeSigAlg(key, 
 		    SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm), 
-		    &sigAlgorithm->parameters, &encAlg, &hashAlg);
+		    &sigAlgorithm->parameters, &encAlg, &hashAlg, &params);
     if (rv != SECSuccess) {
 	return rv;
     }
@@ -695,18 +792,18 @@
 	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
 	return SECFailure;
     }
-    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
+    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, params, wincx);
 }
 
 static SECStatus
 vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
 	       const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
-	       SECOidTag *hash, void *wincx)
+	       void *params, SECOidTag *hash, void *wincx)
 {
     SECStatus rv;
     VFYContext *cx;
 
-    cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
+    cx = vfy_CreateContext(key, sig, encAlg, hashAlg, params, hash, wincx);
     if (cx == NULL)
 	return SECFailure;
 
@@ -721,13 +818,16 @@
     return rv;
 }
 
+/* This public API function is not able to verify */
+/* RSA-PSS signatures */
 SECStatus
 VFY_VerifyDataDirect(const unsigned char *buf, int len, 
 		     const SECKEYPublicKey *key, const SECItem *sig,
 		     SECOidTag encAlg, SECOidTag hashAlg,
 		     SECOidTag *hash, void *wincx)
 {
-    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
+    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, hash,
+			  wincx);
 }
 
 SECStatus
@@ -735,11 +835,14 @@
 	       const SECItem *sig, SECOidTag algid, void *wincx)
 {
     SECOidTag encAlg, hashAlg;
-    SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
+    void *params = NULL;
+    SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg,
+				    &params);
     if (rv != SECSuccess) {
 	return rv;
     }
-    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, wincx);
+    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, params, NULL,
+			  wincx);
 }
 
 SECStatus
@@ -750,11 +853,14 @@
 			      SECOidTag *hash, void *wincx)
 {
     SECOidTag encAlg, hashAlg;
+    void *params = NULL;
     SECOidTag sigAlg = SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm);
     SECStatus rv     = sec_DecodeSigAlg(key, sigAlg, 
-		                &sigAlgorithm->parameters, &encAlg, &hashAlg);
+		                &sigAlgorithm->parameters, &encAlg, &hashAlg,
+		                &params);
     if (rv != SECSuccess) {
 	return rv;
     }
-    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
+    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, params, hash,
+			  wincx);
 }
diff -Naur security/nss/lib/freebl/hasht.h security/nss/lib/freebl/hasht.h
--- security/nss/lib/freebl/hasht.h	2011-04-21 14:37:49.483603476 +0200
+++ security/nss/lib/freebl/hasht.h	2011-04-21 14:38:55.053296627 +0200
@@ -58,6 +58,10 @@
     HASH_AlgTOTAL
 } HASH_HashType;
 
+typedef enum {
+    MGF_AlgMGF1   = 1
+} MGFType;
+
 /*
  * Number of bytes each hash algorithm produces
  */
diff -Naur security/nss/lib/pk11wrap/pk11obj.c security/nss/lib/pk11wrap/pk11obj.c
--- security/nss/lib/pk11wrap/pk11obj.c	2011-04-21 14:37:49.471603532 +0200
+++ security/nss/lib/pk11wrap/pk11obj.c	2011-04-21 14:38:55.053296627 +0200
@@ -686,6 +686,17 @@
 SECStatus
 PK11_Verify(SECKEYPublicKey *key, SECItem *sig, SECItem *hash, void *wincx)
 {
+    return PK11_VerifyWithSigAlg(key, sig, hash, SEC_OID_UNKNOWN, NULL, 0, wincx);
+}
+
+/*
+ * verify a signature from it's hash, specify mechanism and parameters
+ */
+SECStatus
+PK11_VerifyWithSigAlg(SECKEYPublicKey *key, SECItem *sig, const SECItem *hash,
+                    SECOidTag sigAlg, const void *sigParams,
+                    unsigned int sigParamsLen, void *wincx)
+{
     PK11SlotInfo *slot = key->pkcs11Slot;
     CK_OBJECT_HANDLE id = key->pkcs11ID;
     CK_MECHANISM mech = {0, NULL, 0 };
@@ -693,17 +704,23 @@
     CK_SESSION_HANDLE session;
     CK_RV crv;
 
-    mech.mechanism = PK11_MapSignKeyType(key->keyType);
+    if (sigAlg != SEC_OID_UNKNOWN) {
+	mech.mechanism = PK11_AlgtagToMechanism(sigAlg);
+    } else {
+	mech.mechanism = PK11_MapSignKeyType(key->keyType);
+    }
+    mech.pParameter = sigParams;
+    mech.ulParameterLen = sigParamsLen;
 
     if (slot == NULL) {
 	slot = PK11_GetBestSlot(mech.mechanism,wincx);
-       
+
 	if (slot == NULL) {
 	    PORT_SetError( SEC_ERROR_NO_MODULE );
 	    return SECFailure;
 	}
 	id = PK11_ImportPublicKey(slot,key,PR_FALSE);
-            
+
     } else {
 	PK11_ReferenceSlot(slot);
     }
diff -Naur security/nss/lib/pk11wrap/pk11pub.h security/nss/lib/pk11wrap/pk11pub.h
--- security/nss/lib/pk11wrap/pk11pub.h	2011-04-21 14:38:02.937540738 +0200
+++ security/nss/lib/pk11wrap/pk11pub.h	2011-04-21 14:38:55.054296622 +0200
@@ -686,6 +686,10 @@
 						 SECItem *dsig, void * wincx);
 SECStatus PK11_Verify(SECKEYPublicKey *key, SECItem *sig, 
 						SECItem *hash, void *wincx);
+SECStatus PK11_VerifyWithSigAlg(SECKEYPublicKey *key, SECItem *sig,
+			      const SECItem *hash, SECOidTag sigAlg,
+			      const void *mech_parameter,
+			      unsigned int mech_parameter_len, void *wincx);
 
 
 
