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