Blame SOURCES/opensc-0.19.0-rsa-pss.patch

3143c4
?From b85c0706db871828f0bc4672571dd0b9c98dd835 Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Sun, 22 Jul 2018 16:23:54 +0200
3143c4
Subject: [PATCH 1/5] doc: Fix the pkcs11-tool example
3143c4
3143c4
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
3143c4
---
3143c4
 doc/tools/pkcs11-tool.1.xml | 2 +-
3143c4
 1 file changed, 1 insertion(+), 1 deletion(-)
3143c4
3143c4
diff --git a/doc/tools/pkcs11-tool.1.xml b/doc/tools/pkcs11-tool.1.xml
3143c4
index 37093f352..c609ec0e2 100644
3143c4
--- a/doc/tools/pkcs11-tool.1.xml
3143c4
+++ b/doc/tools/pkcs11-tool.1.xml
3143c4
@@ -568,7 +568,7 @@
3143c4
 
3143c4
 			To read the certificate with ID <replaceable>KEY_ID</replaceable>
3143c4
 			in DER format from smart card:
3143c4
-				<programlisting>pkcs11-tool --read-object  --id KEY_ID --type cert --outfile cert.der</programlisting>
3143c4
+				<programlisting>pkcs11-tool --read-object  --id KEY_ID --type cert --output-file cert.der</programlisting>
3143c4
 
3143c4
 			To convert the certificate in DER format to PEM format, use OpenSSL
3143c4
 			tools:
3143c4
3143c4
From 5cc144111acb7b9982ddec7f7597a22c10c4d456 Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Fri, 14 Sep 2018 14:11:18 +0200
3143c4
Subject: [PATCH 2/5] p11test: Add missing CKM_SHA224_RSA_PKCS_PSS
3143c4
3143c4
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
3143c4
---
3143c4
 src/tests/p11test/p11test_case_common.c | 2 ++
3143c4
 1 file changed, 2 insertions(+)
3143c4
3143c4
diff --git a/src/tests/p11test/p11test_case_common.c b/src/tests/p11test/p11test_case_common.c
3143c4
index deb2a56fe..d44b0d8e3 100644
3143c4
--- a/src/tests/p11test/p11test_case_common.c
3143c4
+++ b/src/tests/p11test/p11test_case_common.c
3143c4
@@ -587,6 +587,8 @@ const char *get_mechanism_name(int mech_id)
3143c4
 			return "RSA_PKCS_PSS";
3143c4
 		case CKM_SHA1_RSA_PKCS_PSS:
3143c4
 			return "SHA1_RSA_PKCS_PSS";
3143c4
+		case CKM_SHA224_RSA_PKCS_PSS:
3143c4
+			return "SHA224_RSA_PKCS_PSS";
3143c4
 		case CKM_SHA256_RSA_PKCS_PSS:
3143c4
 			return "SHA256_RSA_PKCS_PSS";
3143c4
 		case CKM_SHA384_RSA_PKCS_PSS:
3143c4
3143c4
From 5aa3dbcdd76af0197946252ff53a0636cb979ab3 Mon Sep 17 00:00:00 2001
3143c4
From: Nicholas Wilson <nicholas.wilson@realvnc.com>
3143c4
Date: Tue, 25 Aug 2015 12:45:27 +0100
3143c4
Subject: [PATCH 3/5] Add support for PSS padding to RSA signatures
3143c4
3143c4
A card driver may declare support for computing the padding on the card,
3143c4
or else the padding will be applied locally in padding.c.  All five
3143c4
PKCS11 PSS mechanisms are supported, for signature and verification.
3143c4
3143c4
There are a few limits on what we choose to support, in particular I
3143c4
don't see a need for arbitrary combinations of MGF hash, data hash, and
3143c4
salt length, so I've restricted it (for the user's benefit) to the only
3143c4
cases that really matter, where salt_len = hash_len and the same hash is
3143c4
used for the MGF and data hashing.
3143c4
3143c4
------------------------------------------------------------------------
3143c4
Reworked and extended in 2018 by Jakub Jelen <jjelen@redhat.com> against
3143c4
current OpenSC master, to actually work with existing PIV cards:
3143c4
 * extended of missing mechanisms (SHA224, possibility to select MGF1)
3143c4
 * compatibility with OpenSSL 1.1+
3143c4
 * Removed the ANSI padding
3143c4
 * Formatting cleanup, error checking
3143c4
3143c4
Based on the original work from
3143c4
3143c4
https://github.com/NWilson/OpenSC/commit/42f3199e66
3143c4
3143c4
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
3143c4
---
3143c4
 src/libopensc/card-atrust-acos.c |   2 +-
3143c4
 src/libopensc/card-starcos.c     |   4 +-
3143c4
 src/libopensc/internal.h         |   2 +-
3143c4
 src/libopensc/opensc.h           |  74 +++++++--
3143c4
 src/libopensc/padding.c          | 257 ++++++++++++++++++++++++++----
3143c4
 src/libopensc/pkcs15-sec.c       |  33 ++--
3143c4
 src/pkcs11/framework-pkcs15.c    | 265 +++++++++++++++++++++++--------
3143c4
 src/pkcs11/mechanism.c           |  31 +++-
3143c4
 src/pkcs11/openssl.c             | 151 ++++++++++++++++--
3143c4
 src/pkcs11/pkcs11.h              |   3 +-
3143c4
 src/pkcs11/sc-pkcs11.h           |   9 +-
3143c4
 11 files changed, 674 insertions(+), 157 deletions(-)
3143c4
3143c4
diff --git a/src/libopensc/card-atrust-acos.c b/src/libopensc/card-atrust-acos.c
3143c4
index fb0b296c8..05ef0f441 100644
3143c4
--- a/src/libopensc/card-atrust-acos.c
3143c4
+++ b/src/libopensc/card-atrust-acos.c
3143c4
@@ -722,7 +722,7 @@ static int atrust_acos_compute_signature(struct sc_card *card,
3143c4
 				flags = SC_ALGORITHM_RSA_HASH_NONE;
3143c4
 			tmp_len = sizeof(sbuf);
3143c4
 			r = sc_pkcs1_encode(card->ctx, flags, data, datalen,
3143c4
-					sbuf, &tmp_len, sizeof(sbuf));
3143c4
+					sbuf, &tmp_len, sizeof(sbuf)*8);
3143c4
 			if (r < 0)
3143c4
 				return r;
3143c4
 		} else {
3143c4
diff --git a/src/libopensc/card-starcos.c b/src/libopensc/card-starcos.c
3143c4
index 7ad132dc1..799c6a680 100644
3143c4
--- a/src/libopensc/card-starcos.c
3143c4
+++ b/src/libopensc/card-starcos.c
3143c4
@@ -1545,7 +1545,7 @@ static int starcos_compute_signature(sc_card_t *card,
3143c4
 					flags = SC_ALGORITHM_RSA_HASH_NONE;
3143c4
 				}
3143c4
 				tmp_len = sizeof(sbuf);
3143c4
-				r = sc_pkcs1_encode(card->ctx, flags, data, datalen, sbuf, &tmp_len, sizeof(sbuf));
3143c4
+				r = sc_pkcs1_encode(card->ctx, flags, data, datalen, sbuf, &tmp_len, sizeof(sbuf)*8);
3143c4
 				SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_pkcs1_encode failed");
3143c4
 			} else {
3143c4
 				memcpy(sbuf, data, datalen);
3143c4
@@ -1607,7 +1607,7 @@ static int starcos_compute_signature(sc_card_t *card,
3143c4
 				flags = SC_ALGORITHM_RSA_HASH_NONE;
3143c4
 			tmp_len = sizeof(sbuf);
3143c4
 			r = sc_pkcs1_encode(card->ctx, flags, data, datalen,
3143c4
-					sbuf, &tmp_len, sizeof(sbuf));
3143c4
+					sbuf, &tmp_len, sizeof(sbuf)*8);
3143c4
 			if (r < 0)
3143c4
 				return r;
3143c4
 		} else {
3143c4
diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h
3143c4
index 9d6a77ffe..08d590f23 100644
3143c4
--- a/src/libopensc/internal.h
3143c4
+++ b/src/libopensc/internal.h
3143c4
@@ -159,7 +159,7 @@ int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm,
3143c4
  * @return SC_SUCCESS on success and an error code otherwise
3143c4
  */
3143c4
 int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
3143c4
-		const u8 *in, size_t inlen, u8 *out, size_t *outlen, size_t modlen);
3143c4
+		const u8 *in, size_t inlen, u8 *out, size_t *outlen, size_t mod_bits);
3143c4
 /**
3143c4
  * Get the necessary padding and sec. env. flags.
3143c4
  * @param  ctx     IN  sc_contex_t object
3143c4
diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h
3143c4
index b9b960d8f..a4e87d5bf 100644
3143c4
--- a/src/libopensc/opensc.h
3143c4
+++ b/src/libopensc/opensc.h
3143c4
@@ -93,19 +93,39 @@ extern "C" {
3143c4
 #define SC_ALGORITHM_NEED_USAGE		0x40000000
3143c4
 #define SC_ALGORITHM_SPECIFIC_FLAGS	0x001FFFFF
3143c4
 
3143c4
-#define SC_ALGORITHM_RSA_RAW		0x00000001
3143c4
 /* If the card is willing to produce a cryptogram padded with the following
3143c4
- * methods, set these flags accordingly. */
3143c4
-#define SC_ALGORITHM_RSA_PADS		0x0000001E
3143c4
-#define SC_ALGORITHM_RSA_PAD_NONE	0x00000000
3143c4
-#define SC_ALGORITHM_RSA_PAD_PKCS1	0x00000002
3143c4
+ * methods, set these flags accordingly.  These flags are exclusive: an RSA card
3143c4
+ * must support at least one of them, and exactly one of them must be selected
3143c4
+ * for a given operation. */
3143c4
+#define SC_ALGORITHM_RSA_RAW		0x00000001
3143c4
+#define SC_ALGORITHM_RSA_PADS		0x0000001F
3143c4
+#define SC_ALGORITHM_RSA_PAD_NONE	0x00000001
3143c4
+#define SC_ALGORITHM_RSA_PAD_PKCS1	0x00000002 /* PKCS#1 v1.5 padding */
3143c4
 #define SC_ALGORITHM_RSA_PAD_ANSI	0x00000004
3143c4
 #define SC_ALGORITHM_RSA_PAD_ISO9796	0x00000008
3143c4
-#define SC_ALGORITHM_RSA_PAD_PSS	0x00000010
3143c4
+#define SC_ALGORITHM_RSA_PAD_PSS	0x00000010 /* PKCS#1 v2.0 PSS */
3143c4
 
3143c4
 /* If the card is willing to produce a cryptogram with the following
3143c4
- * hash values, set these flags accordingly. */
3143c4
-#define SC_ALGORITHM_RSA_HASH_NONE	0x00000100
3143c4
+ * hash values, set these flags accordingly.  The interpretation of the hash
3143c4
+ * flags depends on the algorithm and padding chosen: for RSA, the hash flags
3143c4
+ * determine how the padding is constructed and do not describe the first
3143c4
+ * hash applied to the document before padding begins.
3143c4
+ *
3143c4
+ *   - For PAD_NONE, ANSI X9.31, (and ISO9796?), the hash value is therefore
3143c4
+ *     ignored.  For ANSI X9.31, the input data must already have the hash
3143c4
+ *     identifier byte appended (eg 0x33 for SHA-1).
3143c4
+ *   - For PKCS1 (v1.5) the hash is recorded in the padding, and HASH_NONE is a
3143c4
+ *     valid value, meaning that the hash's DigestInfo has already been
3143c4
+ *     prepended to the data, otherwise the hash id is put on the front.
3143c4
+ *   - For PSS (PKCS#1 v2.0) the hash is used to derive the padding from the
3143c4
+ *     already-hashed message.
3143c4
+ *
3143c4
+ * In no case is the hash actually applied to the entire document.
3143c4
+ *
3143c4
+ * It's possible that the card may support different hashes for PKCS1 and PSS
3143c4
+ * signatures; in this case the card driver has to pick the lowest-denominator
3143c4
+ * when it sets these flags to indicate its capabilities. */
3143c4
+#define SC_ALGORITHM_RSA_HASH_NONE	0x00000100 /* only applies to PKCS1 padding */
3143c4
 #define SC_ALGORITHM_RSA_HASH_SHA1	0x00000200
3143c4
 #define SC_ALGORITHM_RSA_HASH_MD5	0x00000400
3143c4
 #define SC_ALGORITHM_RSA_HASH_MD5_SHA1	0x00000800
3143c4
@@ -114,21 +134,39 @@ extern "C" {
3143c4
 #define SC_ALGORITHM_RSA_HASH_SHA384	0x00004000
3143c4
 #define SC_ALGORITHM_RSA_HASH_SHA512	0x00008000
3143c4
 #define SC_ALGORITHM_RSA_HASH_SHA224	0x00010000
3143c4
-#define SC_ALGORITHM_RSA_HASHES		0x0001FE00
3143c4
-
3143c4
+#define SC_ALGORITHM_RSA_HASHES		0x0001FF00
3143c4
+
3143c4
+/* This defines the hashes to be used with MGF1 in PSS padding */
3143c4
+#define SC_ALGORITHM_MGF1_SHA1		0x00100000
3143c4
+#define SC_ALGORITHM_MGF1_SHA256	0x00200000
3143c4
+#define SC_ALGORITHM_MGF1_SHA384	0x00400000
3143c4
+#define SC_ALGORITHM_MGF1_SHA512	0x00800000
3143c4
+#define SC_ALGORITHM_MGF1_SHA224	0x01000000
3143c4
+#define SC_ALGORITHM_MGF1_HASHES	0x01F00000
3143c4
+
3143c4
+/* These flags are exclusive: a GOST R34.10 card must support at least one or the
3143c4
+ * other of the methods, and exactly one of them applies to any given operation.
3143c4
+ * Note that the GOST R34.11 hash is actually applied to the data (ie if this
3143c4
+ * algorithm is chosen the entire unhashed document is passed in). */
3143c4
 #define SC_ALGORITHM_GOSTR3410_RAW		0x00020000
3143c4
-#define SC_ALGORITHM_GOSTR3410_HASH_NONE	0x00040000
3143c4
+#define SC_ALGORITHM_GOSTR3410_HASH_NONE	SC_ALGORITHM_GOSTR3410_RAW /*XXX*/
3143c4
 #define SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411	0x00080000
3143c4
-#define SC_ALGORITHM_GOSTR3410_HASHES		0x00080000
3143c4
-/*TODO: -DEE Should the above be 0x0000E000 */
3143c4
-/* Or should the HASH_NONE be 0x00000010  and HASHES be 0x00008010 */
3143c4
-
3143c4
+#define SC_ALGORITHM_GOSTR3410_HASHES		0x000A0000
3143c4
+/*TODO: -DEE Should the above be 0x000E0000 */
3143c4
+/* Or should the HASH_NONE be 0x00000100  and HASHES be 0x00080010 */
3143c4
+
3143c4
+/* The ECDSA flags are exclusive, and exactly one of them applies to any given
3143c4
+ * operation.  If ECDSA with a hash is specified, then the data passed in is
3143c4
+ * the entire document, unhashed, and the hash is applied once to it before
3143c4
+ * truncating and signing.  These flags are distinct from the RSA hash flags,
3143c4
+ * which determine the hash ids the card is willing to put in RSA message
3143c4
+ * padding. */
3143c4
 /* May need more bits if card can do more hashes */
3143c4
 /* TODO: -DEE Will overload RSA_HASHES with EC_HASHES */
3143c4
 /* Not clear if these need their own bits or not */
3143c4
 /* The PIV card does not support and hashes */
3143c4
-#define SC_ALGORITHM_ECDSA_RAW		0x00100000
3143c4
 #define SC_ALGORITHM_ECDH_CDH_RAW	0x00200000
3143c4
+#define SC_ALGORITHM_ECDSA_RAW		0x00100000
3143c4
 #define SC_ALGORITHM_ECDSA_HASH_NONE		SC_ALGORITHM_RSA_HASH_NONE
3143c4
 #define SC_ALGORITHM_ECDSA_HASH_SHA1		SC_ALGORITHM_RSA_HASH_SHA1
3143c4
 #define SC_ALGORITHM_ECDSA_HASH_SHA224		SC_ALGORITHM_RSA_HASH_SHA224
3143c4
@@ -142,7 +180,9 @@ extern "C" {
3143c4
 							SC_ALGORITHM_ECDSA_HASH_SHA512)
3143c4
 
3143c4
 /* define mask of all algorithms that can do raw */
3143c4
-#define SC_ALGORITHM_RAW_MASK (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_GOSTR3410_RAW | SC_ALGORITHM_ECDSA_RAW)
3143c4
+#define SC_ALGORITHM_RAW_MASK (SC_ALGORITHM_RSA_RAW | \
3143c4
+                               SC_ALGORITHM_GOSTR3410_RAW | \
3143c4
+                               SC_ALGORITHM_ECDSA_RAW)
3143c4
 
3143c4
 /* extended algorithm bits for selected mechs */
3143c4
 #define SC_ALGORITHM_EXT_EC_F_P          0x00000001
3143c4
diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c
3143c4
index f544e5778..53a87c352 100644
3143c4
--- a/src/libopensc/padding.c
3143c4
+++ b/src/libopensc/padding.c
3143c4
@@ -23,6 +23,12 @@
3143c4
 #include "config.h"
3143c4
 #endif
3143c4
 
3143c4
+#ifdef ENABLE_OPENSSL
3143c4
+#include <openssl/evp.h>
3143c4
+#include <openssl/rand.h>
3143c4
+#include <openssl/sha.h>
3143c4
+#endif
3143c4
+
3143c4
 #include <string.h>
3143c4
 #include <stdlib.h>
3143c4
 
3143c4
@@ -231,22 +237,183 @@ int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm,
3143c4
 	return SC_ERROR_INTERNAL;
3143c4
 }
