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