3143c4
 
3143c4
+#ifdef ENABLE_OPENSSL
3143c4
+
3143c4
+static const EVP_MD* hash_flag2md(unsigned int hash)
3143c4
+{
3143c4
+	switch (hash & SC_ALGORITHM_RSA_HASHES) {
3143c4
+	case SC_ALGORITHM_RSA_HASH_SHA1:
3143c4
+		return EVP_sha1();
3143c4
+	case SC_ALGORITHM_RSA_HASH_SHA224:
3143c4
+		return EVP_sha224();
3143c4
+	case SC_ALGORITHM_RSA_HASH_SHA256:
3143c4
+		return EVP_sha256();
3143c4
+	case SC_ALGORITHM_RSA_HASH_SHA384:
3143c4
+		return EVP_sha384();
3143c4
+	case SC_ALGORITHM_RSA_HASH_SHA512:
3143c4
+		return EVP_sha512();
3143c4
+	default:
3143c4
+		return NULL;
3143c4
+	}
3143c4
+}
3143c4
+
3143c4
+static const EVP_MD* mgf1_flag2md(unsigned int mgf1)
3143c4
+{
3143c4
+	switch (mgf1 & SC_ALGORITHM_MGF1_HASHES) {
3143c4
+	case SC_ALGORITHM_MGF1_SHA1:
3143c4
+		return EVP_sha1();
3143c4
+	case SC_ALGORITHM_MGF1_SHA224:
3143c4
+		return EVP_sha224();
3143c4
+	case SC_ALGORITHM_MGF1_SHA256:
3143c4
+		return EVP_sha256();
3143c4
+	case SC_ALGORITHM_MGF1_SHA384:
3143c4
+		return EVP_sha384();
3143c4
+	case SC_ALGORITHM_MGF1_SHA512:
3143c4
+		return EVP_sha512();
3143c4
+	default:
3143c4
+		return NULL;
3143c4
+	}
3143c4
+}
3143c4
+
3143c4
+/* add PKCS#1 v2.0 PSS padding */
3143c4
+static int sc_pkcs1_add_pss_padding(unsigned int hash, unsigned int mgf1_hash,
3143c4
+    const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_bits)
3143c4
+{
3143c4
+	/* hLen = sLen in our case */
3143c4
+	int rv = SC_ERROR_INTERNAL, i, j, hlen, dblen, plen, round, mgf_rounds;
3143c4
+	int mgf1_hlen;
3143c4
+	const EVP_MD* md, *mgf1_md;
3143c4
+	EVP_MD_CTX* ctx = NULL;
3143c4
+	u8 buf[8];
3143c4
+	u8 salt[EVP_MAX_MD_SIZE], mask[EVP_MAX_MD_SIZE];
3143c4
+	size_t mod_length = (mod_bits + 7) / 8;
3143c4
+
3143c4
+	if (*out_len < mod_length)
3143c4
+		return SC_ERROR_BUFFER_TOO_SMALL;
3143c4
+
3143c4
+	md = hash_flag2md(hash);
3143c4
+	if (md == NULL)
3143c4
+		return SC_ERROR_NOT_SUPPORTED;
3143c4
+	hlen = EVP_MD_size(md);
3143c4
+	dblen = mod_length - hlen - 1; /* emLen - hLen - 1 */
3143c4
+	plen = mod_length - 2*hlen - 1;
3143c4
+	if (in_len != (unsigned)hlen)
3143c4
+		return SC_ERROR_INVALID_ARGUMENTS;
3143c4
+	if (2 * (unsigned)hlen + 2 > mod_length)
3143c4
+		/* RSA key too small for chosen hash (1296 bits or higher needed for
3143c4
+		 * signing SHA-512 hashes) */
3143c4
+		return SC_ERROR_NOT_SUPPORTED;
3143c4
+
3143c4
+	if (RAND_bytes(salt, hlen) != 1)
3143c4
+		return SC_ERROR_INTERNAL;
3143c4
+
3143c4
+	/* Hash M' to create H */
3143c4
+	if (!(ctx = EVP_MD_CTX_create()))
3143c4
+		goto done;
3143c4
+	memset(buf, 0x00, 8);
3143c4
+	if (EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
3143c4
+	    EVP_DigestUpdate(ctx, buf, 8) != 1 ||
3143c4
+	    EVP_DigestUpdate(ctx, in, hlen) != 1 || /* mHash */
3143c4
+	    EVP_DigestUpdate(ctx, salt, hlen) != 1) {
3143c4
+		goto done;
3143c4
+	}
3143c4
+
3143c4
+	/* Construct padding2, salt, H, and BC in the output block */
3143c4
+	/* DB = PS || 0x01 || salt */
3143c4
+	memset(out, 0x00, plen - 1); /* emLen - sLen - hLen - 2 */
3143c4
+	out[plen - 1] = 0x01;
3143c4
+	memcpy(out + plen, salt, hlen);
3143c4
+	if (EVP_DigestFinal_ex(ctx, out + dblen, NULL) != 1) { /* H */
3143c4
+		goto done;
3143c4
+	}
3143c4
+	out[dblen + hlen] = 0xBC;
3143c4
+	/* EM = DB* || H || 0xbc
3143c4
+	 *  *the first part is masked later */
3143c4
+
3143c4
+	/* Construct the DB mask block by block and XOR it in. */
3143c4
+	mgf1_md = mgf1_flag2md(mgf1_hash);
3143c4
+	if (mgf1_md == NULL)
3143c4
+		return SC_ERROR_NOT_SUPPORTED;
3143c4
+	mgf1_hlen = EVP_MD_size(mgf1_md);
3143c4
+
3143c4
+	mgf_rounds = (dblen + mgf1_hlen - 1) / mgf1_hlen; /* round up */
3143c4
+	for (round = 0; round < mgf_rounds; ++round) {
3143c4
+		buf[0] = (round&0xFF000000U) >> 24;
3143c4
+		buf[1] = (round&0x00FF0000U) >> 16;
3143c4
+		buf[2] = (round&0x0000FF00U) >> 8;
3143c4
+		buf[3] = (round&0x000000FFU);
3143c4
+		if (EVP_DigestInit_ex(ctx, mgf1_md, NULL) != 1 ||
3143c4
+		    EVP_DigestUpdate(ctx, out + dblen, hlen) != 1 || /* H (Z parameter of MGF1) */
3143c4
+		    EVP_DigestUpdate(ctx, buf, 4) != 1 || /* C */
3143c4
+		    EVP_DigestFinal_ex(ctx, mask, NULL)) {
3143c4
+			goto done;
3143c4
+		}
3143c4
+		/* this is no longer part of the MGF1, but actually
3143c4
+		 * XORing mask with DB to create maskedDB inplace */
3143c4
+		for (i = round * mgf1_hlen, j = 0; i < dblen && j < mgf1_hlen; ++i, ++j) {
3143c4
+			out[i] ^= mask[j];
3143c4
+		}
3143c4
+	}
3143c4
+
3143c4
+	/* Set leftmost N bits in leftmost octet in maskedDB to zero
3143c4
+	 * to make sure the result is smaller than the modulus ( +1)
3143c4
+	 */
3143c4
+	out[0] &= (0xff >> (8 * mod_length - mod_bits + 1));
3143c4
+
3143c4
+	*out_len = mod_length;
3143c4
+	rv = SC_SUCCESS;
3143c4
+
3143c4
+done:
3143c4
+	OPENSSL_cleanse(salt, sizeof(salt));
3143c4
+	OPENSSL_cleanse(mask, sizeof(mask));
3143c4
+	if (ctx) {
3143c4
+		EVP_MD_CTX_destroy(ctx);
3143c4
+	}
3143c4
+	return rv;
3143c4
+}
3143c4
+
3143c4
+static int hash_len2algo(size_t hash_len)
3143c4
+{
3143c4
+	switch (hash_len) {
3143c4
+	case SHA_DIGEST_LENGTH:
3143c4
+		return SC_ALGORITHM_RSA_HASH_SHA1;
3143c4
+	case SHA224_DIGEST_LENGTH:
3143c4
+		return SC_ALGORITHM_RSA_HASH_SHA224;
3143c4
+	case SHA256_DIGEST_LENGTH:
3143c4
+		return SC_ALGORITHM_RSA_HASH_SHA256;
3143c4
+	case SHA384_DIGEST_LENGTH:
3143c4
+		return SC_ALGORITHM_RSA_HASH_SHA384;
3143c4
+	case SHA512_DIGEST_LENGTH:
3143c4
+		return SC_ALGORITHM_RSA_HASH_SHA512;
3143c4
+	}
3143c4
+	/* Should never happen -- the mechanism and data should be already
3143c4
+	 * verified to match one of the above. If not, we will fail later
3143c4
+	 */
3143c4
+	return SC_ALGORITHM_RSA_HASH_NONE;
3143c4
+}
3143c4
+#endif
3143c4
+
3143c4
 /* general PKCS#1 encoding function */
3143c4
 int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
3143c4
-	const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_len)
3143c4
+	const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_bits)
3143c4
 {
3143c4
 	int    rv, i;
3143c4
 	size_t tmp_len = *out_len;
3143c4
 	const u8    *tmp = in;
3143c4
 	unsigned int hash_algo, pad_algo;
3143c4
+	size_t mod_len = (mod_bits + 7) / 8;
3143c4
+#ifdef ENABLE_OPENSSL
3143c4
+	unsigned int mgf1_hash;
3143c4
+#endif
3143c4
 
3143c4
 	LOG_FUNC_CALLED(ctx);
3143c4
 
3143c4
-	hash_algo = flags & (SC_ALGORITHM_RSA_HASHES | SC_ALGORITHM_RSA_HASH_NONE);
3143c4
+	hash_algo = flags & SC_ALGORITHM_RSA_HASHES;
3143c4
 	pad_algo  = flags & SC_ALGORITHM_RSA_PADS;
3143c4
 	sc_log(ctx, "hash algorithm 0x%X, pad algorithm 0x%X", hash_algo, pad_algo);
3143c4
 
3143c4
-	if (hash_algo != SC_ALGORITHM_RSA_HASH_NONE) {
3143c4
+	if ((pad_algo == SC_ALGORITHM_RSA_PAD_PKCS1 || !pad_algo) &&
3143c4
+	    hash_algo != SC_ALGORITHM_RSA_HASH_NONE) {
3143c4
 		i = sc_pkcs1_add_digest_info_prefix(hash_algo, in, in_len, out, &tmp_len);
3143c4
 		if (i != SC_SUCCESS) {
3143c4
 			sc_log(ctx, "Unable to add digest info 0x%x", hash_algo);
3143c4
@@ -268,10 +435,29 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
3143c4
 		/* add pkcs1 bt01 padding */
3143c4
 		rv = sc_pkcs1_add_01_padding(tmp, tmp_len, out, out_len, mod_len);
3143c4
 		LOG_FUNC_RETURN(ctx, rv);
3143c4
+	case SC_ALGORITHM_RSA_PAD_PSS:
3143c4
+		/* add PSS padding */
3143c4
+#ifdef ENABLE_OPENSSL
3143c4
+		mgf1_hash = flags & SC_ALGORITHM_MGF1_HASHES;
3143c4
+		if (hash_algo == SC_ALGORITHM_RSA_HASH_NONE) {
3143c4
+			/* this is generic RSA_PKCS1_PSS mechanism with hash
3143c4
+			 * already done outside of the module. The parameters
3143c4
+			 * were already checked so we need to adjust the hash
3143c4
+			 * algorithm to do the padding with the correct hash
3143c4
+			 * function.
3143c4
+			 */
3143c4
+			hash_algo = hash_len2algo(tmp_len);
3143c4
+		}
3143c4
+		rv = sc_pkcs1_add_pss_padding(hash_algo, mgf1_hash,
3143c4
+		    tmp, tmp_len, out, out_len, mod_bits);
3143c4
+#else
3143c4
+		rv = SC_ERROR_NOT_SUPPORTED;
3143c4
+#endif
3143c4
+		LOG_FUNC_RETURN(ctx, rv);
3143c4
 	default:
3143c4
-		/* currently only pkcs1 padding is supported */
3143c4
-		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unsupported padding algorithm 0x%x", pad_algo);
3143c4
-		LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
3143c4
+		/* We shouldn't be called with an unexpected padding type, we've already
3143c4
+		 * returned SC_ERROR_NOT_SUPPORTED if the card can't be used. */
3143c4
+		LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
3143c4
 	}
3143c4
 }
3143c4
 
3143c4
@@ -279,42 +465,45 @@ int sc_get_encoding_flags(sc_context_t *ctx,
3143c4
 	unsigned long iflags, unsigned long caps,
3143c4
 	unsigned long *pflags, unsigned long *sflags)
3143c4
 {
3143c4
-	size_t i;
3143c4
-
3143c4
 	LOG_FUNC_CALLED(ctx);
3143c4
 	if (pflags == NULL || sflags == NULL)
3143c4
 		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
3143c4
 
3143c4
 	sc_log(ctx, "iFlags 0x%lX, card capabilities 0x%lX", iflags, caps);
3143c4
-	for (i = 0; digest_info_prefix[i].algorithm != 0; i++) {
3143c4
-		if (iflags & digest_info_prefix[i].algorithm) {
3143c4
-			if (digest_info_prefix[i].algorithm != SC_ALGORITHM_RSA_HASH_NONE &&
3143c4
-			    caps & digest_info_prefix[i].algorithm)
3143c4
-				*sflags |= digest_info_prefix[i].algorithm;
3143c4
-			else
3143c4
-				*pflags |= digest_info_prefix[i].algorithm;
3143c4
-			break;
3143c4
-		}
3143c4
-	}
3143c4
 
3143c4
-	if (iflags & SC_ALGORITHM_RSA_PAD_PKCS1) {
3143c4
-		if (caps & SC_ALGORITHM_RSA_PAD_PKCS1)
3143c4
-			*sflags |= SC_ALGORITHM_RSA_PAD_PKCS1;
3143c4
-		else
3143c4
-			*pflags |= SC_ALGORITHM_RSA_PAD_PKCS1;
3143c4
-	} else if ((iflags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) {
3143c4
-		
3143c4
-		/* Work with RSA, EC and maybe GOSTR? */
3143c4
-		if (!(caps & SC_ALGORITHM_RAW_MASK))
3143c4
-			LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "raw encryption is not supported");
3143c4
+	/* For ECDSA and GOSTR, we don't do any padding or hashing ourselves, the
3143c4
+	 * card has to support the requested operation.  Similarly, for RSA with
3143c4
+	 * raw padding (raw RSA) and ISO9796, we require the card to do it for us.
3143c4
+	 * Finally, for PKCS1 (v1.5 and PSS) and ASNI X9.31 we can apply the padding
3143c4
+	 * ourselves if the card supports raw RSA. */
3143c4
 
3143c4
-		*sflags |= (caps & SC_ALGORITHM_RAW_MASK); /* adds in the one raw type */
3143c4
+	/* TODO: Could convert GOSTR3410_HASH_GOSTR3411 -> GOSTR3410_RAW and
3143c4
+	 *       ECDSA_HASH_ -> ECDSA_RAW using OpenSSL (not much benefit though). */
3143c4
+
3143c4
+	if ((caps & iflags) == iflags) {
3143c4
+		/* Card supports the signature operation we want to do, great, let's
3143c4
+		 * go with it then. */
3143c4
+		*sflags = iflags;
3143c4
 		*pflags = 0;
3143c4
-	} else if (iflags & SC_ALGORITHM_RSA_PAD_PSS) {
3143c4
-		if (caps & SC_ALGORITHM_RSA_PAD_PSS)
3143c4
-			*sflags |= SC_ALGORITHM_RSA_PAD_PSS;
3143c4
-		else
3143c4
-			*pflags |= SC_ALGORITHM_RSA_PAD_PSS;
3143c4
+
3143c4
+	} else if ((caps & SC_ALGORITHM_RSA_PAD_PSS) &&
3143c4
+                   (iflags & SC_ALGORITHM_RSA_PAD_PSS)) {
3143c4
+		*sflags |= SC_ALGORITHM_RSA_PAD_PSS;
3143c4
+
3143c4
+	} else if (((caps & SC_ALGORITHM_RSA_RAW) &&
3143c4
+	            (iflags & SC_ALGORITHM_RSA_PAD_PKCS1))
3143c4
+	           || iflags & SC_ALGORITHM_RSA_PAD_PSS) {
3143c4
+		/* Use the card's raw RSA capability on the padded input */
3143c4
+		*sflags = SC_ALGORITHM_RSA_PAD_NONE;
3143c4
+		*pflags = iflags;
3143c4
+
3143c4
+	} else if ((caps & (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
3143c4
+	           (iflags & SC_ALGORITHM_RSA_PAD_PKCS1)) {
3143c4
+		/* A corner case - the card can partially do PKCS1, if we prepend the
3143c4
+		 * DigestInfo bit it will do the rest. */
3143c4
+		*sflags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE;
3143c4
+		*pflags = iflags & SC_ALGORITHM_RSA_HASHES;
3143c4
+
3143c4
 	} else {
3143c4
 		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "unsupported algorithm");
3143c4
 	}
3143c4
diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c
3143c4
index 6ee4fa3c7..3e7e03b12 100644
3143c4
--- a/src/libopensc/pkcs15-sec.c
3143c4
+++ b/src/libopensc/pkcs15-sec.c
3143c4
@@ -329,7 +329,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
3143c4
 
3143c4
 	switch (obj->type) {
3143c4
 		case SC_PKCS15_TYPE_PRKEY_RSA:
3143c4
-			modlen = prkey->modulus_length / 8;
3143c4
+			modlen = (prkey->modulus_length + 7) / 8;
3143c4
 			break;
3143c4
 		case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
3143c4
 			modlen = (prkey->modulus_length + 7) / 8 * 2;
3143c4
@@ -377,7 +377,8 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
3143c4
 		if (modlen > tmplen)
3143c4
 			LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!");
3143c4
 
3143c4
-		r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, modlen);
3143c4
+		/* XXX Assuming RSA key here */
3143c4
+		r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, prkey->modulus_length);
3143c4
 
3143c4
 		/* no padding needed - already done */
3143c4
 		flags &= ~SC_ALGORITHM_RSA_PADS;
3143c4
@@ -391,10 +392,15 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
3143c4
 	}
3143c4
 
3143c4
 
3143c4
-	/* If the card doesn't support the requested algorithm, see if we
3143c4
-	 * can strip the input so a more restrictive algo can be used */
3143c4
+	/* If the card doesn't support the requested algorithm, we normally add the
3143c4
+	 * padding here in software and ask the card to do a raw signature.  There's
3143c4
+	 * one exception to that, where we might be able to get the signature to
3143c4
+	 * succeed by stripping padding if the card only offers higher-level
3143c4
+	 * signature operations.  The only thing we can strip is the DigestInfo
3143c4
+	 * block from PKCS1 padding. */
3143c4
 	if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
3143c4
-			!(alg_info->flags & (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE))) {
3143c4
+	    !(alg_info->flags & SC_ALGORITHM_RSA_RAW) &&
3143c4
+	    !(alg_info->flags & (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE))) {
3143c4
 		unsigned int algo;
3143c4
 		size_t tmplen = sizeof(buf);
3143c4
 
3143c4
@@ -420,19 +426,16 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
3143c4
 
3143c4
 	/* add the padding bytes (if necessary) */
3143c4
 	if (pad_flags != 0) {
3143c4
-		if (flags & SC_ALGORITHM_RSA_PAD_PSS) {
3143c4
-			// TODO PSS padding
3143c4
-		} else {
3143c4
-			size_t tmplen = sizeof(buf);
3143c4
-
3143c4
-			r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen, modlen);
3143c4
-			SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Unable to add padding");
3143c4
+		size_t tmplen = sizeof(buf);
3143c4
 
3143c4
-			inlen = tmplen;
3143c4
-		}
3143c4
+		/* XXX Assuming RSA key here */
3143c4
+		r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen,
3143c4
+		    prkey->modulus_length);
3143c4
+		SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Unable to add padding");
3143c4
+		inlen = tmplen;
3143c4
 	}
3143c4
 	else if ( senv.algorithm == SC_ALGORITHM_RSA &&
3143c4
-			(flags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) {
3143c4
+	          (flags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) {
3143c4
 		/* Add zero-padding if input is shorter than the modulus */
3143c4
 		if (inlen < modlen) {
3143c4
 			if (modlen > sizeof(buf))
3143c4
diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
3143c4
index 80f9ce89f..a75d239f4 100644
3143c4
--- a/src/pkcs11/framework-pkcs15.c
3143c4
+++ b/src/pkcs11/framework-pkcs15.c
3143c4
@@ -3478,7 +3478,8 @@ struct sc_pkcs11_object_ops pkcs15_cert_ops = {
3143c4
 	NULL,	/* unwrap_key */
3143c4
 	NULL,	/* decrypt */
3143c4
 	NULL,	/* derive */
3143c4
-	NULL	/* can_do */
3143c4
+	NULL,	/* can_do */
3143c4
+	NULL	/* init_params */
3143c4
 };
3143c4
 
3143c4
 /*
3143c4
@@ -3703,53 +3704,44 @@ static CK_RV
3143c4
 pkcs15_prkey_check_pss_param(CK_MECHANISM_PTR pMechanism, CK_ULONG hlen)
3143c4
 {
3143c4
 	CK_RSA_PKCS_PSS_PARAMS *pss_param;
3143c4
-
3143c4
-	if (pMechanism->pParameter == NULL)
3143c4
-		return CKR_OK;				// Support applications that don't provide CK_RSA_PKCS_PSS_PARAMS
3143c4
-
3143c4
-	if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
3143c4
-		return CKR_MECHANISM_PARAM_INVALID;
3143c4
+	int i;
3143c4
+	const unsigned int hash_lens[5] = { 160, 256, 385, 512, 224 };
3143c4
+	const unsigned int hashes[5] = { CKM_SHA_1, CKM_SHA256,
3143c4
+		CKM_SHA384, CKM_SHA512, CKM_SHA224 };
3143c4
 
3143c4
 	pss_param = (CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
3143c4
 
3143c4
-	// Hash parameter must match mechanisms or length of data supplied for CKM_RSA_PKCS_PSS
3143c4
-	switch(pss_param->hashAlg) {
3143c4
-	case CKM_SHA_1:
3143c4
-		if (hlen != 20)
3143c4
-			return CKR_MECHANISM_PARAM_INVALID;
3143c4
-		break;
3143c4
-	case CKM_SHA256:
3143c4
-		if (hlen != 32)
3143c4
+	// Hash parameter must match length of data supplied for CKM_RSA_PKCS_PSS
3143c4
+	for (i = 0; i < 5; i++) {
3143c4
+		if (pss_param->hashAlg == hashes[i]
3143c4
+		    && hlen != hash_lens[i]/8)
3143c4
 			return CKR_MECHANISM_PARAM_INVALID;
3143c4
-		break;
3143c4
-	default:
3143c4
-		return CKR_MECHANISM_PARAM_INVALID;
3143c4
 	}
3143c4
+	/* other aspects of pss params were already verified during SignInit */
3143c4
 
3143c4
-	// SmartCards typically only support MGFs based on the same hash as the
3143c4
-	// message digest
3143c4
-	switch(pss_param->mgf) {
3143c4
-	case CKG_MGF1_SHA1:
3143c4
-		if (hlen != 20)
3143c4
-			return CKR_MECHANISM_PARAM_INVALID;
3143c4
+	return CKR_OK;
3143c4
+}
3143c4
+
3143c4
+static int mgf2flags(CK_RSA_PKCS_MGF_TYPE mgf)
3143c4
+{
3143c4
+	switch (mgf) {
3143c4
+	case CKG_MGF1_SHA224:
3143c4
+		return SC_ALGORITHM_MGF1_SHA224;
3143c4
 		break;
3143c4
 	case CKG_MGF1_SHA256:
3143c4
-		if (hlen != 32)
3143c4
-			return CKR_MECHANISM_PARAM_INVALID;
3143c4
-		break;
3143c4
+		return SC_ALGORITHM_MGF1_SHA256;
3143c4
+	case CKG_MGF1_SHA384:
3143c4
+		return SC_ALGORITHM_MGF1_SHA384;
3143c4
+	case CKG_MGF1_SHA512:
3143c4
+		return SC_ALGORITHM_MGF1_SHA512;
3143c4
+	case CKG_MGF1_SHA1:
3143c4
+		return SC_ALGORITHM_MGF1_SHA1;
3143c4
 	default:
3143c4
-		return CKR_MECHANISM_PARAM_INVALID;
3143c4
+		return -1;
3143c4
 	}
3143c4
-
3143c4
-	// SmartCards typically support only a salt length equal to the hash length
3143c4
-	if (pss_param->sLen != hlen)
3143c4
-		return CKR_MECHANISM_PARAM_INVALID;
3143c4
-
3143c4
-	return CKR_OK;
3143c4
 }
3143c4
 
3143c4
 
3143c4
-
3143c4
 static CK_RV
3143c4
 pkcs15_prkey_sign(struct sc_pkcs11_session *session, void *obj,
3143c4
 			CK_MECHANISM_PTR pMechanism, CK_BYTE_PTR pData,
3143c4
@@ -3798,35 +3790,74 @@ pkcs15_prkey_sign(struct sc_pkcs11_session *session, void *obj,
3143c4
 	case CKM_SHA512_RSA_PKCS:
3143c4
 		flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA512;
3143c4
 		break;
3143c4
+	case CKM_RIPEMD160_RSA_PKCS:
3143c4
+		flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_RIPEMD160;
3143c4
+		break;
3143c4
+	case CKM_RSA_X_509:
3143c4
+		flags = SC_ALGORITHM_RSA_RAW;
3143c4
+		break;
3143c4
 	case CKM_RSA_PKCS_PSS:
3143c4
-		rv = pkcs15_prkey_check_pss_param(pMechanism, (int)ulDataLen);
3143c4
+		flags = SC_ALGORITHM_RSA_PAD_PSS;
3143c4
+		/* The hash was done ouside of the module */
3143c4
+		flags |= SC_ALGORITHM_RSA_HASH_NONE;
3143c4
+		/* Omited parameter can use MGF1-SHA1 ? */
3143c4
+		if (pMechanism->pParameter == NULL) {
3143c4
+			flags |= SC_ALGORITHM_MGF1_SHA1;
3143c4
+			if (ulDataLen != SHA_DIGEST_LENGTH)
3143c4
+				return CKR_MECHANISM_PARAM_INVALID;
3143c4
+			break;
3143c4
+		}
3143c4
 
3143c4
-		if (rv != CKR_OK)
3143c4
+		/* Check the data length matches the selected hash */
3143c4
+		rv = pkcs15_prkey_check_pss_param(pMechanism, (int)ulDataLen);
3143c4
+		if (rv != CKR_OK) {
3143c4
+			sc_log(context, "Invalid data lenght for the selected "
3143c4
+			    "PSS parameters");
3143c4
 			return rv;
3143c4
+		}
3143c4
 
3143c4
-		flags = SC_ALGORITHM_RSA_PAD_PSS | SC_ALGORITHM_RSA_HASH_NONE;
3143c4
-		break;
3143c4
-	case CKM_SHA1_RSA_PKCS_PSS:
3143c4
-		rv = pkcs15_prkey_check_pss_param(pMechanism, 20);
3143c4
-
3143c4
-		if (rv != CKR_OK)
3143c4
-			return rv;
3143c4
+		/* The MGF parameter was already verified in SignInit() */
3143c4
+		flags |=  mgf2flags(((CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)->mgf);
3143c4
 
3143c4
-		flags = SC_ALGORITHM_RSA_PAD_PSS | SC_ALGORITHM_RSA_HASH_SHA1;
3143c4
+		/* Assuming salt is the size of hash */
3143c4
 		break;
3143c4
+	case CKM_SHA1_RSA_PKCS_PSS:
3143c4
+	case CKM_SHA224_RSA_PKCS_PSS:
3143c4
 	case CKM_SHA256_RSA_PKCS_PSS:
3143c4
-		rv = pkcs15_prkey_check_pss_param(pMechanism, 32);
3143c4
+	case CKM_SHA384_RSA_PKCS_PSS:
3143c4
+	case CKM_SHA512_RSA_PKCS_PSS:
3143c4
+		flags = SC_ALGORITHM_RSA_PAD_PSS;
3143c4
+		/* Omited parameter can use MGF1-SHA1 and SHA1 hash ? */
3143c4
+		if (pMechanism->pParameter == NULL) {
3143c4
+			flags |= SC_ALGORITHM_RSA_HASH_SHA1;
3143c4
+			flags |= SC_ALGORITHM_MGF1_SHA1;
3143c4
+			break;
3143c4
+		}
3143c4
 
3143c4
-		if (rv != CKR_OK)
3143c4
-			return rv;
3143c4
+		switch (((CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)->hashAlg) {
3143c4
+		case CKM_SHA_1:
3143c4
+			flags |= SC_ALGORITHM_RSA_HASH_SHA1;
3143c4
+			break;
3143c4
+		case CKM_SHA224:
3143c4
+			flags |= SC_ALGORITHM_RSA_HASH_SHA224;
3143c4
+			break;
3143c4
+		case CKM_SHA256:
3143c4
+			flags |= SC_ALGORITHM_RSA_HASH_SHA256;
3143c4
+			break;
3143c4
+		case CKM_SHA384:
3143c4
+			flags |= SC_ALGORITHM_RSA_HASH_SHA384;
3143c4
+			break;
3143c4
+		case CKM_SHA512:
3143c4
+			flags |= SC_ALGORITHM_RSA_HASH_SHA512;
3143c4
+			break;
3143c4
+		default:
3143c4
+			return CKR_MECHANISM_PARAM_INVALID;
3143c4
+		}
3143c4
 
3143c4
-		flags = SC_ALGORITHM_RSA_PAD_PSS | SC_ALGORITHM_RSA_HASH_SHA256;
3143c4
-		break;
3143c4
-	case CKM_RIPEMD160_RSA_PKCS:
3143c4
-		flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_RIPEMD160;
3143c4
-		break;
3143c4
-	case CKM_RSA_X_509:
3143c4
-		flags = SC_ALGORITHM_RSA_RAW;
3143c4
+		/* The MGF parameter was already verified in SignInit() */
3143c4
+		flags |= mgf2flags(((CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)->mgf);
3143c4
+
3143c4
+		/* Assuming salt is the size of hash */
3143c4
 		break;
3143c4
 	case CKM_GOSTR3410:
3143c4
 		flags = SC_ALGORITHM_GOSTR3410_HASH_NONE;
3143c4
@@ -4074,6 +4105,76 @@ pkcs15_prkey_can_do(struct sc_pkcs11_session *session, void *obj,
3143c4
 }
3143c4
 
3143c4
 
3143c4
+static CK_RV
3143c4
+pkcs15_prkey_init_params(struct sc_pkcs11_session *session,
3143c4
+			CK_MECHANISM_PTR pMechanism)
3143c4
+{
3143c4
+	const CK_RSA_PKCS_PSS_PARAMS *pss_params;
3143c4
+	unsigned int expected_hash = 0, i;
3143c4
+	unsigned int expected_salt_len = 0;
3143c4
+	const unsigned int salt_lens[5] = { 160, 256, 384, 512, 224 };
3143c4
+	const unsigned int hashes[5] = { CKM_SHA_1, CKM_SHA256,
3143c4
+		CKM_SHA384, CKM_SHA512, CKM_SHA224 };
3143c4
+
3143c4
+	switch (pMechanism->mechanism) {
3143c4
+	case CKM_RSA_PKCS_PSS:
3143c4
+	case CKM_SHA1_RSA_PKCS_PSS:
3143c4
+	case CKM_SHA224_RSA_PKCS_PSS:
3143c4
+	case CKM_SHA256_RSA_PKCS_PSS:
3143c4
+	case CKM_SHA384_RSA_PKCS_PSS:
3143c4
+	case CKM_SHA512_RSA_PKCS_PSS:
3143c4
+		if (!pMechanism->pParameter ||
3143c4
+		    pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
3143c4
+			return CKR_MECHANISM_PARAM_INVALID;
3143c4
+
3143c4
+		pss_params = (CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter;
3143c4
+		if (pss_params->mgf < CKG_MGF1_SHA1 || pss_params->mgf > CKG_MGF1_SHA224)
3143c4
+			return CKR_MECHANISM_PARAM_INVALID;
3143c4
+
3143c4
+		/* The hashAlg field can have any value for CKM_RSA_PKCS_PSS and must be
3143c4
+		 * used again in the PSS padding; for the other mechanisms it strictly
3143c4
+		 * must match the padding declared in the mechanism.
3143c4
+		 */
3143c4
+		if (pMechanism->mechanism == CKM_SHA1_RSA_PKCS_PSS) {
3143c4
+			expected_hash = CKM_SHA_1;
3143c4
+			expected_salt_len = 160;
3143c4
+		} else if (pMechanism->mechanism == CKM_SHA224_RSA_PKCS_PSS) {
3143c4
+			expected_hash = CKM_SHA224;
3143c4
+			expected_salt_len = 224;
3143c4
+		} else if (pMechanism->mechanism == CKM_SHA256_RSA_PKCS_PSS) {
3143c4
+			expected_hash = CKM_SHA256;
3143c4
+			expected_salt_len = 256;
3143c4
+		} else if (pMechanism->mechanism == CKM_SHA384_RSA_PKCS_PSS) {
3143c4
+			expected_hash = CKM_SHA384;
3143c4
+			expected_salt_len = 384;
3143c4
+		} else if (pMechanism->mechanism == CKM_SHA512_RSA_PKCS_PSS) {
3143c4
+			expected_hash = CKM_SHA512;
3143c4
+			expected_salt_len = 512;
3143c4
+		} else if (pMechanism->mechanism == CKM_RSA_PKCS_PSS) {
3143c4
+			for (i = 0; i < 5; ++i) {
3143c4
+			        if (hashes[i] == pss_params->hashAlg) {
3143c4
+			                expected_hash = hashes[i];
3143c4
+			                expected_salt_len = salt_lens[i];
3143c4
+				}
3143c4
+			}
3143c4
+		}
3143c4
+
3143c4
+		if (expected_hash != pss_params->hashAlg)
3143c4
+			return CKR_MECHANISM_PARAM_INVALID;
3143c4
+
3143c4
+		/* We're strict, and only do PSS signatures with a salt length that
3143c4
+		 * matches the digest length (any shorter is rubbish, any longer
3143c4
+		 * is useless). */
3143c4
+		if (pss_params->sLen != expected_salt_len / 8)
3143c4
+			return CKR_MECHANISM_PARAM_INVALID;
3143c4
+
3143c4
+		/* TODO support different salt lengths */
3143c4
+		break;
3143c4
+	}
3143c4
+	return CKR_OK;
3143c4
+}
3143c4
+
3143c4
+
3143c4
 struct sc_pkcs11_object_ops pkcs15_prkey_ops = {
3143c4
 	pkcs15_prkey_release,
3143c4
 	pkcs15_prkey_set_attribute,
3143c4
@@ -4084,8 +4185,9 @@ struct sc_pkcs11_object_ops pkcs15_prkey_ops = {
3143c4
 	pkcs15_prkey_sign,
3143c4
 	NULL,	/* unwrap */
3143c4
 	pkcs15_prkey_decrypt,
3143c4
-        pkcs15_prkey_derive,
3143c4
-        pkcs15_prkey_can_do
3143c4
+	pkcs15_prkey_derive,
3143c4
+	pkcs15_prkey_can_do,
3143c4
+	pkcs15_prkey_init_params,
3143c4
 };
3143c4
 
3143c4
 /*
3143c4
@@ -4322,7 +4424,8 @@ struct sc_pkcs11_object_ops pkcs15_pubkey_ops = {
3143c4
 	NULL,	/* unwrap_key */
3143c4
 	NULL,	/* decrypt */
3143c4
 	NULL,	/* derive */
3143c4
-	NULL	/* can_do */
3143c4
+	NULL,	/* can_do */
3143c4
+	NULL	/* init_params */
3143c4
 };
3143c4
 
3143c4
 
3143c4
@@ -4500,7 +4603,8 @@ struct sc_pkcs11_object_ops pkcs15_dobj_ops = {
3143c4
 	NULL,	/* unwrap_key */
3143c4
 	NULL,	/* decrypt */
3143c4
 	NULL,	/* derive */
3143c4
-	NULL	/* can_do */
3143c4
+	NULL,	/* can_do */
3143c4
+	NULL	/* init_params */
3143c4
 };
3143c4
 
3143c4
 
3143c4
@@ -4629,7 +4733,8 @@ struct sc_pkcs11_object_ops pkcs15_skey_ops = {
3143c4
 	NULL,	/* unwrap_key */
3143c4
 	NULL,	/* decrypt */
3143c4
 	NULL,	/* derive */
3143c4
-	NULL	/* can_do */
3143c4
+	NULL,	/* can_do */
3143c4
+	NULL	/* init_params */
3143c4
 };
3143c4
 
3143c4
 /*
3143c4
@@ -5040,6 +5145,17 @@ register_mechanisms(struct sc_pkcs11_card *p11card)
3143c4
 		/* We support PKCS1 padding in software */
3143c4
 		/* either the card supports it or OpenSC does */
3143c4
 		rsa_flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
3143c4
+#ifdef ENABLE_OPENSSL
3143c4
+		rsa_flags |= SC_ALGORITHM_RSA_PAD_PSS;
3143c4
+#endif
3143c4
+	}
3143c4
+
3143c4
+	if (rsa_flags & SC_ALGORITHM_RSA_PAD_ISO9796) {
3143c4
+		/* Supported in hardware only, if the card driver declares it. */
3143c4
+		mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_9796, &mech_info, CKK_RSA, NULL, NULL);
3143c4
+		rc = sc_pkcs11_register_mechanism(p11card, mt);
3143c4
+		if (rc != CKR_OK)
3143c4
+			return rc;
3143c4
 	}
3143c4
 
3143c4
 #ifdef ENABLE_OPENSSL
3143c4
@@ -5098,23 +5214,40 @@ register_mechanisms(struct sc_pkcs11_card *p11card)
3143c4
 #endif /* ENABLE_OPENSSL */
3143c4
 	}
3143c4
 
3143c4
-	/* TODO support other padding mechanisms */
3143c4
-
3143c4
 	if (rsa_flags & SC_ALGORITHM_RSA_PAD_PSS) {
3143c4
-		mech_info.flags &= ~(CKF_DECRYPT|CKF_VERIFY);
3143c4
-
3143c4
+		mech_info.flags &= ~(CKF_DECRYPT|CKF_ENCRYPT);
3143c4
 		mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_PSS, &mech_info, CKK_RSA, NULL, NULL);
3143c4
 		rc = sc_pkcs11_register_mechanism(p11card, mt);
3143c4
 		if (rc != CKR_OK)
3143c4
 			return rc;
3143c4
 
3143c4
 		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA1) {
3143c4
-			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA1_RSA_PKCS_PSS, CKM_SHA_1, mt);
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+			    CKM_SHA1_RSA_PKCS_PSS, CKM_SHA_1, mt);
3143c4
+			if (rc != CKR_OK)
3143c4
+				return rc;
3143c4
+		}
3143c4
+		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA224) {
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+			    CKM_SHA224_RSA_PKCS_PSS, CKM_SHA224, mt);
3143c4
 			if (rc != CKR_OK)
3143c4
 				return rc;
3143c4
 		}
3143c4
 		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA256) {
3143c4
-			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA256_RSA_PKCS_PSS, CKM_SHA256, mt);
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+			    CKM_SHA256_RSA_PKCS_PSS, CKM_SHA256, mt);
3143c4
+			if (rc != CKR_OK)
3143c4
+				return rc;
3143c4
+		}
3143c4
+		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA384) {
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+			    CKM_SHA384_RSA_PKCS_PSS, CKM_SHA384, mt);
3143c4
+			if (rc != CKR_OK)
3143c4
+				return rc;
3143c4
+		}
3143c4
+		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA512) {
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+			    CKM_SHA512_RSA_PKCS_PSS, CKM_SHA512, mt);
3143c4
 			if (rc != CKR_OK)
3143c4
 				return rc;
3143c4
 		}
3143c4
diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c
3143c4
index 5f006c839..d4ce7fef5 100644
3143c4
--- a/src/pkcs11/mechanism.c
3143c4
+++ b/src/pkcs11/mechanism.c
3143c4
@@ -262,11 +262,20 @@ sc_pkcs11_sign_init(struct sc_pkcs11_session *session, CK_MECHANISM_PTR pMechani
3143c4
 	if (mt->key_type != key_type)
3143c4
 		LOG_FUNC_RETURN(context, CKR_KEY_TYPE_INCONSISTENT);
3143c4
 
3143c4
+	if (pMechanism->pParameter &&
3143c4
+	    pMechanism->ulParameterLen > sizeof(operation->mechanism_params))
3143c4
+		LOG_FUNC_RETURN(context, CKR_ARGUMENTS_BAD);
3143c4
+
3143c4
 	rv = session_start_operation(session, SC_PKCS11_OPERATION_SIGN, mt, &operation);
3143c4
 	if (rv != CKR_OK)
3143c4
 		LOG_FUNC_RETURN(context, rv);
3143c4
 
3143c4
 	memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
3143c4
+	if (pMechanism->pParameter) {
3143c4
+		memcpy(&operation->mechanism_params, pMechanism->pParameter,
3143c4
+		       pMechanism->ulParameterLen);
3143c4
+		operation->mechanism.pParameter = &operation->mechanism_params;
3143c4
+	}
3143c4
 	rv = mt->sign_init(operation, key);
3143c4
 	if (rv != CKR_OK)
3143c4
 		session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
3143c4
@@ -387,6 +396,16 @@ sc_pkcs11_signature_init(sc_pkcs11_operation_t *operation,
3143c4
 		}
3143c4
 	}
3143c4
 
3143c4
+	/* Validate the mechanism parameters */
3143c4
+	if (key->ops->init_params) {
3143c4
+		rv = key->ops->init_params(operation->session, &operation->mechanism);
3143c4
+		if (rv != CKR_OK) {
3143c4
+			/* Probably bad arguments */
3143c4
+			free(data);
3143c4
+			LOG_FUNC_RETURN(context, rv);
3143c4
+		}
3143c4
+	}
3143c4
+
3143c4
 	/* If this is a signature with hash operation,
3143c4
 	 * and card cannot perform itself signature with hash operation,
3143c4
 	 * set up the hash operation */
3143c4
@@ -636,6 +655,16 @@ sc_pkcs11_verify_init(sc_pkcs11_operation_t *operation,
3143c4
 		}
3143c4
 	}
3143c4
 
3143c4
+	/* Validate the mechanism parameters */
3143c4
+	if (key->ops->init_params) {
3143c4
+		rv = key->ops->init_params(operation->session, &operation->mechanism);
3143c4
+		if (rv != CKR_OK) {
3143c4
+			/* Probably bad arguments */
3143c4
+			free(data);
3143c4
+			LOG_FUNC_RETURN(context, rv);
3143c4
+		}
3143c4
+	}
3143c4
+
3143c4
 	/* If this is a verify with hash operation, set up the
3143c4
 	 * hash operation */
3143c4
 	info = (struct hash_signature_info *) operation->type->mech_data;
3143c4
@@ -729,7 +758,7 @@ sc_pkcs11_verify_final(sc_pkcs11_operation_t *operation,
3143c4
 
3143c4
 	rv = sc_pkcs11_verify_data(pubkey_value, attr.ulValueLen,
3143c4
 		params, sizeof(params),
3143c4
-		operation->mechanism.mechanism, data->md,
3143c4
+		&operation->mechanism, data->md,
3143c4
 		data->buffer, data->buffer_len, pSignature, ulSignatureLen);
3143c4
 
3143c4
 done:
3143c4
diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c
3143c4
index 59de1210d..e8b246145 100644
3143c4
--- a/src/pkcs11/openssl.c
3143c4
+++ b/src/pkcs11/openssl.c
3143c4
@@ -68,6 +68,23 @@ static sc_pkcs11_mechanism_type_t openssl_sha1_mech = {
3143c4
 	NULL,			/* free_mech_data */
3143c4
 };
3143c4
 
3143c4
+static sc_pkcs11_mechanism_type_t openssl_sha224_mech = {
3143c4
+	CKM_SHA224,
3143c4
+	{ 0, 0, CKF_DIGEST },
3143c4
+	0,
3143c4
+	sizeof(struct sc_pkcs11_operation),
3143c4
+	sc_pkcs11_openssl_md_release,
3143c4
+	sc_pkcs11_openssl_md_init,
3143c4
+	sc_pkcs11_openssl_md_update,
3143c4
+	sc_pkcs11_openssl_md_final,
3143c4
+	NULL, NULL, NULL, NULL,	/* sign_* */
3143c4
+	NULL, NULL, NULL,	/* verif_* */
3143c4
+	NULL, NULL,		/* decrypt_* */
3143c4
+	NULL,			/* derive */
3143c4
+	NULL,			/* mech_data */
3143c4
+	NULL,			/* free_mech_data */
3143c4
+};
3143c4
+
3143c4
 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
3143c4
 static sc_pkcs11_mechanism_type_t openssl_sha256_mech = {
3143c4
 	CKM_SHA256,
3143c4
@@ -231,6 +248,8 @@ sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *p11card)
3143c4
 
3143c4
 	openssl_sha1_mech.mech_data = EVP_sha1();
3143c4
 	sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_sha1_mech, sizeof openssl_sha1_mech));
3143c4
+	openssl_sha224_mech.mech_data = EVP_sha224();
3143c4
+	sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_sha224_mech, sizeof openssl_sha224_mech));
3143c4
 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
3143c4
 	openssl_sha256_mech.mech_data = EVP_sha256();
3143c4
 	sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_sha256_mech, sizeof openssl_sha256_mech));
3143c4
@@ -396,7 +415,7 @@ static CK_RV gostr3410_verify_data(const unsigned char *pubkey, int pubkey_len,
3143c4
  */
3143c4
 CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
3143c4
 			const unsigned char *pubkey_params, int pubkey_params_len,
3143c4
-			CK_MECHANISM_TYPE mech, sc_pkcs11_operation_t *md,
3143c4
+			CK_MECHANISM_PTR mech, sc_pkcs11_operation_t *md,
3143c4
 			unsigned char *data, int data_len,
3143c4
 			unsigned char *signat, int signat_len)
3143c4
 {
3143c4
@@ -405,7 +424,7 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
3143c4
 	EVP_PKEY *pkey = NULL;
3143c4
 	const unsigned char *pubkey_tmp = NULL;
3143c4
 
3143c4
-	if (mech == CKM_GOSTR3410)
3143c4
+	if (mech->mechanism == CKM_GOSTR3410)
3143c4
 	{
3143c4
 #if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC)
3143c4
 		return gostr3410_verify_data(pubkey, pubkey_len,
3143c4
@@ -429,37 +448,53 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
3143c4
 	if (pkey == NULL)
3143c4
 		return CKR_GENERAL_ERROR;
3143c4
 
3143c4
-	if (md != NULL) {
3143c4
+	if (md != NULL && (mech->mechanism == CKM_SHA1_RSA_PKCS
3143c4
+		|| mech->mechanism == CKM_SHA224_RSA_PKCS
3143c4
+		|| mech->mechanism == CKM_SHA256_RSA_PKCS
3143c4
+		|| mech->mechanism == CKM_SHA384_RSA_PKCS
3143c4
+		|| mech->mechanism == CKM_SHA512_RSA_PKCS)) {
3143c4
 		EVP_MD_CTX *md_ctx = DIGEST_CTX(md);
3143c4
 
3143c4
+		/* This does not really use the data argument, but the data
3143c4
+		 * are already collected in the md_ctx
3143c4
+		 */
3143c4
+		sc_log(context, "Trying to verify using EVP");
3143c4
 		res = EVP_VerifyFinal(md_ctx, signat, signat_len, pkey);
3143c4
 		EVP_PKEY_free(pkey);
3143c4
 		if (res == 1)
3143c4
 			return CKR_OK;
3143c4
-		else if (res == 0)
3143c4
+		else if (res == 0) {
3143c4
+			sc_log(context, "EVP_VerifyFinal(): Signature invalid");
3143c4
 			return CKR_SIGNATURE_INVALID;
3143c4
-		else {
3143c4
+		} else {
3143c4
 			sc_log(context, "EVP_VerifyFinal() returned %d\n", res);
3143c4
 			return CKR_GENERAL_ERROR;
3143c4
 		}
3143c4
-	}
3143c4
-	else {
3143c4
+	} else {
3143c4
 		RSA *rsa;
3143c4
 		unsigned char *rsa_out = NULL, pad;
3143c4
 		int rsa_outlen = 0;
3143c4
 
3143c4
-		switch(mech) {
3143c4
+		sc_log(context, "Trying to verify using low-level API");
3143c4
+		switch (mech->mechanism) {
3143c4
 		case CKM_RSA_PKCS:
3143c4
 		 	pad = RSA_PKCS1_PADDING;
3143c4
 		 	break;
3143c4
-		 case CKM_RSA_X_509:
3143c4
-		 	pad = RSA_NO_PADDING;
3143c4
-		 	break;
3143c4
-		/* TODO support more then RSA */
3143c4
-		 default:
3143c4
+		case CKM_RSA_X_509:
3143c4
+			pad = RSA_NO_PADDING;
3143c4
+			break;
3143c4
+		case CKM_RSA_PKCS_PSS:
3143c4
+		case CKM_SHA1_RSA_PKCS_PSS:
3143c4
+		case CKM_SHA224_RSA_PKCS_PSS:
3143c4
+		case CKM_SHA256_RSA_PKCS_PSS:
3143c4
+		case CKM_SHA384_RSA_PKCS_PSS:
3143c4
+		case CKM_SHA512_RSA_PKCS_PSS:
3143c4
+			pad = RSA_NO_PADDING;
3143c4
+			break;
3143c4
+		default:
3143c4
 			EVP_PKEY_free(pkey);
3143c4
-		 	return CKR_ARGUMENTS_BAD;
3143c4
-		 }
3143c4
+			return CKR_ARGUMENTS_BAD;
3143c4
+		}
3143c4
 
3143c4
 		rsa = EVP_PKEY_get1_RSA(pkey);
3143c4
 		EVP_PKEY_free(pkey);
3143c4
@@ -473,13 +508,95 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
3143c4
 		}
3143c4
 
3143c4
 		rsa_outlen = RSA_public_decrypt(signat_len, signat, rsa_out, rsa, pad);
3143c4
-		RSA_free(rsa);
3143c4
-		if(rsa_outlen <= 0) {
3143c4
+		if (rsa_outlen <= 0) {
3143c4
 			free(rsa_out);
3143c4
 			sc_log(context, "RSA_public_decrypt() returned %d\n", rsa_outlen);
3143c4
 			return CKR_GENERAL_ERROR;
3143c4
 		}
3143c4
 
3143c4
+		/* For PSS mechanisms we can not simply compare the "decrypted"
3143c4
+		 * data -- we need to verify the PSS padding is valid
3143c4
+		 */
3143c4
+		if (mech->mechanism == CKM_RSA_PKCS_PSS ||
3143c4
+		    mech->mechanism == CKM_SHA1_RSA_PKCS_PSS ||
3143c4
+		    mech->mechanism == CKM_SHA224_RSA_PKCS_PSS ||
3143c4
+		    mech->mechanism == CKM_SHA256_RSA_PKCS_PSS ||
3143c4
+		    mech->mechanism == CKM_SHA384_RSA_PKCS_PSS ||
3143c4
+		    mech->mechanism == CKM_SHA512_RSA_PKCS_PSS) {
3143c4
+			CK_RSA_PKCS_PSS_PARAMS* param = NULL;
3143c4
+			const EVP_MD *mgf_md, *pss_md;
3143c4
+			unsigned char digest[EVP_MAX_MD_SIZE];
3143c4
+
3143c4
+			if (mech->pParameter == NULL) {
3143c4
+				sc_log(context, "PSS mechanism requires parameter");
3143c4
+				return CKR_MECHANISM_PARAM_INVALID;
3143c4
+			}
3143c4
+
3143c4
+			param = (CK_RSA_PKCS_PSS_PARAMS*)mech->pParameter;
3143c4
+			switch (param->mgf) {
3143c4
+			case CKG_MGF1_SHA1:
3143c4
+				mgf_md = EVP_sha1();
3143c4
+				break;
3143c4
+			case CKG_MGF1_SHA224:
3143c4
+				mgf_md = EVP_sha224();
3143c4
+				break;
3143c4
+			case CKG_MGF1_SHA256:
3143c4
+				mgf_md = EVP_sha256();
3143c4
+				break;
3143c4
+			case CKG_MGF1_SHA384:
3143c4
+				mgf_md = EVP_sha384();
3143c4
+				break;
3143c4
+			case CKG_MGF1_SHA512:
3143c4
+				mgf_md = EVP_sha512();
3143c4
+				break;
3143c4
+			default:
3143c4
+				return CKR_MECHANISM_PARAM_INVALID;
3143c4
+			}
3143c4
+
3143c4
+			switch (param->hashAlg) {
3143c4
+			case CKM_SHA_1:
3143c4
+				pss_md = EVP_sha1();
3143c4
+				break;
3143c4
+			case CKM_SHA224:
3143c4
+				pss_md = EVP_sha224();
3143c4
+				break;
3143c4
+			case CKM_SHA256:
3143c4
+				pss_md = EVP_sha256();
3143c4
+				break;
3143c4
+			case CKM_SHA384:
3143c4
+				pss_md = EVP_sha384();
3143c4
+				break;
3143c4
+			case CKM_SHA512:
3143c4
+				pss_md = EVP_sha512();
3143c4
+				break;
3143c4
+			default:
3143c4
+				return CKR_MECHANISM_PARAM_INVALID;
3143c4
+			}
3143c4
+
3143c4
+			/* for the mechanisms with hash algorithm, the data
3143c4
+			 * is already added to the hash buffer, so we need
3143c4
+			 * to finish the hash operation here
3143c4
+			 */
3143c4
+			if (mech->mechanism != CKM_RSA_PKCS_PSS) {
3143c4
+				EVP_MD_CTX *md_ctx = DIGEST_CTX(md);
3143c4
+				unsigned char *tmp = digest;
3143c4
+				unsigned int tmp_len;
3143c4
+
3143c4
+				EVP_DigestFinal(md_ctx, tmp, &tmp_len);
3143c4
+				data = tmp;
3143c4
+				data_len = tmp_len;
3143c4
+			}
3143c4
+			rv = CKR_SIGNATURE_INVALID;
3143c4
+			if (data_len == EVP_MD_size(pss_md) &&
3143c4
+			    RSA_verify_PKCS1_PSS_mgf1(rsa, data, pss_md, mgf_md,
3143c4
+			        rsa_out, EVP_MD_size(pss_md)/*sLen*/) == 1)
3143c4
+				rv = CKR_OK;
3143c4
+			RSA_free(rsa);
3143c4
+			sc_log(context, "Returning %lu", rv);
3143c4
+			return rv;
3143c4
+		}
3143c4
+		RSA_free(rsa);
3143c4
+
3143c4
 		if (rsa_outlen == data_len && memcmp(rsa_out, data, data_len) == 0)
3143c4
 			rv = CKR_OK;
3143c4
 		else
3143c4
diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h
3143c4
index 61a5050df..8219b961b 100644
3143c4
--- a/src/pkcs11/pkcs11.h
3143c4
+++ b/src/pkcs11/pkcs11.h
3143c4
@@ -480,8 +480,6 @@ struct ck_date
3143c4
 
3143c4
 typedef unsigned long ck_mechanism_type_t;
3143c4
 
3143c4
-typedef unsigned long int ck_rsa_pkcs_mgf_type_t;
3143c4
-
3143c4
 #define CKM_RSA_PKCS_KEY_PAIR_GEN	(0UL)
3143c4
 #define CKM_RSA_PKCS			(1UL)
3143c4
 #define CKM_RSA_9796			(2UL)
3143c4
@@ -764,6 +762,7 @@ typedef struct CK_ECDH1_DERIVE_PARAMS {
3143c4
 	unsigned char *  pPublicData;
3143c4
 } CK_ECDH1_DERIVE_PARAMS;
3143c4
 
3143c4
+typedef unsigned long ck_rsa_pkcs_mgf_type_t;
3143c4
 typedef unsigned long CK_RSA_PKCS_OAEP_SOURCE_TYPE;
3143c4
 
3143c4
 typedef struct CK_RSA_PKCS_OAEP_PARAMS {
3143c4
diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h
3143c4
index 843245882..f0115ed04 100644
3143c4
--- a/src/pkcs11/sc-pkcs11.h
3143c4
+++ b/src/pkcs11/sc-pkcs11.h
3143c4
@@ -119,6 +119,9 @@ struct sc_pkcs11_object_ops {
3143c4
 	/* Check compatibility of PKCS#15 object usage and an asked PKCS#11 mechanism. */
3143c4
 	CK_RV (*can_do)(struct sc_pkcs11_session *, void *, CK_MECHANISM_TYPE, unsigned int);
3143c4
 
3143c4
+	/* General validation of mechanism parameters (sign, encrypt, etc) */
3143c4
+	CK_RV (*init_params)(struct sc_pkcs11_session *, CK_MECHANISM_PTR);
3143c4
+
3143c4
 	/* Others to be added when implemented */
3143c4
 };
3143c4
 
3143c4
@@ -290,6 +293,10 @@ typedef struct sc_pkcs11_mechanism_type sc_pkcs11_mechanism_type_t;
3143c4
 struct sc_pkcs11_operation {
3143c4
 	sc_pkcs11_mechanism_type_t *type;
3143c4
 	CK_MECHANISM	  mechanism;
3143c4
+	union {
3143c4
+		CK_RSA_PKCS_PSS_PARAMS pss;
3143c4
+		CK_RSA_PKCS_OAEP_PARAMS oaep;
3143c4
+	} mechanism_params;
3143c4
 	struct sc_pkcs11_session *session;
3143c4
 	void *		  priv_data;
3143c4
 };
3143c4
@@ -434,7 +441,7 @@ CK_RV sc_pkcs11_register_sign_and_hash_mechanism(struct sc_pkcs11_card *,
3143c4
 #ifdef ENABLE_OPENSSL
3143c4
 CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
3143c4
 	const unsigned char *pubkey_params, int pubkey_params_len,
3143c4
-	CK_MECHANISM_TYPE mech, sc_pkcs11_operation_t *md,
3143c4
+	CK_MECHANISM_PTR mech, sc_pkcs11_operation_t *md,
3143c4
 	unsigned char *inp, int inp_len,
3143c4
 	unsigned char *signat, int signat_len);
3143c4
 #endif
3143c4
3143c4
From 2f36612d116ed1fb3ed305a5657871fa12f75011 Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Sun, 22 Jul 2018 16:29:19 +0200
3143c4
Subject: [PATCH 4/5] pkcs11-tool: Support for signature verification
3143c4
3143c4
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
3143c4
---
3143c4
 doc/tools/pkcs11-tool.1.xml |  14 ++
3143c4
 src/tools/pkcs11-tool.c     | 273 +++++++++++++++++++++++++++---------
3143c4
 2 files changed, 222 insertions(+), 65 deletions(-)
3143c4
3143c4
diff --git a/doc/tools/pkcs11-tool.1.xml b/doc/tools/pkcs11-tool.1.xml
3143c4
index c609ec0e2..fd823c06e 100644
3143c4
--- a/doc/tools/pkcs11-tool.1.xml
3143c4
+++ b/doc/tools/pkcs11-tool.1.xml
3143c4
@@ -481,6 +481,13 @@
3143c4
 					non-zero number.</para></listitem>
3143c4
 				</varlistentry>
3143c4
 
3143c4
+				<varlistentry>
3143c4
+					<term>
3143c4
+						<option>--verify</option>,
3143c4
+					</term>
3143c4
+					<listitem><para>Verify signature of some data.</para></listitem>
3143c4
+				</varlistentry>
3143c4
+
3143c4
 				<varlistentry>
3143c4
 					<term>
3143c4
 						<option>--read-object</option>,
3143c4
@@ -530,6 +537,13 @@
3143c4
 					<option>--type</option> cert/privkey/pubkey).</para></listitem>
3143c4
 				</varlistentry>
3143c4
 
3143c4
+				<varlistentry>
3143c4
+					<term>
3143c4
+						<option>--signature-file</option> <replaceable>filename</replaceable>
3143c4
+					</term>
3143c4
+					<listitem><para>The path to the signature file for signature verification</para></listitem>
3143c4
+				</varlistentry>
3143c4
+
3143c4
 				<varlistentry>
3143c4
 					<term>
3143c4
 						<option>--signature-format</option> <replaceable>format</replaceable>
3143c4
diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c
3143c4
index 64525f6ad..e3c52e2f8 100644
3143c4
--- a/src/tools/pkcs11-tool.c
3143c4
+++ b/src/tools/pkcs11-tool.c
3143c4
@@ -150,6 +150,8 @@ enum {
3143c4
 	OPT_HASH_ALGORITHM,
3143c4
 	OPT_MGF,
3143c4
 	OPT_SALT,
3143c4
+	OPT_VERIFY,
3143c4
+	OPT_SIGNATURE_FILE,
3143c4
 };
3143c4
 
3143c4
 static const struct option options[] = {
3143c4
@@ -161,6 +163,7 @@ static const struct option options[] = {
3143c4
 	{ "list-objects",	0, NULL,		'O' },
3143c4
 
3143c4
 	{ "sign",		0, NULL,		's' },
3143c4
+	{ "verify",		0, NULL,		OPT_VERIFY },
3143c4
 	{ "decrypt",		0, NULL,		OPT_DECRYPT },
3143c4
 	{ "hash",		0, NULL,		'h' },
3143c4
 	{ "derive",		0, NULL,		OPT_DERIVE },
3143c4
@@ -203,6 +206,7 @@ static const struct option options[] = {
3143c4
 	{ "set-id",		1, NULL,		'e' },
3143c4
 	{ "attr-from",		1, NULL,		OPT_ATTR_FROM },
3143c4
 	{ "input-file",		1, NULL,		'i' },
3143c4
+	{ "signature-file",	1, NULL,		OPT_SIGNATURE_FILE },
3143c4
 	{ "output-file",	1, NULL,		'o' },
3143c4
 	{ "signature-format",	1, NULL,		'f' },
3143c4
 
3143c4
@@ -230,6 +234,7 @@ static const char *option_help[] = {
3143c4
 	"Show objects on token",
3143c4
 
3143c4
 	"Sign some data",
3143c4
+	"Verify a signature of some data",
3143c4
 	"Decrypt some data",
3143c4
 	"Hash some data",
3143c4
 	"Derive a secret key using another key and some data",
3143c4
@@ -272,6 +277,7 @@ static const char *option_help[] = {
3143c4
 	"Set the CKA_ID of an object, <args>= the (new) CKA_ID",
3143c4
 	"Use <arg> to create some attributes when writing an object",
3143c4
 	"Specify the input file",
3143c4
+	"Specify the file with signature for verification",
3143c4
 	"Specify the output file",
3143c4
 	"Format for ECDSA signature <arg>: 'rs' (default), 'sequence', 'openssl'",
3143c4
 
3143c4
@@ -293,6 +299,7 @@ static const char *	app_name = "pkcs11-tool"; /* for utils.c */
3143c4
 static int		verbose = 0;
3143c4
 static const char *	opt_input = NULL;
3143c4
 static const char *	opt_output = NULL;
3143c4
+static const char *	opt_signature_file = NULL;
3143c4
 static const char *	opt_module = DEFAULT_PKCS11_PROVIDER;
3143c4
 static int		opt_slot_set = 0;
3143c4
 static CK_SLOT_ID	opt_slot = 0;
3143c4
@@ -331,8 +338,8 @@ static int		opt_derive_pass_der = 0;
3143c4
 static unsigned long	opt_random_bytes = 0;
3143c4
 static CK_MECHANISM_TYPE opt_hash_alg = 0;
3143c4
 static unsigned long	opt_mgf = 0;
3143c4
-static long	        salt_len = 0;
3143c4
-static int		salt_len_given = 0; /* 0 - not given, 1 - given with input parameters */
3143c4
+static long	        opt_salt_len = 0;
3143c4
+static int		opt_salt_len_given = 0; /* 0 - not given, 1 - given with input parameters */
3143c4
 
3143c4
 static void *module = NULL;
3143c4
 static CK_FUNCTION_LIST_PTR p11 = NULL;
3143c4
@@ -396,6 +403,7 @@ static void		show_key(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
3143c4
 static void		show_cert(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
3143c4
 static void		show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj);
3143c4
 static void		sign_data(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
3143c4
+static void		verify_signature(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
3143c4
 static void		decrypt_data(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
3143c4
 static void		hash_data(CK_SLOT_ID, CK_SESSION_HANDLE);
3143c4
 static void		derive_key(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
3143c4
@@ -532,6 +540,7 @@ int main(int argc, char * argv[])
3143c4
 	int do_list_mechs = 0;
3143c4
 	int do_list_objects = 0;
3143c4
 	int do_sign = 0;
3143c4
+	int do_verify = 0;
3143c4
 	int do_decrypt = 0;
3143c4
 	int do_hash = 0;
3143c4
 	int do_derive = 0;
3143c4
@@ -685,6 +694,9 @@ int main(int argc, char * argv[])
3143c4
 		case 'i':
3143c4
 			opt_input = optarg;
3143c4
 			break;
3143c4
+		case OPT_SIGNATURE_FILE:
3143c4
+			opt_signature_file = optarg;
3143c4
+			break;
3143c4
 		case 'l':
3143c4
 			need_session |= NEED_SESSION_RW;
3143c4
 			opt_login = 1;
3143c4
@@ -700,8 +712,8 @@ int main(int argc, char * argv[])
3143c4
 			opt_mgf = p11_name_to_mgf(optarg);
3143c4
 			break;
3143c4
 		case OPT_SALT:
3143c4
-			salt_len = (CK_ULONG) strtoul(optarg, NULL, 0);
3143c4
-			salt_len_given = 1;
3143c4
+			opt_salt_len = (CK_ULONG) strtoul(optarg, NULL, 0);
3143c4
+			opt_salt_len_given = 1;
3143c4
 			break;
3143c4
 		case 'o':
3143c4
 			opt_output = optarg;
3143c4
@@ -726,6 +738,11 @@ int main(int argc, char * argv[])
3143c4
 			do_sign = 1;
3143c4
 			action_count++;
3143c4
 			break;
3143c4
+		case OPT_VERIFY:
3143c4
+			need_session |= NEED_SESSION_RO;
3143c4
+			do_verify = 1;
3143c4
+			action_count++;
3143c4
+			break;
3143c4
 		case OPT_DECRYPT:
3143c4
 			need_session |= NEED_SESSION_RW;
3143c4
 			do_decrypt = 1;
3143c4
@@ -1037,6 +1054,16 @@ int main(int argc, char * argv[])
3143c4
 			util_fatal("Private key not found");
3143c4
 	}
3143c4
 
3143c4
+	if (do_verify) {
3143c4
+		if (!find_object(session, CKO_PUBLIC_KEY, &object,
3143c4
+		        opt_object_id_len ? opt_object_id : NULL,
3143c4
+		        opt_object_id_len, 0) &&
3143c4
+		    !find_object(session, CKO_CERTIFICATE, &object,
3143c4
+		        opt_object_id_len ? opt_object_id : NULL,
3143c4
+		        opt_object_id_len, 0))
3143c4
+			util_fatal("Public key nor certificate not found");
3143c4
+	}
3143c4
+
3143c4
 	/* before list objects, so we can see a derived key */
3143c4
 	if (do_derive)
3143c4
 		derive_key(opt_slot, session, object);
3143c4
@@ -1047,6 +1074,9 @@ int main(int argc, char * argv[])
3143c4
 	if (do_sign)
3143c4
 		sign_data(opt_slot, session, object);
3143c4
 
3143c4
+	if (do_verify)
3143c4
+		verify_signature(opt_slot, session, object);
3143c4
+
3143c4
 	if (do_decrypt)
3143c4
 		decrypt_data(opt_slot, session, object);
3143c4
 
3143c4
@@ -1636,7 +1666,7 @@ static int unlock_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess, int login_type)
3143c4
 }
3143c4
 
3143c4
 /* return digest length in bytes */
3143c4
-static unsigned long figure_pss_salt_length(const int hash) {
3143c4
+static unsigned long hash_length(const int hash) {
3143c4
 	unsigned long sLen = 0;
3143c4
 	switch (hash) {
3143c4
 	case  CKM_SHA_1:
3143c4
@@ -1662,26 +1692,16 @@ static unsigned long figure_pss_salt_length(const int hash) {
3143c4
 	return sLen;
3143c4
 }
3143c4
 
3143c4
-static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
3143c4
-		CK_OBJECT_HANDLE key)
3143c4
+static unsigned long
3143c4
+parse_pss_params(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key,
3143c4
+    CK_MECHANISM *mech, CK_RSA_PKCS_PSS_PARAMS *pss_params)
3143c4
 {
3143c4
-	unsigned char	in_buffer[1025], sig_buffer[512];
3143c4
-	CK_MECHANISM	mech;
3143c4
-	CK_RSA_PKCS_PSS_PARAMS pss_params;
3143c4
-	CK_RV		rv;
3143c4
-	CK_ULONG	sig_len;
3143c4
-	int		fd, r;
3143c4
+	unsigned long hashlen = 0;
3143c4
 
3143c4
-	unsigned long hashlen = 0, modlen = 0;
3143c4
-
3143c4
-	if (!opt_mechanism_used)
3143c4
-		if (!find_mechanism(slot, CKF_SIGN|CKF_HW, NULL, 0, &opt_mechanism))
3143c4
-			util_fatal("Sign mechanism not supported");
3143c4
+	if (pss_params == NULL)
3143c4
+		return 0;
3143c4
 
3143c4
-	fprintf(stderr, "Using signature algorithm %s\n", p11_mechanism_to_name(opt_mechanism));
3143c4
-	memset(&mech, 0, sizeof(mech));
3143c4
-	mech.mechanism = opt_mechanism;
3143c4
-	pss_params.hashAlg = 0;
3143c4
+	pss_params->hashAlg = 0;
3143c4
 
3143c4
 	if (opt_hash_alg != 0 && opt_mechanism != CKM_RSA_PKCS_PSS)
3143c4
 		util_fatal("The hash-algorithm is applicable only to "
3143c4
@@ -1690,93 +1710,118 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
3143c4
 	/* set "default" MGF and hash algorithms. We can overwrite MGF later */
3143c4
 	switch (opt_mechanism) {
3143c4
 	case CKM_RSA_PKCS_PSS:
3143c4
-		pss_params.hashAlg = opt_hash_alg;
3143c4
+		pss_params->hashAlg = opt_hash_alg;
3143c4
 
3143c4
 		switch (opt_hash_alg) {
3143c4
 		case CKM_SHA224:
3143c4
-			pss_params.mgf = CKG_MGF1_SHA224;
3143c4
+			pss_params->mgf = CKG_MGF1_SHA224;
3143c4
 			break;
3143c4
 		case CKM_SHA256:
3143c4
-			pss_params.mgf = CKG_MGF1_SHA256;
3143c4
+			pss_params->mgf = CKG_MGF1_SHA256;
3143c4
 			break;
3143c4
 		case CKM_SHA384:
3143c4
-			pss_params.mgf = CKG_MGF1_SHA384;
3143c4
+			pss_params->mgf = CKG_MGF1_SHA384;
3143c4
 			break;
3143c4
 		case CKM_SHA512:
3143c4
-			pss_params.mgf = CKG_MGF1_SHA512;
3143c4
+			pss_params->mgf = CKG_MGF1_SHA512;
3143c4
 			break;
3143c4
 		default:
3143c4
 			/* the PSS should use SHA-1 if not specified */
3143c4
-			pss_params.hashAlg = CKM_SHA_1;
3143c4
+			pss_params->hashAlg = CKM_SHA_1;
3143c4
 			/* fallthrough */
3143c4
 		case CKM_SHA_1:
3143c4
-			pss_params.mgf = CKG_MGF1_SHA1;
3143c4
+			pss_params->mgf = CKG_MGF1_SHA1;
3143c4
 		}
3143c4
 		break;
3143c4
 
3143c4
 	case CKM_SHA1_RSA_PKCS_PSS:
3143c4
-		pss_params.hashAlg = CKM_SHA_1;
3143c4
-		pss_params.mgf = CKG_MGF1_SHA1;
3143c4
+		pss_params->hashAlg = CKM_SHA_1;
3143c4
+		pss_params->mgf = CKG_MGF1_SHA1;
3143c4
 		break;
3143c4
 
3143c4
 	case CKM_SHA224_RSA_PKCS_PSS:
3143c4
-		pss_params.hashAlg = CKM_SHA224;
3143c4
-		pss_params.mgf = CKG_MGF1_SHA224;
3143c4
+		pss_params->hashAlg = CKM_SHA224;
3143c4
+		pss_params->mgf = CKG_MGF1_SHA224;
3143c4
 		break;
3143c4
 
3143c4
 	case CKM_SHA256_RSA_PKCS_PSS:
3143c4
-		pss_params.hashAlg = CKM_SHA256;
3143c4
-		pss_params.mgf = CKG_MGF1_SHA256;
3143c4
+		pss_params->hashAlg = CKM_SHA256;
3143c4
+		pss_params->mgf = CKG_MGF1_SHA256;
3143c4
 		break;
3143c4
 
3143c4
 	case CKM_SHA384_RSA_PKCS_PSS:
3143c4
-		pss_params.hashAlg = CKM_SHA384;
3143c4
-		pss_params.mgf = CKG_MGF1_SHA384;
3143c4
+		pss_params->hashAlg = CKM_SHA384;
3143c4
+		pss_params->mgf = CKG_MGF1_SHA384;
3143c4
 		break;
3143c4
 
3143c4
 	case CKM_SHA512_RSA_PKCS_PSS:
3143c4
-		pss_params.hashAlg = CKM_SHA512;
3143c4
-		pss_params.mgf = CKG_MGF1_SHA512;
3143c4
+		pss_params->hashAlg = CKM_SHA512;
3143c4
+		pss_params->mgf = CKG_MGF1_SHA512;
3143c4
 		break;
3143c4
 	}
3143c4
 
3143c4
 	/* One of RSA-PSS mechanisms above: They need parameters */
3143c4
-	if (pss_params.hashAlg) {
3143c4
+	if (pss_params->hashAlg) {
3143c4
 		if (opt_mgf != 0)
3143c4
-			pss_params.mgf = opt_mgf;
3143c4
+			pss_params->mgf = opt_mgf;
3143c4
 
3143c4
-		hashlen = figure_pss_salt_length(pss_params.hashAlg);
3143c4
+		hashlen = hash_length(pss_params->hashAlg);
3143c4
 
3143c4
-		if (salt_len_given == 1) { /* salt size explicitly given */
3143c4
-			if (salt_len < 0 && salt_len != -1 && salt_len != -2)
3143c4
-				util_fatal("Salt length must be greater or equal \
3143c4
-to zero, or equal to -1 (meaning: use digest size) or to -2 \
3143c4
-(meaning: use maximum permissible size");
3143c4
+		if (opt_salt_len_given == 1) { /* salt size explicitly given */
3143c4
+			unsigned long modlen = 0;
3143c4
+			if (opt_salt_len < 0 && opt_salt_len != -1 && opt_salt_len != -2)
3143c4
+				util_fatal("Salt length must be greater or equal "
3143c4
+				    "to zero, or equal to -1 (meaning: use digest size) "
3143c4
+				    "or to -2 (meaning: use maximum permissible size");
3143c4
 		  
3143c4
 			modlen = (get_private_key_length(session, key) + 7) / 8;
3143c4
-			switch(salt_len) {
3143c4
+			switch (opt_salt_len) {
3143c4
 			case -1: /* salt size equals to digest size */
3143c4
-				pss_params.sLen = hashlen;
3143c4
+				pss_params->sLen = hashlen;
3143c4
 				break;
3143c4
 			case -2: /* maximum permissible salt len */
3143c4
-				pss_params.sLen = modlen - hashlen -2;
3143c4
+				pss_params->sLen = modlen - hashlen -2;
3143c4
 				break;
3143c4
 			default: /* use given size but its value must be >= 0 */
3143c4
-				pss_params.sLen = salt_len;
3143c4
+				pss_params->sLen = opt_salt_len;
3143c4
 				break;
3143c4
-			} /* end switch (salt_len_given) */
3143c4
+			} /* end switch (opt_salt_len_given) */
3143c4
 		} else { /* use default: salt len of digest size */
3143c4
-			pss_params.sLen = hashlen;
3143c4
+			pss_params->sLen = hashlen;
3143c4
 		}
3143c4
 
3143c4
-		mech.pParameter = &pss_params;
3143c4
-		mech.ulParameterLen = sizeof(pss_params);
3143c4
+		mech->pParameter = pss_params;
3143c4
+		mech->ulParameterLen = sizeof(*pss_params);
3143c4
 
3143c4
 		fprintf(stderr, "PSS parameters: hashAlg=%s, mgf=%s, salt_len=%lu B\n",
3143c4
-			p11_mechanism_to_name(pss_params.hashAlg),
3143c4
-			p11_mgf_to_name(pss_params.mgf),
3143c4
-			pss_params.sLen);
3143c4
+			p11_mechanism_to_name(pss_params->hashAlg),
3143c4
+			p11_mgf_to_name(pss_params->mgf),
3143c4
+			pss_params->sLen);
3143c4
 	}
3143c4
+	return hashlen;
3143c4
+}
3143c4
+
3143c4
+static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
3143c4
+		CK_OBJECT_HANDLE key)
3143c4
+{
3143c4
+	unsigned char	in_buffer[1025], sig_buffer[512];
3143c4
+	CK_MECHANISM	mech;
3143c4
+	CK_RSA_PKCS_PSS_PARAMS pss_params;
3143c4
+	CK_RV		rv;
3143c4
+	CK_ULONG	sig_len;
3143c4
+	int		fd, r;
3143c4
+	unsigned long	hashlen;
3143c4
+
3143c4
+	if (!opt_mechanism_used)
3143c4
+		if (!find_mechanism(slot, CKF_SIGN|CKF_HW, NULL, 0, &opt_mechanism))
3143c4
+			util_fatal("Sign mechanism not supported");
3143c4
+
3143c4
+	fprintf(stderr, "Using signature algorithm %s\n", p11_mechanism_to_name(opt_mechanism));
3143c4
+	memset(&mech, 0, sizeof(mech));
3143c4
+	mech.mechanism = opt_mechanism;
3143c4
+	hashlen = parse_pss_params(session, key, &mech, &pss_params);
3143c4
+	if (hashlen == 0)
3143c4
+		util_fatal("Invalid RSA-PSS parameters");
3143c4
 
3143c4
 	if (opt_input == NULL)
3143c4
 		fd = 0;
3143c4
@@ -1787,12 +1832,15 @@ to zero, or equal to -1 (meaning: use digest size) or to -2 \
3143c4
 	if (r < 0)
3143c4
 		util_fatal("Cannot read from %s: %m", opt_input);
3143c4
 
3143c4
-	if (opt_mechanism == CKM_RSA_PKCS_PSS && (unsigned long)r != hashlen)
3143c4
-		util_fatal("For %s mechanism, message size (got %d bytes) must be equal to specified digest length (%lu)\n",
3143c4
-			p11_mechanism_to_name(opt_mechanism), r, hashlen);
3143c4
+	if (opt_mechanism == CKM_RSA_PKCS_PSS) {
3143c4
+		if  ((unsigned long)r != hashlen)
3143c4
+			util_fatal("For %s mechanism, message size (got %d bytes) "
3143c4
+			     "must be equal to specified digest length (%lu)\n",
3143c4
+			    p11_mechanism_to_name(opt_mechanism), r, hashlen);
3143c4
+	}
3143c4
 
3143c4
 	rv = CKR_CANCEL;
3143c4
-	if (r < (int) sizeof(in_buffer))   {
3143c4
+	if (r < (int) sizeof(in_buffer)) {
3143c4
 		rv = p11->C_SignInit(session, &mech, key);
3143c4
 		if (rv != CKR_OK)
3143c4
 			p11_fatal("C_SignInit", rv);
3143c4
@@ -1833,12 +1881,16 @@ to zero, or equal to -1 (meaning: use digest size) or to -2 \
3143c4
 		util_fatal("failed to open %s: %m", opt_output);
3143c4
 	}
3143c4
 
3143c4
-	if (opt_mechanism == CKM_ECDSA || opt_mechanism == CKM_ECDSA_SHA1 || opt_mechanism == CKM_ECDSA_SHA256 || opt_mechanism == CKM_ECDSA_SHA384 || opt_mechanism == CKM_ECDSA_SHA512 || opt_mechanism == CKM_ECDSA_SHA224) {
3143c4
-		if (opt_sig_format &&  (!strcmp(opt_sig_format, "openssl") || !strcmp(opt_sig_format, "sequence"))) {
3143c4
+	if (opt_mechanism == CKM_ECDSA || opt_mechanism == CKM_ECDSA_SHA1 ||
3143c4
+	    opt_mechanism == CKM_ECDSA_SHA256 || opt_mechanism == CKM_ECDSA_SHA384 ||
3143c4
+	    opt_mechanism == CKM_ECDSA_SHA512 || opt_mechanism == CKM_ECDSA_SHA224) {
3143c4
+		if (opt_sig_format && (!strcmp(opt_sig_format, "openssl") ||
3143c4
+		                       !strcmp(opt_sig_format, "sequence"))) {
3143c4
 			unsigned char *seq;
3143c4
 			size_t seqlen;
3143c4
 
3143c4
-			if (sc_asn1_sig_value_rs_to_sequence(NULL, sig_buffer, sig_len, &seq, &seqlen)) {
3143c4
+			if (sc_asn1_sig_value_rs_to_sequence(NULL, sig_buffer,
3143c4
+			    sig_len, &seq, &seqlen)) {
3143c4
 				util_fatal("Failed to convert signature to ASN.1 sequence format");
3143c4
 			}
3143c4
 
3143c4
@@ -1856,6 +1908,97 @@ to zero, or equal to -1 (meaning: use digest size) or to -2 \
3143c4
 		close(fd);
3143c4
 }
3143c4
 
3143c4
+static void verify_signature(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
3143c4
+		CK_OBJECT_HANDLE key)
3143c4
+{
3143c4
+	unsigned char	in_buffer[1025], sig_buffer[512];
3143c4
+	CK_MECHANISM	mech;
3143c4
+	CK_RSA_PKCS_PSS_PARAMS pss_params;
3143c4
+	CK_RV		rv;
3143c4
+	CK_ULONG	sig_len;
3143c4
+	int		fd, fd2, r, r2;
3143c4
+	unsigned long   hashlen;
3143c4
+
3143c4
+	if (!opt_mechanism_used)
3143c4
+		if (!find_mechanism(slot, CKF_VERIFY|CKF_HW, NULL, 0, &opt_mechanism))
3143c4
+			util_fatal("Mechanism not supported for signature verification");
3143c4
+
3143c4
+	fprintf(stderr, "Using signature algorithm %s\n", p11_mechanism_to_name(opt_mechanism));
3143c4
+	memset(&mech, 0, sizeof(mech));
3143c4
+	mech.mechanism = opt_mechanism;
3143c4
+	hashlen = parse_pss_params(session, key, &mech, &pss_params);
3143c4
+	if (hashlen == 0)
3143c4
+		util_fatal("Invalid RSA-PSS parameters");
3143c4
+
3143c4
+	/* Open a signature file */
3143c4
+	if (opt_signature_file == NULL)
3143c4
+		util_fatal("No file with signature provided. Use --signature-file");
3143c4
+	else if ((fd2 = open(opt_signature_file, O_RDONLY|O_BINARY)) < 0)
3143c4
+		util_fatal("Cannot open %s: %m", opt_signature_file);
3143c4
+
3143c4
+	r2 = read(fd2, sig_buffer, sizeof(sig_buffer));
3143c4
+	if (r2 < 0)
3143c4
+		util_fatal("Cannot read from %s: %m", opt_signature_file);
3143c4
+
3143c4
+	close(fd2);
3143c4
+
3143c4
+	/* Open the data file */
3143c4
+	if (opt_input == NULL)
3143c4
+		fd = 0;
3143c4
+	else if ((fd = open(opt_input, O_RDONLY|O_BINARY)) < 0)
3143c4
+		util_fatal("Cannot open %s: %m", opt_input);
3143c4
+
3143c4
+	r = read(fd, in_buffer, sizeof(in_buffer));
3143c4
+	if (r < 0)
3143c4
+		util_fatal("Cannot read from %s: %m", opt_input);
3143c4
+
3143c4
+	if (opt_mechanism == CKM_RSA_PKCS_PSS) {
3143c4
+		if ((unsigned long)r != hashlen)
3143c4
+			util_fatal("For %s mechanism, message size (got %d bytes)"
3143c4
+			    " must be equal to specified digest length (%lu)\n",
3143c4
+			    p11_mechanism_to_name(opt_mechanism), r, hashlen);
3143c4
+	}
3143c4
+
3143c4
+	rv = CKR_CANCEL;
3143c4
+	if (r < (int) sizeof(in_buffer)) {
3143c4
+		rv = p11->C_VerifyInit(session, &mech, key);
3143c4
+		if (rv != CKR_OK)
3143c4
+			p11_fatal("C_VerifyInit", rv);
3143c4
+
3143c4
+		sig_len = r2;
3143c4
+		rv =  p11->C_Verify(session, in_buffer, r, sig_buffer, sig_len);
3143c4
+	}
3143c4
+
3143c4
+	if (rv != CKR_OK) {
3143c4
+		rv = p11->C_VerifyInit(session, &mech, key);
3143c4
+		if (rv != CKR_OK)
3143c4
+			p11_fatal("C_VerifyInit", rv);
3143c4
+
3143c4
+		do   {
3143c4
+			rv = p11->C_VerifyUpdate(session, in_buffer, r);
3143c4
+			if (rv != CKR_OK)
3143c4
+				p11_fatal("C_VerifyUpdate", rv);
3143c4
+
3143c4
+			r = read(fd, in_buffer, sizeof(in_buffer));
3143c4
+		} while (r > 0);
3143c4
+
3143c4
+		sig_len = sizeof(sig_buffer);
3143c4
+		rv = p11->C_VerifyFinal(session, sig_buffer, sig_len);
3143c4
+		if (rv != CKR_OK)
3143c4
+			p11_fatal("C_VerifyFinal", rv);
3143c4
+	}
3143c4
+
3143c4
+	if (fd != 0)
3143c4
+		close(fd);
3143c4
+
3143c4
+	if (rv == CKR_OK)
3143c4
+		printf("Signature is valid\n");
3143c4
+	else if (rv == CKR_SIGNATURE_INVALID)
3143c4
+		printf("Invalid signature\n");
3143c4
+	else
3143c4
+		printf("Cryptoki returned erorr: %s\n", CKR2Str(rv));
3143c4
+}
3143c4
+
3143c4
 
3143c4
 static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
3143c4
 		CK_OBJECT_HANDLE key)
3143c4
3143c4
From 256502bed97d56a6813c0b4a7d4c64ee1ff0606e Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Fri, 14 Sep 2018 17:27:11 +0200
3143c4
Subject: [PATCH 5/5] slot: Switch cleanup steps to avoid segfaults on errors
3143c4
3143c4
and some more sanity checking
3143c4
3143c4
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
3143c4
---
3143c4
 src/pkcs11/framework-pkcs15.c | 2 +-
3143c4
 src/pkcs11/slot.c             | 4 ++--
3143c4
 2 files changed, 3 insertions(+), 3 deletions(-)
3143c4
3143c4
diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
3143c4
index a75d239f4..85e12df66 100644
3143c4
--- a/src/pkcs11/framework-pkcs15.c
3143c4
+++ b/src/pkcs11/framework-pkcs15.c
3143c4
@@ -365,7 +365,7 @@ pkcs15_unbind(struct sc_pkcs11_card *p11card)
3143c4
 
3143c4
 		unlock_card(fw_data);
3143c4
 
3143c4
-		if (fw_data->p15_card) {
3143c4
+		if (fw_data->p15_card && fw_data->p15_card->card) {
3143c4
 			if (idx == 0) {
3143c4
 				int rc = sc_detect_card_presence(fw_data->p15_card->card->reader);
3143c4
 				if (rc <= 0 || rc & SC_READER_CARD_CHANGED) {
3143c4
diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c
3143c4
index fe322e68e..3102bf986 100644
3143c4
--- a/src/pkcs11/slot.c
3143c4
+++ b/src/pkcs11/slot.c
3143c4
@@ -374,10 +374,10 @@ CK_RV card_detect(sc_reader_t *reader)
3143c4
 
3143c4
 fail:
3143c4
 	if (free_p11card) {
3143c4
-		if (p11card->card != NULL)
3143c4
-			sc_disconnect_card(p11card->card);
3143c4
 		if (p11card->framework)
3143c4
 			p11card->framework->unbind(p11card);
3143c4
+		if (p11card->card != NULL)
3143c4
+			sc_disconnect_card(p11card->card);
3143c4
 		free(p11card);
3143c4
 	}
3143c4
 
3143c4
3143c4
From 2fd8e278f5d3664555cad706d7270229c87cae56 Mon Sep 17 00:00:00 2001
3143c4
From: Doug Engert <deengert@gmail.com>
3143c4
Date: Wed, 17 Oct 2018 16:07:20 -0500
3143c4
Subject: [PATCH] pkcs11/openssl.c - add missing mechanisms fixes #1497
3143c4
3143c4
 On branch pkcs11-openssl-c
3143c4
 Changes to be committed:
3143c4
	modified:   ../pkcs11/openssl.c
3143c4
---
3143c4
 src/pkcs11/openssl.c | 4 ++++
3143c4
 1 file changed, 4 insertions(+)
3143c4
3143c4
diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c
3143c4
index 00b9814e4..fb9f8fea8 100644
3143c4
--- a/src/pkcs11/openssl.c
3143c4
+++ b/src/pkcs11/openssl.c
3143c4
@@ -449,6 +449,8 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
3143c4
 		return CKR_GENERAL_ERROR;
3143c4
 
3143c4
 	if (md != NULL && (mech->mechanism == CKM_SHA1_RSA_PKCS
3143c4
+		|| mech->mechanism == CKM_MD5_RSA_PKCS
3143c4
+		|| mech->mechanism == CKM_RIPEMD160_RSA_PKCS
3143c4
 		|| mech->mechanism == CKM_SHA224_RSA_PKCS
3143c4
 		|| mech->mechanism == CKM_SHA256_RSA_PKCS
3143c4
 		|| mech->mechanism == CKM_SHA384_RSA_PKCS
3143c4
@@ -478,6 +480,8 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
3143c4
 		sc_log(context, "Trying to verify using low-level API");
3143c4
 		switch (mech->mechanism) {
3143c4
 		case CKM_RSA_PKCS:
3143c4
+		case CKM_MD5_RSA_PKCS:
3143c4
+		case CKM_RIPEMD160_RSA_PKCS:
3143c4
 		 	pad = RSA_PKCS1_PADDING;
3143c4
 		 	break;
3143c4
 		case CKM_RSA_X_509:
3143c4
3143c4
3143c4
From 9b289e074bff22f7e2339b7d3f9428c3233efb71 Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Wed, 31 Oct 2018 11:46:37 +0100
3143c4
Subject: [PATCH 2/7] coolkey: Check return values from list initialization
3143c4
 (coverity)
3143c4
3143c4
>>>     CID 324484:  Error handling issues  (CHECKED_RETURN)
3143c4
>>>     Calling "list_init" without checking return value (as is done elsewhere 8 out of 9 times).
3143c4
---
3143c4
 src/libopensc/card-coolkey.c | 13 ++++++++++---
3143c4
 1 file changed, 10 insertions(+), 3 deletions(-)
3143c4
3143c4
diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c
3143c4
index c1c09b662..e320290df 100644
3143c4
--- a/src/libopensc/card-coolkey.c
3143c4
+++ b/src/libopensc/card-coolkey.c
3143c4
@@ -784,18 +784,25 @@ size_t coolkey_list_meter(const void *el) {
3143c4
 	return sizeof(sc_cardctl_coolkey_object_t);
3143c4
 }
3143c4
 
3143c4
+static void coolkey_free_private_data(coolkey_private_data_t *priv);
3143c4
+
3143c4
 static coolkey_private_data_t *coolkey_new_private_data(void)
3143c4
 {
3143c4
 	coolkey_private_data_t *priv;
3143c4
+
3143c4
 	/* allocate priv and zero all the fields */
3143c4
 	priv = calloc(1, sizeof(coolkey_private_data_t));
3143c4
 	if (!priv)
3143c4
 		return NULL;
3143c4
+
3143c4
 	/* set other fields as appropriate */
3143c4
 	priv->key_id = COOLKEY_INVALID_KEY;
3143c4
-	list_init(&priv->objects_list);
3143c4
-	list_attributes_comparator(&priv->objects_list, coolkey_compare_id);
3143c4
-	list_attributes_copy(&priv->objects_list, coolkey_list_meter, 1);
3143c4
+	if (list_init(&priv->objects_list) != 0 ||
3143c4
+	    list_attributes_comparator(&priv->objects_list, coolkey_compare_id) != 0 ||
3143c4
+	    list_attributes_copy(&priv->objects_list, coolkey_list_meter, 1) != 0) {
3143c4
+		coolkey_free_private_data(priv);
3143c4
+		return NULL;
3143c4
+	}
3143c4
 
3143c4
 	return priv;
3143c4
 }
3143c4
3143c4
From a32fbd0525ea6e21e73b03086e29862481761848 Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Wed, 31 Oct 2018 15:02:00 +0100
3143c4
Subject: [PATCH 3/7] framework-pkcs15.c: Reformat
3143c4
3143c4
 * Reasonable line lengths
3143c4
 * Correct indentation
3143c4
 * Add missing SHA224 mechanism
3143c4
---
3143c4
 src/pkcs11/framework-pkcs15.c | 40 +++++++++++++++++++++++------------
3143c4
 1 file changed, 26 insertions(+), 14 deletions(-)
3143c4
3143c4
diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
3143c4
index 85e12df66..3657bcbdd 100644
3143c4
--- a/src/pkcs11/framework-pkcs15.c
3143c4
+++ b/src/pkcs11/framework-pkcs15.c
3143c4
@@ -5159,18 +5159,14 @@ register_mechanisms(struct sc_pkcs11_card *p11card)
3143c4
 	}
3143c4
 
3143c4
 #ifdef ENABLE_OPENSSL
3143c4
-		/* all our software hashes are in OpenSSL */
3143c4
-		/* Only if card did not list the hashes, will we
3143c4
-		 * help it a little, by adding all the OpenSSL hashes
3143c4
-		 * that have PKCS#11 mechanisms.
3143c4
-		 */
3143c4
-		if (!(rsa_flags & SC_ALGORITHM_RSA_HASHES)) {
3143c4
-			rsa_flags |= SC_ALGORITHM_RSA_HASHES;
3143c4
-#if OPENSSL_VERSION_NUMBER <  0x00908000L
3143c4
-		/* turn off hashes not in openssl 0.9.8 */
3143c4
-			rsa_flags &= ~(SC_ALGORITHM_RSA_HASH_SHA256 | SC_ALGORITHM_RSA_HASH_SHA384 | SC_ALGORITHM_RSA_HASH_SHA512 | SC_ALGORITHM_RSA_HASH_SHA224);
3143c4
-#endif
3143c4
-		}
3143c4
+	/* all our software hashes are in OpenSSL */
3143c4
+	/* Only if card did not list the hashes, will we
3143c4
+	 * help it a little, by adding all the OpenSSL hashes
3143c4
+	 * that have PKCS#11 mechanisms.
3143c4
+	 */
3143c4
+	if (!(rsa_flags & SC_ALGORITHM_RSA_HASHES)) {
3143c4
+		rsa_flags |= SC_ALGORITHM_RSA_HASHES;
3143c4
+	}
3143c4
 #endif
3143c4
 
3143c4
 	/* No need to Check for PKCS1  We support it in software and turned it on above so always added it */
3143c4
@@ -5182,32 +5182,44 @@ register_mechanisms(struct sc_pkcs11_card *p11card)
3143c4
 		 * Either the card set the hashes or we helped it above */
3143c4
 
3143c4
 		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA1) {
3143c4
-			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA1_RSA_PKCS, CKM_SHA_1, mt);
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+				CKM_SHA1_RSA_PKCS, CKM_SHA_1, mt);
3143c4
+			if (rc != CKR_OK)
3143c4
+				return rc;
3143c4
+		}
3143c4
+		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA224) {
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+				CKM_SHA224_RSA_PKCS, CKM_SHA224, mt);
3143c4
 			if (rc != CKR_OK)
3143c4
 				return rc;
3143c4
 		}
3143c4
 		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA256) {
3143c4
-			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA256_RSA_PKCS, CKM_SHA256, mt);
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+				CKM_SHA256_RSA_PKCS, CKM_SHA256, mt);
3143c4
 			if (rc != CKR_OK)
3143c4
 				return rc;
3143c4
 		}
3143c4
 		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA384) {
3143c4
-			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA384_RSA_PKCS, CKM_SHA384, mt);
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+				CKM_SHA384_RSA_PKCS, CKM_SHA384, mt);
3143c4
 			if (rc != CKR_OK)
3143c4
 				return rc;
3143c4
 		}
3143c4
 		if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA512) {
3143c4
-			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA512_RSA_PKCS, CKM_SHA512, mt);
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+				CKM_SHA512_RSA_PKCS, CKM_SHA512, mt);
3143c4
 			if (rc != CKR_OK)
3143c4
 				return rc;
3143c4
 		}
3143c4
 		if (rsa_flags & SC_ALGORITHM_RSA_HASH_MD5) {
3143c4
-			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_MD5_RSA_PKCS, CKM_MD5, mt);
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+				CKM_MD5_RSA_PKCS, CKM_MD5, mt);
3143c4
 			if (rc != CKR_OK)
3143c4
 				return rc;
3143c4
 		}
3143c4
 		if (rsa_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160) {
3143c4
-			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_RIPEMD160_RSA_PKCS, CKM_RIPEMD160, mt);
3143c4
+			rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card,
3143c4
+				CKM_RIPEMD160_RSA_PKCS, CKM_RIPEMD160, mt);
3143c4
 			if (rc != CKR_OK)
3143c4
 				return rc;
3143c4
 		}
3143c4
3143c4
From 7461c259c96f086621a35baeb699cf3cdc2968dd Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Wed, 31 Oct 2018 15:03:40 +0100
3143c4
Subject: [PATCH 4/7] framework-pkcs15.c: Add PKCS#1 mechanisms also if
3143c4
 SC_ALGORITHM_RSA_HASH_NONE is defined
3143c4
3143c4
---
3143c4
 src/pkcs11/framework-pkcs15.c | 2 +-
3143c4
 1 file changed, 1 insertion(+), 1 deletion(-)
3143c4
3143c4
diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
3143c4
index 3657bcbdd..cac39b821 100644
3143c4
--- a/src/pkcs11/framework-pkcs15.c
3143c4
+++ b/src/pkcs11/framework-pkcs15.c
3143c4
@@ -5164,7 +5164,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card)
3143c4
 	 * help it a little, by adding all the OpenSSL hashes
3143c4
 	 * that have PKCS#11 mechanisms.
3143c4
 	 */
3143c4
-	if (!(rsa_flags & SC_ALGORITHM_RSA_HASHES)) {
3143c4
+	if (!(rsa_flags & (SC_ALGORITHM_RSA_HASHES & ~SC_ALGORITHM_RSA_HASH_NONE))) {
3143c4
 		rsa_flags |= SC_ALGORITHM_RSA_HASHES;
3143c4
 	}
3143c4
 #endif
3143c4
3143c4
From 56a9dab5c0a3bc91175266296a70aea94cb5747b Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Wed, 31 Oct 2018 15:35:25 +0100
3143c4
Subject: [PATCH 5/7] p11test: Do not report incomplete key pairs
3143c4
3143c4
---
3143c4
 src/tests/p11test/p11test_case_pss_oaep.c | 4 ++++
3143c4
 1 file changed, 4 insertions(+)
3143c4
3143c4
diff --git a/src/tests/p11test/p11test_case_pss_oaep.c b/src/tests/p11test/p11test_case_pss_oaep.c
3143c4
index d0b8392fd..019471192 100644
3143c4
--- a/src/tests/p11test/p11test_case_pss_oaep.c
3143c4
+++ b/src/tests/p11test/p11test_case_pss_oaep.c
3143c4
@@ -815,6 +815,10 @@ void pss_oaep_test(void **state) {
3143c4
 	for (i = 0; i < objects.count; i++) {
3143c4
 		test_cert_t *o = &objects.data[i];
3143c4
 
3143c4
+		/* Do not go through incomplete pairs */
3143c4
+		if (o->private_handle == CK_INVALID_HANDLE)
3143c4
+			continue;
3143c4
+
3143c4
 		/* Do not list non-RSA keys here */
3143c4
 		if (o->type != EVP_PK_RSA)
3143c4
 			continue;
3143c4
3143c4
From 21d6d8092c98e572c89853593f3f680d219a06d9 Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Wed, 31 Oct 2018 15:39:56 +0100
3143c4
Subject: [PATCH 6/7] framework-pkcs15.c: Add SHA224 mechanism for PKCS#1.5
3143c4
3143c4
---
3143c4
 src/pkcs11/framework-pkcs15.c | 3 +++
3143c4
 1 file changed, 3 insertions(+)
3143c4
3143c4
diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
3143c4
index cac39b821..6948e31d4 100644
3143c4
--- a/src/pkcs11/framework-pkcs15.c
3143c4
+++ b/src/pkcs11/framework-pkcs15.c
3143c4
@@ -3781,6 +3781,9 @@ pkcs15_prkey_sign(struct sc_pkcs11_session *session, void *obj,
3143c4
 	case CKM_SHA1_RSA_PKCS:
3143c4
 		flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1;
3143c4
 		break;
3143c4
+	case CKM_SHA224_RSA_PKCS:
3143c4
+		flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA224;
3143c4
+		break;
3143c4
 	case CKM_SHA256_RSA_PKCS:
3143c4
 		flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA256;
3143c4
 		break;
3143c4
3143c4
From 7d4fa67efc22bf085863ead342b9fc55513425f1 Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Wed, 31 Oct 2018 17:50:08 +0100
3143c4
Subject: [PATCH 7/7] padding: Fix error checking in RSA-PSS
3143c4
3143c4
---
3143c4
 src/libopensc/padding.c | 2 +-
3143c4
 1 file changed, 1 insertion(+), 1 deletion(-)
3143c4
3143c4
diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c
3143c4
index 75c92b651..f0e2263b8 100644
3143c4
--- a/src/libopensc/padding.c
3143c4
+++ b/src/libopensc/padding.c
3143c4
@@ -345,7 +345,7 @@ static int sc_pkcs1_add_pss_padding(unsigned int hash, unsigned int mgf1_hash,
3143c4
 		if (EVP_DigestInit_ex(ctx, mgf1_md, NULL) != 1 ||
3143c4
 		    EVP_DigestUpdate(ctx, out + dblen, hlen) != 1 || /* H (Z parameter of MGF1) */
3143c4
 		    EVP_DigestUpdate(ctx, buf, 4) != 1 || /* C */
3143c4
-		    EVP_DigestFinal_ex(ctx, mask, NULL)) {
3143c4
+		    EVP_DigestFinal_ex(ctx, mask, NULL) != 1) {
3143c4
 			goto done;
3143c4
 		}
3143c4
 		/* this is no longer part of the MGF1, but actually
3143c4
3143c4
From e5d8395a7b8e5d6d1493d893c31fac321f45433a Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Tue, 20 Nov 2018 09:29:53 +0100
3143c4
Subject: [PATCH] pkcs11-tool: Unbreak signature and verification in
3143c4
 pkcs11-tool
3143c4
3143c4
---
3143c4
 src/tools/pkcs11-tool.c | 25 +++++++++++--------------
3143c4
 1 file changed, 11 insertions(+), 14 deletions(-)
3143c4
3143c4
diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c
3143c4
index df4a0ef3..ff1c00ac 100644
3143c4
--- a/src/tools/pkcs11-tool.c
3143c4
+++ b/src/tools/pkcs11-tool.c
3143c4
@@ -1758,6 +1758,9 @@ parse_pss_params(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key,
3143c4
 		pss_params->hashAlg = CKM_SHA512;
3143c4
 		pss_params->mgf = CKG_MGF1_SHA512;
3143c4
 		break;
3143c4
+
3143c4
+	default: /* The non-RSA-PSS algorithms do not need any parameters */
3143c4
+		return 0;
3143c4
 	}
3143c4
 
3143c4
 	/* One of RSA-PSS mechanisms above: They need parameters */
3143c4
@@ -1820,8 +1823,6 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
3143c4
 	memset(&mech, 0, sizeof(mech));
3143c4
 	mech.mechanism = opt_mechanism;
3143c4
 	hashlen = parse_pss_params(session, key, &mech, &pss_params);
3143c4
-	if (hashlen == 0)
3143c4
-		util_fatal("Invalid RSA-PSS parameters");
3143c4
 
3143c4
 	if (opt_input == NULL)
3143c4
 		fd = 0;
3143c4
@@ -1832,11 +1833,10 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
3143c4
 	if (r < 0)
3143c4
 		util_fatal("Cannot read from %s: %m", opt_input);
3143c4
 
3143c4
-	if (opt_mechanism == CKM_RSA_PKCS_PSS) {
3143c4
-		if  ((unsigned long)r != hashlen)
3143c4
-			util_fatal("For %s mechanism, message size (got %d bytes) "
3143c4
-			     "must be equal to specified digest length (%lu)\n",
3143c4
-			    p11_mechanism_to_name(opt_mechanism), r, hashlen);
3143c4
+	if (opt_mechanism == CKM_RSA_PKCS_PSS && (unsigned long)r != hashlen) {
3143c4
+		util_fatal("For %s mechanism, message size (got %d bytes) "
3143c4
+			"must be equal to specified digest length (%lu)\n",
3143c4
+			p11_mechanism_to_name(opt_mechanism), r, hashlen);
3143c4
 	}
3143c4
 
3143c4
 	rv = CKR_CANCEL;
3143c4
@@ -1927,8 +1927,6 @@ static void verify_signature(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
3143c4
 	memset(&mech, 0, sizeof(mech));
3143c4
 	mech.mechanism = opt_mechanism;
3143c4
 	hashlen = parse_pss_params(session, key, &mech, &pss_params);
3143c4
-	if (hashlen == 0)
3143c4
-		util_fatal("Invalid RSA-PSS parameters");
3143c4
 
3143c4
 	/* Open a signature file */
3143c4
 	if (opt_signature_file == NULL)
3143c4
@@ -1952,11 +1950,10 @@ static void verify_signature(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
3143c4
 	if (r < 0)
3143c4
 		util_fatal("Cannot read from %s: %m", opt_input);
3143c4
 
3143c4
-	if (opt_mechanism == CKM_RSA_PKCS_PSS) {
3143c4
-		if ((unsigned long)r != hashlen)
3143c4
-			util_fatal("For %s mechanism, message size (got %d bytes)"
3143c4
-			    " must be equal to specified digest length (%lu)\n",
3143c4
-			    p11_mechanism_to_name(opt_mechanism), r, hashlen);
3143c4
+	if (opt_mechanism == CKM_RSA_PKCS_PSS && (unsigned long)r != hashlen) {
3143c4
+		util_fatal("For %s mechanism, message size (got %d bytes)"
3143c4
+			" must be equal to specified digest length (%lu)\n",
3143c4
+			p11_mechanism_to_name(opt_mechanism), r, hashlen);
3143c4
 	}
3143c4
 
3143c4
 	rv = CKR_CANCEL;
3143c4
-- 
3143c4
2.19.1
3143c4
3143c4
From d517d8e18d9c7f918e38de7e613e34f6b3d21f09 Mon Sep 17 00:00:00 2001
3143c4
From: Luka Logar <luka.logar@iname.com>
3143c4
Date: Thu, 11 Oct 2018 11:22:15 +0200
3143c4
Subject: [PATCH] Fix minidriver padding
3143c4
3143c4
Commit e5707b545e5a2dc33b0ca52a8bf63f36f71b3d85 broke signing using minidriver on Windows.
3143c4
3143c4
More specifically changing #define SC_ALGORITHM_RSA_PAD_NONE from 0x00000000 to 0x00000001 caused a call to sc_pkcs1_encode() to fail as the padding algorithm was not specified anywhere in the CardSignData() implementation. It kind of worked as long as SC_ALGORITHM_RSA_PAD_NONE was 0x00000000, but the above mentioned commit broke this.
3143c4
3143c4
Now padding algorithm has to be explicitly specified, otherwise a call to sc_pkcs1_encode() will fail.
3143c4
---
3143c4
 src/libopensc/padding.c     | 2 +-
3143c4
 src/minidriver/minidriver.c | 1 +
3143c4
 2 files changed, 2 insertions(+), 1 deletion(-)
3143c4
3143c4
diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c
3143c4
index 53a87c352e..934fc67d11 100644
3143c4
--- a/src/libopensc/padding.c
3143c4
+++ b/src/libopensc/padding.c
3143c4
@@ -412,7 +412,7 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
3143c4
 	pad_algo  = flags & SC_ALGORITHM_RSA_PADS;
3143c4
 	sc_log(ctx, "hash algorithm 0x%X, pad algorithm 0x%X", hash_algo, pad_algo);
3143c4
 
3143c4
-	if ((pad_algo == SC_ALGORITHM_RSA_PAD_PKCS1 || !pad_algo) &&
3143c4
+	if ((pad_algo == SC_ALGORITHM_RSA_PAD_PKCS1 || pad_algo == SC_ALGORITHM_RSA_PAD_NONE) &&
3143c4
 	    hash_algo != SC_ALGORITHM_RSA_HASH_NONE) {
3143c4
 		i = sc_pkcs1_add_digest_info_prefix(hash_algo, in, in_len, out, &tmp_len);
3143c4
 		if (i != SC_SUCCESS) {
3143c4
3143c4
From ba2bcb3fd763a791750506ec30283cca0d1870cd Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Wed, 12 Dec 2018 10:55:39 +0100
3143c4
Subject: [PATCH 5/7] padding: Resotre the PAD_NONE if nothing else is
3143c4
 specified
3143c4
3143c4
Patch from Doug Engert
3143c4
---
3143c4
 src/libopensc/padding.c | 2 ++
3143c4
 1 file changed, 2 insertions(+)
3143c4
3143c4
diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c
3143c4
index 047b3bc82c..3456a6265a 100644
3143c4
--- a/src/libopensc/padding.c
3143c4
+++ b/src/libopensc/padding.c
3143c4
@@ -410,6 +410,8 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
3143c4
 
3143c4
 	hash_algo = flags & SC_ALGORITHM_RSA_HASHES;
3143c4
 	pad_algo  = flags & SC_ALGORITHM_RSA_PADS;
3143c4
+	if (pad_algo == 0)
3143c4
+		pad_algo = SC_ALGORITHM_RSA_PAD_NONE;
3143c4
 	sc_log(ctx, "hash algorithm 0x%X, pad algorithm 0x%X", hash_algo, pad_algo);
3143c4
 
3143c4
 	if ((pad_algo == SC_ALGORITHM_RSA_PAD_PKCS1 || pad_algo == SC_ALGORITHM_RSA_PAD_NONE) &&
3143c4
3143c4
From 8c535c184f41dff417eb23069fec511f911f8ae6 Mon Sep 17 00:00:00 2001
3143c4
From: Frank Morgner <frankmorgner@gmail.com>
3143c4
Date: Thu, 4 Oct 2018 15:59:11 +0200
3143c4
Subject: [PATCH] removed duplicate code for adding padding
3143c4
3143c4
Fixes padding handling of SC_ALGORITHM_RSA_PAD_NONE introduced with
3143c4
e5707b545e5a2dc33b0ca52a8bf63f36f71b3d85
3143c4
---
3143c4
 src/libopensc/padding.c     |   9 ++-
3143c4
 src/minidriver/minidriver.c | 144 +++++++++++++++---------------------
3143c4
 2 files changed, 64 insertions(+), 89 deletions(-)
3143c4
3143c4
diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c
3143c4
index 934fc67d11..75c92b651a 100644
3143c4
--- a/src/libopensc/padding.c
3143c4
+++ b/src/libopensc/padding.c
3143c4
@@ -487,18 +487,19 @@ int sc_get_encoding_flags(sc_context_t *ctx,
3143c4
 		*pflags = 0;
3143c4
 
3143c4
 	} else if ((caps & SC_ALGORITHM_RSA_PAD_PSS) &&
3143c4
-                   (iflags & SC_ALGORITHM_RSA_PAD_PSS)) {
3143c4
+			(iflags & SC_ALGORITHM_RSA_PAD_PSS)) {
3143c4
 		*sflags |= SC_ALGORITHM_RSA_PAD_PSS;
3143c4
 
3143c4
 	} else if (((caps & SC_ALGORITHM_RSA_RAW) &&
3143c4
-	            (iflags & SC_ALGORITHM_RSA_PAD_PKCS1))
3143c4
-	           || iflags & SC_ALGORITHM_RSA_PAD_PSS) {
3143c4
+				(iflags & SC_ALGORITHM_RSA_PAD_PKCS1))
3143c4
+			|| iflags & SC_ALGORITHM_RSA_PAD_PSS
3143c4
+			|| iflags & SC_ALGORITHM_RSA_PAD_NONE) {
3143c4
 		/* Use the card's raw RSA capability on the padded input */
3143c4
 		*sflags = SC_ALGORITHM_RSA_PAD_NONE;
3143c4
 		*pflags = iflags;
3143c4
 
3143c4
 	} else if ((caps & (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
3143c4
-	           (iflags & SC_ALGORITHM_RSA_PAD_PKCS1)) {
3143c4
+			(iflags & SC_ALGORITHM_RSA_PAD_PKCS1)) {
3143c4
 		/* A corner case - the card can partially do PKCS1, if we prepend the
3143c4
 		 * DigestInfo bit it will do the rest. */
3143c4
 		*sflags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE;
3143c4
3143c4
From b01beec4f82294d59b1cf737d5b74d0c194e98da Mon Sep 17 00:00:00 2001
3143c4
From: Jakub Jelen <jjelen@redhat.com>
3143c4
Date: Wed, 12 Dec 2018 11:56:31 +0100
3143c4
Subject: [PATCH 6/7] padding: Do not set wrong flags if the raw capability is
3143c4
 not available
3143c4
3143c4
Thanks Doug Engert for pointing the issue out
3143c4
---
3143c4
 src/libopensc/padding.c | 8 ++++----
3143c4
 1 file changed, 4 insertions(+), 4 deletions(-)
3143c4
3143c4
diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c
3143c4
index 3456a6265a..4a8fc17b9c 100644
3143c4
--- a/src/libopensc/padding.c
3143c4
+++ b/src/libopensc/padding.c
3143c4
@@ -492,10 +492,10 @@ int sc_get_encoding_flags(sc_context_t *ctx,
3143c4
 			(iflags & SC_ALGORITHM_RSA_PAD_PSS)) {
3143c4
 		*sflags |= SC_ALGORITHM_RSA_PAD_PSS;
3143c4
 
3143c4
-	} else if (((caps & SC_ALGORITHM_RSA_RAW) &&
3143c4
-				(iflags & SC_ALGORITHM_RSA_PAD_PKCS1))
3143c4
-			|| iflags & SC_ALGORITHM_RSA_PAD_PSS
3143c4
-			|| iflags & SC_ALGORITHM_RSA_PAD_NONE) {
3143c4
+	} else if ((caps & SC_ALGORITHM_RSA_RAW) &&
3143c4
+				(iflags & SC_ALGORITHM_RSA_PAD_PKCS1
3143c4
+				|| iflags & SC_ALGORITHM_RSA_PAD_PSS
3143c4
+				|| iflags & SC_ALGORITHM_RSA_PAD_NONE)) {
3143c4
 		/* Use the card's raw RSA capability on the padded input */
3143c4
 		*sflags = SC_ALGORITHM_RSA_PAD_NONE;
3143c4
 		*pflags = iflags;
3143c4