From 93e75e7ae50b9c20abed4fd6ca5a24a873cb0a3d Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 3 Nov 2020 06:45:30 -0500 Subject: [PATCH] import opensc-0.20.0-2.el8 --- .gitignore | 2 +- .opensc.metadata | 2 +- SOURCES/opensc-0.19.0-cac1.patch | 1113 -------- SOURCES/opensc-0.19.0-coolkey-2k.patch | 48 - SOURCES/opensc-0.19.0-coolkey-matching.patch | 112 - SOURCES/opensc-0.19.0-coverity.patch | 446 ---- SOURCES/opensc-0.19.0-dual.patch | 609 ----- SOURCES/opensc-0.19.0-idprime.patch | 604 +++-- SOURCES/opensc-0.19.0-rsa-pss.patch | 2385 ------------------ SOURCES/opensc-0.20.0-cardos.patch | 1338 ++++++++++ SPECS/opensc.spec | 44 +- 11 files changed, 1748 insertions(+), 4955 deletions(-) delete mode 100644 SOURCES/opensc-0.19.0-cac1.patch delete mode 100644 SOURCES/opensc-0.19.0-coolkey-2k.patch delete mode 100644 SOURCES/opensc-0.19.0-coolkey-matching.patch delete mode 100644 SOURCES/opensc-0.19.0-coverity.patch delete mode 100644 SOURCES/opensc-0.19.0-dual.patch delete mode 100644 SOURCES/opensc-0.19.0-rsa-pss.patch create mode 100644 SOURCES/opensc-0.20.0-cardos.patch diff --git a/.gitignore b/.gitignore index 846cace..e16cf74 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/opensc-0.19.0.tar.gz +SOURCES/opensc-0.20.0.tar.gz diff --git a/.opensc.metadata b/.opensc.metadata index ec57eb9..06d2db5 100644 --- a/.opensc.metadata +++ b/.opensc.metadata @@ -1 +1 @@ -56cd654550aed081eb8ed86edba86e6d766133c4 SOURCES/opensc-0.19.0.tar.gz +86bf24a556837fa94d8f9b5aa4be3c9e55d4d94d SOURCES/opensc-0.20.0.tar.gz diff --git a/SOURCES/opensc-0.19.0-cac1.patch b/SOURCES/opensc-0.19.0-cac1.patch deleted file mode 100644 index a864613..0000000 --- a/SOURCES/opensc-0.19.0-cac1.patch +++ /dev/null @@ -1,1113 +0,0 @@ -commit a2efcb184fcb0302bfadeb97b5cf8953cb77d0fb -Author: Jakub Jelen -Date: Tue Oct 9 16:03:19 2018 +0200 - - WIP: Add minimal CAC1 driver for legacy cards. - - It is using the same pkcs15 backend as the CAC2 cards as well as some of - the CAC2 driver methods. - - The separation is made mostly for easier card matching. - -diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am -index a99b0c57..5a17df2b 100644 ---- a/src/libopensc/Makefile.am -+++ b/src/libopensc/Makefile.am -@@ -40,7 +40,8 @@ libopensc_la_SOURCES_BASE = \ - card-mcrd.c card-starcos.c card-openpgp.c card-jcop.c \ - card-oberthur.c card-belpic.c card-atrust-acos.c \ - card-entersafe.c card-epass2003.c card-coolkey.c card-incrypto34.c \ -- card-piv.c card-cac.c card-muscle.c card-acos5.c \ -+ card-piv.c card-cac-common.c card-cac.c card-cac1.c \ -+ card-muscle.c card-acos5.c \ - card-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c \ - card-rtecp.c card-westcos.c card-myeid.c \ - card-itacns.c card-authentic.c \ -diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak -index 10a3b0a9..7ef642b6 100644 ---- a/src/libopensc/Makefile.mak -+++ b/src/libopensc/Makefile.mak -@@ -19,7 +19,7 @@ OBJECTS = \ - card-mcrd.obj card-starcos.obj card-openpgp.obj card-jcop.obj \ - card-oberthur.obj card-belpic.obj card-atrust-acos.obj \ - card-entersafe.obj card-epass2003.obj card-coolkey.obj \ -- card-incrypto34.obj card-cac.obj card-piv.obj card-muscle.obj \ -+ card-incrypto34.obj card-cac.obj card-cac1.obj card-piv.obj card-muscle.obj \ - card-acos5.obj \ - card-asepcos.obj card-akis.obj card-gemsafeV1.obj card-rutoken.obj \ - card-rtecp.obj card-westcos.obj card-myeid.obj \ -diff --git a/src/libopensc/card-cac-common.c b/src/libopensc/card-cac-common.c -new file mode 100644 -index 00000000..6c338bf9 ---- /dev/null -+++ b/src/libopensc/card-cac-common.c -@@ -0,0 +1,116 @@ -+/* -+ * card-cac-common.c: Code shared among CAC1 and CAC2 drivers -+ * -+ * Copyright (C) 2018, Red Hat, Inc. -+ * -+ * Author: Jakub Jelen -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#if HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include -+#include -+ -+#ifdef _WIN32 -+#include -+#else -+#include -+#endif -+ -+#include "internal.h" -+#include "iso7816.h" -+#include "card-cac-common.h" -+ -+/* default certificate labels for the CAC card */ -+const char *cac_labels[MAX_CAC_SLOTS] = { -+ "CAC ID Certificate", -+ "CAC Email Signature Certificate", -+ "CAC Email Encryption Certificate", -+ "CAC Cert 4", -+ "CAC Cert 5", -+ "CAC Cert 6", -+ "CAC Cert 7", -+ "CAC Cert 8", -+ "CAC Cert 9", -+ "CAC Cert 10", -+ "CAC Cert 11", -+ "CAC Cert 12", -+ "CAC Cert 13", -+ "CAC Cert 14", -+ "CAC Cert 15", -+ "CAC Cert 16" -+}; -+ -+const char *get_cac_label(int index) -+{ -+ if (index < 0 || index >= MAX_CAC_SLOTS) -+ return NULL; -+ -+ return cac_labels[index]; -+} -+ -+static int cac_list_compare_path(const void *a, const void *b) -+{ -+ if (a == NULL || b == NULL) -+ return 1; -+ return memcmp( &((cac_object_t *) a)->path, -+ &((cac_object_t *) b)->path, sizeof(sc_path_t)); -+} -+ -+/* For SimCList autocopy, we need to know the size of the data elements */ -+static size_t cac_list_meter(const void *el) { -+ return sizeof(cac_object_t); -+} -+ -+cac_private_data_t *cac_new_private_data(void) -+{ -+ cac_private_data_t *priv; -+ priv = calloc(1, sizeof(cac_private_data_t)); -+ if (!priv) -+ return NULL; -+ list_init(&priv->pki_list); -+ list_attributes_comparator(&priv->pki_list, cac_list_compare_path); -+ list_attributes_copy(&priv->pki_list, cac_list_meter, 1); -+ list_init(&priv->general_list); -+ list_attributes_comparator(&priv->general_list, cac_list_compare_path); -+ list_attributes_copy(&priv->general_list, cac_list_meter, 1); -+ /* set other fields as appropriate */ -+ -+ return priv; -+} -+ -+void cac_free_private_data(cac_private_data_t *priv) -+{ -+ free(priv->cac_id); -+ free(priv->cache_buf); -+ free(priv->aca_path); -+ list_destroy(&priv->pki_list); -+ list_destroy(&priv->general_list); -+ free(priv); -+ return; -+} -+ -+int cac_add_object_to_list(list_t *list, const cac_object_t *object) -+{ -+ if (list_append(list, object) < 0) -+ return SC_ERROR_UNKNOWN; -+ return SC_SUCCESS; -+} -+ -diff --git a/src/libopensc/card-cac-common.h b/src/libopensc/card-cac-common.h -new file mode 100644 -index 00000000..77f14761 ---- /dev/null -+++ b/src/libopensc/card-cac-common.h -@@ -0,0 +1,89 @@ -+/* -+ * card-cac-common.h: Code shared among CAC1 and CAC2 drivers -+ * -+ * Copyright (C) 2018, Red Hat, Inc. -+ * -+ * Author: Jakub Jelen -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef HAVE_CARD_CAC_COMMON_H -+#define HAVE_CARD_CAC_COMMON_H -+ -+#define CAC_MAX_SIZE 4096 /* arbitrary, just needs to be 'large enough' */ -+ -+typedef struct cac_cuid { -+ u8 gsc_rid[5]; -+ u8 manufacturer_id; -+ u8 card_type; -+ u8 card_id; -+} cac_cuid_t; -+ -+/* data structures to store meta data about CAC objects */ -+typedef struct cac_object { -+ const char *name; -+ int fd; -+ sc_path_t path; -+} cac_object_t; -+ -+/* -+ * CAC private data per card state -+ */ -+typedef struct cac_private_data { -+ int object_type; /* select set this so we know how to read the file */ -+ int cert_next; /* index number for the next certificate found in the list */ -+ u8 *cache_buf; /* cached version of the currently selected file */ -+ size_t cache_buf_len; /* length of the cached selected file */ -+ int cached; /* is the cached selected file valid */ -+ cac_cuid_t cuid; /* card unique ID from the CCC */ -+ u8 *cac_id; /* card serial number */ -+ size_t cac_id_len; /* card serial number len */ -+ list_t pki_list; /* list of pki containers */ -+ cac_object_t *pki_current; /* current pki object _ctl function */ -+ list_t general_list; /* list of general containers */ -+ cac_object_t *general_current; /* current object for _ctl function */ -+ sc_path_t *aca_path; /* ACA path to be selected before pin verification */ -+} cac_private_data_t; -+ -+#define CAC_DATA(card) ((cac_private_data_t*)card->drv_data) -+ -+/* -+ * Set up the normal CAC paths -+ */ -+#define CAC_1_RID "\xA0\x00\x00\x00\x79" -+#define CAC_TO_AID(x) x, sizeof(x)-1 -+ -+ -+#define MAX_CAC_SLOTS 16 /* Maximum number of slots is 16 now */ -+ -+/* template for a CAC pki object */ -+static const cac_object_t cac_cac_pki_obj = { -+ "CAC Certificate", 0x0, { { 0 }, 0, 0, 0, SC_PATH_TYPE_DF_NAME, -+ { CAC_TO_AID(CAC_1_RID "\x01\x00") } } -+}; -+ -+/* template for emulated cuid */ -+static const cac_cuid_t cac_cac_cuid = { -+ { 0xa0, 0x00, 0x00, 0x00, 0x79 }, -+ 2, 2, 0 -+}; -+ -+cac_private_data_t *cac_new_private_data(void); -+void cac_free_private_data(cac_private_data_t *priv); -+int cac_add_object_to_list(list_t *list, const cac_object_t *object); -+const char *get_cac_label(int index); -+ -+#endif /* HAVE_CARD_CAC_COMMON_H */ -diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c -index bd4e0336..f9620009 100644 ---- a/src/libopensc/card-cac.c -+++ b/src/libopensc/card-cac.c -@@ -58,8 +58,8 @@ - #include "compression.h" - #endif - #include "iso7816.h" -+#include "card-cac-common.h" - --#define CAC_MAX_SIZE 4096 /* arbitrary, just needs to be 'large enough' */ - /* - * CAC hardware and APDU constants - */ -@@ -147,20 +147,6 @@ typedef struct cac_card_url { - u8 keyCryptoAlgorithm; /* not used for VM cards */ - } cac_card_url_t; - --typedef struct cac_cuid { -- u8 gsc_rid[5]; -- u8 manufacturer_id; -- u8 card_type; -- u8 card_id; --} cac_cuid_t; -- --/* data structures to store meta data about CAC objects */ --typedef struct cac_object { -- const char *name; -- int fd; -- sc_path_t path; --} cac_object_t; -- - #define CAC_MAX_OBJECTS 16 - - typedef struct { -@@ -190,82 +176,10 @@ typedef struct { - #define CAC_OBJECT_TYPE_TLV_FILE 4 - #define CAC_OBJECT_TYPE_GENERIC 5 - --/* -- * CAC private data per card state -- */ --typedef struct cac_private_data { -- int object_type; /* select set this so we know how to read the file */ -- int cert_next; /* index number for the next certificate found in the list */ -- u8 *cache_buf; /* cached version of the currently selected file */ -- size_t cache_buf_len; /* length of the cached selected file */ -- int cached; /* is the cached selected file valid */ -- cac_cuid_t cuid; /* card unique ID from the CCC */ -- u8 *cac_id; /* card serial number */ -- size_t cac_id_len; /* card serial number len */ -- list_t pki_list; /* list of pki containers */ -- cac_object_t *pki_current; /* current pki object _ctl function */ -- list_t general_list; /* list of general containers */ -- cac_object_t *general_current; /* current object for _ctl function */ -- sc_path_t *aca_path; /* ACA path to be selected before pin verification */ --} cac_private_data_t; -- --#define CAC_DATA(card) ((cac_private_data_t*)card->drv_data) -- --static int cac_list_compare_path(const void *a, const void *b) --{ -- if (a == NULL || b == NULL) -- return 1; -- return memcmp( &((cac_object_t *) a)->path, -- &((cac_object_t *) b)->path, sizeof(sc_path_t)); --} -- --/* For SimCList autocopy, we need to know the size of the data elements */ --static size_t cac_list_meter(const void *el) { -- return sizeof(cac_object_t); --} -- --static cac_private_data_t *cac_new_private_data(void) --{ -- cac_private_data_t *priv; -- priv = calloc(1, sizeof(cac_private_data_t)); -- if (!priv) -- return NULL; -- list_init(&priv->pki_list); -- list_attributes_comparator(&priv->pki_list, cac_list_compare_path); -- list_attributes_copy(&priv->pki_list, cac_list_meter, 1); -- list_init(&priv->general_list); -- list_attributes_comparator(&priv->general_list, cac_list_compare_path); -- list_attributes_copy(&priv->general_list, cac_list_meter, 1); -- /* set other fields as appropriate */ -- -- return priv; --} -- --static void cac_free_private_data(cac_private_data_t *priv) --{ -- free(priv->cac_id); -- free(priv->cache_buf); -- free(priv->aca_path); -- list_destroy(&priv->pki_list); -- list_destroy(&priv->general_list); -- free(priv); -- return; --} -- --static int cac_add_object_to_list(list_t *list, const cac_object_t *object) --{ -- if (list_append(list, object) < 0) -- return SC_ERROR_UNKNOWN; -- return SC_SUCCESS; --} -- - /* - * Set up the normal CAC paths - */ --#define CAC_TO_AID(x) x, sizeof(x)-1 -- - #define CAC_2_RID "\xA0\x00\x00\x01\x16" --#define CAC_1_RID "\xA0\x00\x00\x00\x79" - - static const sc_path_t cac_ACA_Path = { - "", 0, -@@ -279,39 +193,6 @@ static const sc_path_t cac_CCC_Path = { - { CAC_TO_AID(CAC_2_RID "\xDB\x00") } - }; - --#define MAX_CAC_SLOTS 16 /* Maximum number of slots is 16 now */ --/* default certificate labels for the CAC card */ --static const char *cac_labels[MAX_CAC_SLOTS] = { -- "CAC ID Certificate", -- "CAC Email Signature Certificate", -- "CAC Email Encryption Certificate", -- "CAC Cert 4", -- "CAC Cert 5", -- "CAC Cert 6", -- "CAC Cert 7", -- "CAC Cert 8", -- "CAC Cert 9", -- "CAC Cert 10", -- "CAC Cert 11", -- "CAC Cert 12", -- "CAC Cert 13", -- "CAC Cert 14", -- "CAC Cert 15", -- "CAC Cert 16" --}; -- --/* template for a CAC pki object */ --static const cac_object_t cac_cac_pki_obj = { -- "CAC Certificate", 0x0, { { 0 }, 0, 0, 0, SC_PATH_TYPE_DF_NAME, -- { CAC_TO_AID(CAC_1_RID "\x01\x00") } } --}; -- --/* template for emulated cuid */ --static const cac_cuid_t cac_cac_cuid = { -- { 0xa0, 0x00, 0x00, 0x00, 0x79 }, -- 2, 2, 0 --}; -- - /* - * CAC general objects defined in 4.3.1.2 of CAC Applet Developer Guide Version 1.0. - * doubles as a source for CAC-2 labels. -@@ -1178,7 +1059,7 @@ static int cac_get_properties(sc_card_t *card, cac_properties_t *prop) - * - * The rest is just copied from iso7816_select_file - */ --static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out, int type) -+static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out) - { - struct sc_context *ctx; - struct sc_apdu apdu; -@@ -1356,7 +1237,7 @@ static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc - - static int cac_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out) - { -- return cac_select_file_by_type(card, in_path, file_out, card->type); -+ return cac_select_file_by_type(card, in_path, file_out); - } - - static int cac_finish(sc_card_t *card) -@@ -1374,13 +1255,13 @@ static int cac_finish(sc_card_t *card) - /* select the Card Capabilities Container on CAC-2 */ - static int cac_select_CCC(sc_card_t *card) - { -- return cac_select_file_by_type(card, &cac_CCC_Path, NULL, SC_CARD_TYPE_CAC_II); -+ return cac_select_file_by_type(card, &cac_CCC_Path, NULL); - } - - /* Select ACA in non-standard location */ - static int cac_select_ACA(sc_card_t *card) - { -- return cac_select_file_by_type(card, &cac_ACA_Path, NULL, SC_CARD_TYPE_CAC_II); -+ return cac_select_file_by_type(card, &cac_ACA_Path, NULL); - } - - static int cac_path_from_cardurl(sc_card_t *card, sc_path_t *path, cac_card_url_t *val, int len) -@@ -1432,7 +1313,7 @@ static int cac_parse_aid(sc_card_t *card, cac_private_data_t *priv, u8 *aid, int - /* Call without OID set will just select the AID without subseqent - * OID selection, which we need to figure out just now - */ -- cac_select_file_by_type(card, &new_object.path, NULL, SC_CARD_TYPE_CAC_II); -+ cac_select_file_by_type(card, &new_object.path, NULL); - r = cac_get_properties(card, &prop); - if (r < 0) - return SC_ERROR_INTERNAL; -@@ -1444,7 +1325,7 @@ static int cac_parse_aid(sc_card_t *card, cac_private_data_t *priv, u8 *aid, int - - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, - "ACA: pki_object found, cert_next=%d (%s), privkey=%d", -- priv->cert_next, cac_labels[priv->cert_next], -+ priv->cert_next, get_cac_label(priv->cert_next), - prop.objects[i].privatekey); - - /* If the private key is not initialized, we can safely -@@ -1460,7 +1341,7 @@ static int cac_parse_aid(sc_card_t *card, cac_private_data_t *priv, u8 *aid, int - memcpy(new_object.path.value, &prop.objects[i].oid, 2); - new_object.path.len = 2; - new_object.path.type = SC_PATH_TYPE_FILE_ID; -- new_object.name = cac_labels[priv->cert_next]; -+ new_object.name = get_cac_label(priv->cert_next); - new_object.fd = priv->cert_next+1; - cac_add_object_to_list(&priv->pki_list, &new_object); - priv->cert_next++; -@@ -1488,7 +1369,7 @@ static int cac_parse_cardurl(sc_card_t *card, cac_private_data_t *priv, cac_card - */ - if (priv->cert_next >= MAX_CAC_SLOTS) - break; /* don't fail just because we have more certs than we can support */ -- new_object.name = cac_labels[priv->cert_next]; -+ new_object.name = get_cac_label(priv->cert_next); - new_object.fd = priv->cert_next+1; - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"CARDURL: pki_object found, cert_next=%d (%s),", priv->cert_next, new_object.name); - cac_add_object_to_list(&priv->pki_list, &new_object); -@@ -1629,7 +1510,7 @@ static int cac_parse_CCC(sc_card_t *card, cac_private_data_t *priv, u8 *tl, - if (r < 0) - return r; - -- r = cac_select_file_by_type(card, &new_path, NULL, SC_CARD_TYPE_CAC_II); -+ r = cac_select_file_by_type(card, &new_path, NULL); - if (r < 0) - return r; - -@@ -1740,7 +1621,7 @@ static int cac_select_pki_applet(sc_card_t *card, int index) - { - sc_path_t applet_path = cac_cac_pki_obj.path; - applet_path.aid.value[applet_path.aid.len-1] = index; -- return cac_select_file_by_type(card, &applet_path, NULL, SC_CARD_TYPE_CAC_II); -+ return cac_select_file_by_type(card, &applet_path, NULL); - } - - /* -@@ -1785,7 +1666,7 @@ static int cac_populate_cac_alt(sc_card_t *card, int index, cac_private_data_t * - for (i = index; i < MAX_CAC_SLOTS; i++) { - r = cac_select_pki_applet(card, i); - if (r == SC_SUCCESS) { -- pki_obj.name = cac_labels[i]; -+ pki_obj.name = get_cac_label(i); - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, - "CAC: pki_object found, cert_next=%d (%s),", i, pki_obj.name); - pki_obj.path.aid.value[pki_obj.path.aid.len-1] = i; -@@ -1796,8 +1677,7 @@ static int cac_populate_cac_alt(sc_card_t *card, int index, cac_private_data_t * - - /* populate non-PKI objects */ - for (i=0; i < cac_object_count; i++) { -- r = cac_select_file_by_type(card, &cac_objects[i].path, NULL, -- SC_CARD_TYPE_CAC_II); -+ r = cac_select_file_by_type(card, &cac_objects[i].path, NULL); - if (r == SC_SUCCESS) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, - "CAC: obj_object found, cert_next=%d (%s),", -diff --git a/src/libopensc/card-cac1.c b/src/libopensc/card-cac1.c -new file mode 100644 -index 00000000..f3a16547 ---- /dev/null -+++ b/src/libopensc/card-cac1.c -@@ -0,0 +1,563 @@ -+/* -+ * card-cac1.c: Support for legacy CAC-1 -+ * card-default.c: Support for cards with no driver -+ * -+ * Copyright (C) 2001, 2002 Juha Yrjölä -+ * Copyright (C) 2005,2006,2007,2008,2009,2010 Douglas E. Engert -+ * Copyright (C) 2006, Identity Alliance, Thomas Harning -+ * Copyright (C) 2007, EMC, Russell Larner -+ * Copyright (C) 2016 - 2018, Red Hat, Inc. -+ * -+ * CAC driver author: Robert Relyea -+ * Further work: Jakub Jelen -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#if HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef _WIN32 -+#include -+#else -+#include -+#endif -+ -+#ifdef ENABLE_OPENSSL -+ /* openssl only needed for card administration */ -+#include -+#include -+#include -+#include -+#include -+#endif /* ENABLE_OPENSSL */ -+ -+#include "internal.h" -+#include "simpletlv.h" -+#include "cardctl.h" -+#ifdef ENABLE_ZLIB -+#include "compression.h" -+#endif -+#include "iso7816.h" -+#include "card-cac-common.h" -+ -+/* -+ * CAC hardware and APDU constants -+ */ -+#define CAC_INS_GET_CERTIFICATE 0x36 /* CAC1 command to read a certificate */ -+ -+/* -+ * OLD cac read certificate, only use with CAC-1 card. -+ */ -+static int cac_cac1_get_certificate(sc_card_t *card, u8 **out_buf, size_t *out_len) -+{ -+ u8 buf[CAC_MAX_SIZE]; -+ u8 *out_ptr; -+ size_t size = 0; -+ size_t left = 0; -+ size_t len, next_len; -+ sc_apdu_t apdu; -+ int r = SC_SUCCESS; -+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); -+ /* get the size */ -+ size = left = *out_buf ? *out_len : sizeof(buf); -+ out_ptr = *out_buf ? *out_buf : buf; -+ sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, CAC_INS_GET_CERTIFICATE, 0, 0 ); -+ next_len = MIN(left, 100); -+ for (; left > 0; left -= len, out_ptr += len) { -+ len = next_len; -+ apdu.resp = out_ptr; -+ apdu.le = len; -+ apdu.resplen = left; -+ r = sc_transmit_apdu(card, &apdu); -+ if (r < 0) { -+ break; -+ } -+ if (apdu.resplen == 0) { -+ r = SC_ERROR_INTERNAL; -+ break; -+ } -+ /* in the old CAC-1, 0x63 means 'more data' in addition to 'pin failed' */ -+ if (apdu.sw1 != 0x63) { -+ /* we've either finished reading, or hit an error, break */ -+ r = sc_check_sw(card, apdu.sw1, apdu.sw2); -+ left -= len; -+ break; -+ } -+ next_len = MIN(left, apdu.sw2); -+ } -+ if (r < 0) { -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); -+ } -+ r = size - left; -+ if (*out_buf == NULL) { -+ *out_buf = malloc(r); -+ if (*out_buf == NULL) { -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, -+ SC_ERROR_OUT_OF_MEMORY); -+ } -+ memcpy(*out_buf, buf, r); -+ } -+ *out_len = r; -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); -+} -+ -+/* -+ * Callers of this may be expecting a certificate, -+ * select file will have saved the object type for us -+ * as well as set that we want the cert from the object. -+ */ -+static int cac_read_binary(sc_card_t *card, unsigned int idx, -+ unsigned char *buf, size_t count, unsigned long flags) -+{ -+ cac_private_data_t * priv = CAC_DATA(card); -+ int r = 0; -+ u8 *val = NULL; -+ u8 *cert_ptr; -+ size_t val_len; -+ size_t len, cert_len; -+ u8 cert_type; -+ -+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); -+ -+ /* if we didn't return it all last time, return the remainder */ -+ if (priv->cached) { -+ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, -+ "returning cached value idx=%d count=%"SC_FORMAT_LEN_SIZE_T"u", -+ idx, count); -+ if (idx > priv->cache_buf_len) { -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_END_REACHED); -+ } -+ len = MIN(count, priv->cache_buf_len-idx); -+ memcpy(buf, &priv->cache_buf[idx], len); -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, len); -+ } -+ -+ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, -+ "clearing cache idx=%d count=%"SC_FORMAT_LEN_SIZE_T"u", -+ idx, count); -+ if (priv->cache_buf) { -+ free(priv->cache_buf); -+ priv->cache_buf = NULL; -+ priv->cache_buf_len = 0; -+ } -+ -+ r = cac_cac1_get_certificate(card, &val, &val_len); -+ if (r < 0) -+ goto done; -+ -+ cert_type = val[0]; -+ cert_ptr = val + 1; -+ cert_len = val_len - 1; -+ -+ /* if the info byte is 1, then the cert is compressed, decompress it */ -+ if ((cert_type & 0x3) == 1) { -+#ifdef ENABLE_ZLIB -+ r = sc_decompress_alloc(&priv->cache_buf, &priv->cache_buf_len, -+ cert_ptr, cert_len, COMPRESSION_AUTO); -+#else -+ sc_log(card->ctx, "CAC compression not supported, no zlib"); -+ r = SC_ERROR_NOT_SUPPORTED; -+#endif -+ if (r) -+ goto done; -+ cert_ptr = val; -+ } else if (cert_len > 0) { -+ priv->cache_buf = malloc(cert_len); -+ if (priv->cache_buf == NULL) { -+ r = SC_ERROR_OUT_OF_MEMORY; -+ goto done; -+ } -+ priv->cache_buf_len = cert_len; -+ memcpy(priv->cache_buf, cert_ptr, cert_len); -+ } -+ -+ /* OK we've read the data, now copy the required portion out to the callers buffer */ -+ priv->cached = 1; -+ len = MIN(count, priv->cache_buf_len-idx); -+ memcpy(buf, &priv->cache_buf[idx], len); -+ r = len; -+done: -+ if (val) -+ free(val); -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); -+} -+ -+/* -+ * CAC cards use SC_PATH_SELECT_OBJECT_ID rather than SC_PATH_SELECT_FILE_ID. In order to use more -+ * of the PKCS #15 structure, we call the selection SC_PATH_SELECT_FILE_ID, but we set p1 to 2 instead -+ * of 0. Also cac1 does not do any FCI, but it doesn't understand not selecting it. It returns invalid INS -+ * if it doesn't like anything about the select, so we always 'request' FCI for CAC1 -+ * -+ * The rest is just copied from iso7816_select_file -+ */ -+static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out) -+{ -+ struct sc_context *ctx; -+ struct sc_apdu apdu; -+ unsigned char buf[SC_MAX_APDU_BUFFER_SIZE]; -+ unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf; -+ int r, pathlen, pathtype; -+ struct sc_file *file = NULL; -+ cac_private_data_t * priv = CAC_DATA(card); -+ -+ assert(card != NULL && in_path != NULL); -+ ctx = card->ctx; -+ -+ SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); -+ -+ memcpy(path, in_path->value, in_path->len); -+ pathlen = in_path->len; -+ pathtype = in_path->type; -+ -+ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, -+ "path->aid=%x %x %x %x %x %x %x len=%"SC_FORMAT_LEN_SIZE_T"u, path->value = %x %x %x %x len=%"SC_FORMAT_LEN_SIZE_T"u path->type=%d (%x)", -+ in_path->aid.value[0], in_path->aid.value[1], -+ in_path->aid.value[2], in_path->aid.value[3], -+ in_path->aid.value[4], in_path->aid.value[5], -+ in_path->aid.value[6], in_path->aid.len, in_path->value[0], -+ in_path->value[1], in_path->value[2], in_path->value[3], -+ in_path->len, in_path->type, in_path->type); -+ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "file_out=%p index=%d count=%d\n", -+ file_out, in_path->index, in_path->count); -+ -+ /* Sigh, sc_key_select expects paths to keys to have specific formats. There is no override. -+ * we have to add some bytes to the path to make it happy. A better fix would be to give sc_key_file -+ * a flag that says 'no, really this path is fine'. We only need to do this for private keys */ -+ if ((pathlen > 2) && (pathlen <= 4) && memcmp(path, "\x3F\x00", 2) == 0) { -+ if (pathlen > 2) { -+ path += 2; -+ pathlen -= 2; -+ } -+ } -+ -+ -+ /* CAC has multiple different type of objects that aren't PKCS #15. When we read -+ * them we need convert them to something PKCS #15 would understand. Find the object -+ * and object type here: -+ */ -+ if (priv) { /* don't record anything if we haven't been initialized yet */ -+ /* forget any old cached values */ -+ if (priv->cache_buf) { -+ free(priv->cache_buf); -+ priv->cache_buf = NULL; -+ } -+ priv->cache_buf_len = 0; -+ priv->cached = 0; -+ } -+ -+ if (in_path->aid.len) { -+ if (!pathlen) { -+ memcpy(path, in_path->aid.value, in_path->aid.len); -+ pathlen = in_path->aid.len; -+ pathtype = SC_PATH_TYPE_DF_NAME; -+ } else { -+ /* First, select the application */ -+ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"select application" ); -+ sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0); -+ apdu.data = in_path->aid.value; -+ apdu.datalen = in_path->aid.len; -+ apdu.lc = in_path->aid.len; -+ -+ r = sc_transmit_apdu(card, &apdu); -+ LOG_TEST_RET(ctx, r, "APDU transmit failed"); -+ r = sc_check_sw(card, apdu.sw1, apdu.sw2); -+ if (r) -+ LOG_FUNC_RETURN(ctx, r); -+ -+ } -+ } -+ -+ sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0); -+ -+ switch (pathtype) { -+ /* ideally we would had SC_PATH_TYPE_OBJECT_ID and add code to the iso7816 select. -+ * Unfortunately we'd also need to update the caching code as well. For now just -+ * use FILE_ID and change p1 here */ -+ case SC_PATH_TYPE_FILE_ID: -+ apdu.p1 = 2; -+ if (pathlen != 2) -+ return SC_ERROR_INVALID_ARGUMENTS; -+ break; -+ case SC_PATH_TYPE_DF_NAME: -+ apdu.p1 = 4; -+ break; -+ default: -+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); -+ } -+ apdu.lc = pathlen; -+ apdu.data = path; -+ apdu.datalen = pathlen; -+ apdu.resp = buf; -+ apdu.resplen = sizeof(buf); -+ apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256; -+ apdu.p2 = 0x00; -+ -+ r = sc_transmit_apdu(card, &apdu); -+ LOG_TEST_RET(ctx, r, "APDU transmit failed"); -+ -+ if (file_out == NULL) { -+ /* For some cards 'SELECT' can be only with request to return FCI/FCP. */ -+ r = sc_check_sw(card, apdu.sw1, apdu.sw2); -+ if (apdu.sw1 == 0x6A && apdu.sw2 == 0x86) { -+ apdu.p2 = 0x00; -+ apdu.resplen = sizeof(buf); -+ if (sc_transmit_apdu(card, &apdu) == SC_SUCCESS) -+ r = sc_check_sw(card, apdu.sw1, apdu.sw2); -+ } -+ if (apdu.sw1 == 0x61) -+ LOG_FUNC_RETURN(ctx, SC_SUCCESS); -+ LOG_FUNC_RETURN(ctx, r); -+ } -+ -+ r = sc_check_sw(card, apdu.sw1, apdu.sw2); -+ if (r) -+ LOG_FUNC_RETURN(ctx, r); -+ -+ /* CAC cards never return FCI, fake one */ -+ file = sc_file_new(); -+ if (file == NULL) -+ LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); -+ file->path = *in_path; -+ file->size = CAC_MAX_SIZE; /* we don't know how big, just give a large size until we can read the file */ -+ -+ *file_out = file; -+ SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); -+ -+} -+ -+static int cac_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out) -+{ -+ return cac_select_file_by_type(card, in_path, file_out); -+} -+ -+static int cac_finish(sc_card_t *card) -+{ -+ cac_private_data_t * priv = CAC_DATA(card); -+ -+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); -+ if (priv) { -+ cac_free_private_data(priv); -+ } -+ return SC_SUCCESS; -+} -+ -+ -+/* select a CAC pki applet by index */ -+static int cac_select_pki_applet(sc_card_t *card, int index) -+{ -+ sc_path_t applet_path = cac_cac_pki_obj.path; -+ applet_path.aid.value[applet_path.aid.len-1] = index; -+ return cac_select_file_by_type(card, &applet_path, NULL); -+} -+ -+/* -+ * Find the first existing CAC applet. If none found, then this isn't a CAC -+ */ -+static int cac_find_first_pki_applet(sc_card_t *card, int *index_out) -+{ -+ int r, i; -+ -+ for (i = 0; i < MAX_CAC_SLOTS; i++) { -+ r = cac_select_pki_applet(card, i); -+ if (r == SC_SUCCESS) { -+ u8 data[2]; -+ sc_apdu_t apdu; -+ -+ /* Try to read first two bytes of the buffer to -+ * make sure it is not just malfunctioning card -+ */ -+ sc_format_apdu(card, &apdu, SC_APDU_CASE_2, -+ CAC_INS_GET_CERTIFICATE, 0x00, 0x00); -+ apdu.le = 0x02; -+ apdu.resplen = 2; -+ apdu.resp = data; -+ r = sc_transmit_apdu(card, &apdu); -+ /* SW1 = 0x63 means more data in CAC1 */ -+ if (r == SC_SUCCESS && apdu.sw1 != 0x63) -+ continue; -+ -+ *index_out = i; -+ return SC_SUCCESS; -+ } -+ } -+ return SC_ERROR_OBJECT_NOT_FOUND; -+} -+ -+static int cac_populate_cac1(sc_card_t *card, int index, cac_private_data_t *priv) -+{ -+ int r, i; -+ cac_object_t pki_obj = cac_cac_pki_obj; -+ u8 buf[100]; -+ u8 *val; -+ size_t val_len; -+ -+ /* populate PKI objects */ -+ for (i = index; i < MAX_CAC_SLOTS; i++) { -+ r = cac_select_pki_applet(card, i); -+ if (r == SC_SUCCESS) { -+ pki_obj.name = get_cac_label(i); -+ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, -+ "CAC: pki_object found, cert_next=%d (%s),", i, pki_obj.name); -+ pki_obj.path.aid.value[pki_obj.path.aid.len-1] = i; -+ pki_obj.fd = i+1; /* don't use id of zero */ -+ cac_add_object_to_list(&priv->pki_list, &pki_obj); -+ } -+ } -+ -+ /* -+ * create a cuid to simulate the cac 2 cuid. -+ */ -+ priv->cuid = cac_cac_cuid; -+ /* create a serial number by hashing the first 100 bytes of the -+ * first certificate on the card */ -+ r = cac_select_pki_applet(card, index); -+ if (r < 0) { -+ return r; /* shouldn't happen unless the card has been removed or is malfunctioning */ -+ } -+ val = buf; -+ val_len = sizeof(buf); -+ r = cac_cac1_get_certificate(card, &val, &val_len); -+ if (r >= 0) { -+ priv->cac_id = malloc(20); -+ if (priv->cac_id == NULL) { -+ return SC_ERROR_OUT_OF_MEMORY; -+ } -+#ifdef ENABLE_OPENSSL -+ SHA1(val, val_len, priv->cac_id); -+ priv->cac_id_len = 20; -+ sc_debug_hex(card->ctx, SC_LOG_DEBUG_VERBOSE, -+ "cuid", priv->cac_id, priv->cac_id_len); -+#else -+ sc_log(card->ctx, "OpenSSL Required"); -+ return SC_ERROR_NOT_SUPPORTED; -+#endif /* ENABLE_OPENSSL */ -+ } -+ return SC_SUCCESS; -+} -+ -+/* -+ * Look for a CAC card. If it exists, initialize our data structures -+ */ -+static int cac_find_and_initialize(sc_card_t *card, int initialize) -+{ -+ int r, index; -+ cac_private_data_t *priv = NULL; -+ -+ /* already initialized? */ -+ if (card->drv_data) { -+ return SC_SUCCESS; -+ } -+ -+ /* is this a CAC Alt token without any accompanying structures */ -+ r = cac_find_first_pki_applet(card, &index); -+ if (r == SC_SUCCESS) { -+ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "PKI applet found, is bare CAC-1"); -+ if (!initialize) /* match card only */ -+ return r; -+ -+ if (!priv) { -+ priv = cac_new_private_data(); -+ if (!priv) -+ return SC_ERROR_OUT_OF_MEMORY; -+ } -+ card->drv_data = priv; /* needed for the read_binary() */ -+ r = cac_populate_cac1(card, index, priv); -+ if (r == SC_SUCCESS) { -+ card->type = SC_CARD_TYPE_CAC_I; -+ return r; -+ } -+ card->drv_data = NULL; /* reset on failure */ -+ } -+ if (priv) { -+ cac_free_private_data(priv); -+ } -+ return r; -+} -+ -+ -+/* NOTE: returns a bool, 1 card matches, 0 it does not */ -+static int cac_match_card(sc_card_t *card) -+{ -+ int r; -+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); -+ /* Since we send an APDU, the card's logout function may be called... -+ * however it may be in dirty memory */ -+ card->ops->logout = NULL; -+ -+ r = cac_find_and_initialize(card, 0); -+ return (r == SC_SUCCESS); /* never match */ -+} -+ -+ -+static int cac_init(sc_card_t *card) -+{ -+ int r; -+ unsigned long flags; -+ -+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); -+ -+ r = cac_find_and_initialize(card, 1); -+ if (r < 0) { -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_CARD); -+ } -+ flags = SC_ALGORITHM_RSA_RAW; -+ -+ _sc_card_add_rsa_alg(card, 1024, flags, 0); /* mandatory */ -+ _sc_card_add_rsa_alg(card, 2048, flags, 0); /* optional */ -+ _sc_card_add_rsa_alg(card, 3072, flags, 0); /* optional */ -+ -+ card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO; -+ -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); -+} -+ -+static struct sc_card_operations cac_ops; -+ -+static struct sc_card_driver cac1_drv = { -+ "Common Access Card (CAC 1)", -+ "cac1", -+ &cac_ops, -+ NULL, 0, NULL -+}; -+ -+static struct sc_card_driver * sc_get_driver(void) -+{ -+ /* Inherit most of the things from the CAC driver */ -+ struct sc_card_driver *cac_drv = sc_get_cac_driver(); -+ -+ cac_ops = *cac_drv->ops; -+ cac_ops.match_card = cac_match_card; -+ cac_ops.init = cac_init; -+ cac_ops.finish = cac_finish; -+ -+ cac_ops.select_file = cac_select_file; /* need to record object type */ -+ cac_ops.read_binary = cac_read_binary; -+ -+ return &cac1_drv; -+} -+ -+ -+struct sc_card_driver * sc_get_cac1_driver(void) -+{ -+ return sc_get_driver(); -+} -diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h -index 5d545b35..f4df17fb 100644 ---- a/src/libopensc/cards.h -+++ b/src/libopensc/cards.h -@@ -286,6 +286,7 @@ extern sc_card_driver_t *sc_get_gids_driver(void); - extern sc_card_driver_t *sc_get_jpki_driver(void); - extern sc_card_driver_t *sc_get_coolkey_driver(void); - extern sc_card_driver_t *sc_get_cac_driver(void); -+extern sc_card_driver_t *sc_get_cac1_driver(void); - extern sc_card_driver_t *sc_get_npa_driver(void); - - #ifdef __cplusplus -diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c -index 98e6038a..5b5d4996 100644 ---- a/src/libopensc/ctx.c -+++ b/src/libopensc/ctx.c -@@ -146,6 +146,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = { - { "openpgp", (void *(*)(void)) sc_get_openpgp_driver }, - { "jpki", (void *(*)(void)) sc_get_jpki_driver }, - { "npa", (void *(*)(void)) sc_get_npa_driver }, -+ { "cac1", (void *(*)(void)) sc_get_cac1_driver }, - /* The default driver should be last, as it handles all the - * unrecognized cards. */ - { "default", (void *(*)(void)) sc_get_default_driver }, diff --git a/SOURCES/opensc-0.19.0-coolkey-2k.patch b/SOURCES/opensc-0.19.0-coolkey-2k.patch deleted file mode 100644 index f4567cf..0000000 --- a/SOURCES/opensc-0.19.0-coolkey-2k.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 6c1b9094a6060d9d838bac9ea4f7c4c9e755c4ae Mon Sep 17 00:00:00 2001 -From: Steve Ross -Date: Wed, 14 Nov 2018 11:59:43 -0600 -Subject: [PATCH] Enable CoolKey driver to handle 2048-bit keys. - -For a problem description, see . -In a nutshell, for a card with the CoolKey applet and 2048-bit keys, -the command - pkcs11-tool --test --login -fails to complete all of its tests. - -This commit consists of a patch from @dengert. - -To avoid triggering an error when the data exceeds 255 bytes, this commit -limits the amount of the payload sent to the CoolKey applet on the card based -on the maximum amount of data that the card can receive, and overhead bytes -(namely, a header and nonce) that accompany the payload. - -With this change, the command - pkcs11-tool --test --login -succeeds. ---- - src/libopensc/card-coolkey.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c -index e320290dfe..11c4e92643 100644 ---- a/src/libopensc/card-coolkey.c -+++ b/src/libopensc/card-coolkey.c -@@ -1168,12 +1168,16 @@ static int coolkey_write_object(sc_card_t *card, unsigned long object_id, - size_t operation_len; - size_t left = buf_len; - int r; -+ size_t max_operation_len; -+ -+ /* set limit for the card's maximum send size and short write */ -+ max_operation_len = MIN(COOLKEY_MAX_CHUNK_SIZE, (card->max_send_size - sizeof(coolkey_read_object_param_t) - nonce_size)); - - ulong2bebytes(¶ms.head.object_id[0], object_id); - - do { - ulong2bebytes(¶ms.head.offset[0], offset); -- operation_len = MIN(left, COOLKEY_MAX_CHUNK_SIZE); -+ operation_len = MIN(left, max_operation_len); - params.head.length = operation_len; - memcpy(params.buf, buf, operation_len); - r = coolkey_apdu_io(card, COOLKEY_CLASS, COOLKEY_INS_WRITE_OBJECT, 0, 0, - diff --git a/SOURCES/opensc-0.19.0-coolkey-matching.patch b/SOURCES/opensc-0.19.0-coolkey-matching.patch deleted file mode 100644 index 2f00866..0000000 --- a/SOURCES/opensc-0.19.0-coolkey-matching.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 6691487cd7433b4ffc3a99124b5ecf92361b8a76 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 9 Oct 2018 15:10:36 +0200 -Subject: [PATCH 1/3] cac: These functions do not have to be exposed - ---- - src/libopensc/card-cac.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c -index eeab07e4f..bd4e03362 100644 ---- a/src/libopensc/card-cac.c -+++ b/src/libopensc/card-cac.c -@@ -211,7 +211,7 @@ typedef struct cac_private_data { - - #define CAC_DATA(card) ((cac_private_data_t*)card->drv_data) - --int cac_list_compare_path(const void *a, const void *b) -+static int cac_list_compare_path(const void *a, const void *b) - { - if (a == NULL || b == NULL) - return 1; -@@ -220,7 +220,7 @@ int cac_list_compare_path(const void *a, const void *b) - } - - /* For SimCList autocopy, we need to know the size of the data elements */ --size_t cac_list_meter(const void *el) { -+static size_t cac_list_meter(const void *el) { - return sizeof(cac_object_t); - } - - -From fab79b70ff45d02d99bc05863be57f8ca8f0acda Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 9 Oct 2018 15:58:12 +0200 -Subject: [PATCH 2/3] coolkey: Improve card matching to avoid mismatches in - muscle - ---- - src/libopensc/card-coolkey.c | 20 +++++++++++++++++++- - 1 file changed, 19 insertions(+), 1 deletion(-) - -diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c -index b97559cc3..2cf2362c8 100644 ---- a/src/libopensc/card-coolkey.c -+++ b/src/libopensc/card-coolkey.c -@@ -2224,14 +2224,32 @@ static int coolkey_initialize(sc_card_t *card) - /* NOTE: returns a bool, 1 card matches, 0 it does not */ - static int coolkey_match_card(sc_card_t *card) - { -+ sc_apdu_t apdu; - int r; -+ - SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); - /* Since we send an APDU, the card's logout function may be called... - * however it may be in dirty memory */ - card->ops->logout = NULL; - - r = coolkey_select_applet(card); -- return (r >= SC_SUCCESS); -+ if (r == SC_SUCCESS) { -+ /* The GET STATUS INS with P1 = 1 returns invalid instruction (0x6D00) -+ * on Coolkey applet (reserved for GetMemory function), -+ * while incorrect P1 (0x9C10) on Muscle applets -+ */ -+ sc_format_apdu(card, &apdu, SC_APDU_CASE_1, COOLKEY_INS_GET_STATUS, 0x01, 0x00); -+ apdu.cla = COOLKEY_CLASS; -+ apdu.le = 0x00; -+ apdu.resplen = 0; -+ apdu.resp = NULL; -+ r = sc_transmit_apdu(card, &apdu); -+ if (r == SC_SUCCESS && apdu.sw1 == 0x6d && apdu.sw2 == 0x00) { -+ return 1; -+ } -+ return 0; -+ } -+ return 0; - } - - - -From 98a1716768d11afd6d0e1e73bf8154dddfe915e9 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 9 Oct 2018 16:01:57 +0200 -Subject: [PATCH 3/3] ctx: Move coolkey driver up after improving the matching - -Fixes #1483 ---- - src/libopensc/ctx.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c -index f24a61ca0..98e6038a7 100644 ---- a/src/libopensc/ctx.c -+++ b/src/libopensc/ctx.c -@@ -128,6 +128,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = { - - /* Here should be placed drivers that need some APDU transactions in the - * driver's `match_card()` function. */ -+ { "coolkey", (void *(*)(void)) sc_get_coolkey_driver }, - /* MUSCLE card applet returns 9000 on whatever AID is selected, see - * https://github.com/JavaCardOS/MuscleCard-Applet/blob/master/musclecard/src/com/musclecard/CardEdge/CardEdge.java#L326 - * put the muscle driver first to cope with this bug. */ -@@ -144,7 +145,6 @@ static const struct _sc_driver_entry internal_card_drivers[] = { - #endif - { "openpgp", (void *(*)(void)) sc_get_openpgp_driver }, - { "jpki", (void *(*)(void)) sc_get_jpki_driver }, -- { "coolkey", (void *(*)(void)) sc_get_coolkey_driver }, - { "npa", (void *(*)(void)) sc_get_npa_driver }, - /* The default driver should be last, as it handles all the - * unrecognized cards. */ - diff --git a/SOURCES/opensc-0.19.0-coverity.patch b/SOURCES/opensc-0.19.0-coverity.patch deleted file mode 100644 index 12a6d4b..0000000 --- a/SOURCES/opensc-0.19.0-coverity.patch +++ /dev/null @@ -1,446 +0,0 @@ -diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c -index 49b593f9..299520d6 100644 ---- a/src/libopensc/card-epass2003.c -+++ b/src/libopensc/card-epass2003.c -@@ -1846,11 +1846,6 @@ epass2003_process_fci(struct sc_card *card, sc_file_t * file, const u8 * buf, si - case 0x04: - file->ef_structure = SC_FILE_EF_LINEAR_FIXED; - break; -- case 0x03: -- case 0x05: -- case 0x06: -- case 0x07: -- break; - default: - break; - } -diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c -index 254f8aa5..7eb3f5d0 100644 ---- a/src/libopensc/card-iasecc.c -+++ b/src/libopensc/card-iasecc.c -@@ -2406,7 +2406,11 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_ - sc_format_path("3F00", &path); - path.type = SC_PATH_TYPE_FILE_ID; - rv = iasecc_select_file(card, &path, NULL); -- LOG_TEST_RET(ctx, rv, "Unable to select MF"); -+ if (rv != SC_SUCCESS) { -+ sc_file_free(save_current); -+ sc_log(ctx, "Unable to select MF"); -+ LOG_FUNC_RETURN(ctx, rv); -+ } - } - - memset(&sdo, 0, sizeof(sdo)); -@@ -3478,9 +3482,12 @@ iasecc_get_free_reference(struct sc_card *card, struct iasecc_ctl_get_free_refer - - sc_log(ctx, "found empty key slot %i", idx); - break; -+ } else if (rv != SC_SUCCESS) { -+ iasecc_sdo_free(card, sdo); -+ -+ sc_log(ctx, "get new key reference failed"); -+ LOG_FUNC_RETURN(ctx, rv); - } -- else -- LOG_TEST_RET(ctx, rv, "get new key reference failed"); - - sz = *(sdo->docp.size.value + 0) * 0x100 + *(sdo->docp.size.value + 1); - sc_log(ctx, -diff --git a/src/libopensc/card-muscle.c b/src/libopensc/card-muscle.c -index c91b8d5e..be5b9f14 100644 ---- a/src/libopensc/card-muscle.c -+++ b/src/libopensc/card-muscle.c -@@ -455,6 +455,7 @@ static int _listFile(mscfs_file_t *file, int reset, void *udata) - static int muscle_init(sc_card_t *card) - { - muscle_private_t *priv; -+ int r; - - card->name = "MuscleApplet"; - card->drv_data = malloc(sizeof(muscle_private_t)); -@@ -478,7 +479,10 @@ static int muscle_init(sc_card_t *card) - card->caps |= SC_CARD_CAP_RNG; - - /* Card type detection */ -- _sc_match_atr(card, muscle_atrs, &card->type); -+ r = _sc_match_atr(card, muscle_atrs, &card->type); -+ if (r < 0) { -+ sc_log(card->ctx, "Failed to match the ATRs"); -+ } - if(card->type == SC_CARD_TYPE_MUSCLE_ETOKEN_72K) { - card->caps |= SC_CARD_CAP_APDU_EXT; - } -diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c -index 61acedc8..a678b768 100644 ---- a/src/libopensc/card-piv.c -+++ b/src/libopensc/card-piv.c -@@ -922,7 +922,11 @@ piv_get_data(sc_card_t * card, int enumtag, u8 **buf, size_t *buf_len) - SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); - sc_log(card->ctx, "#%d", enumtag); - -- sc_lock(card); /* do check len and get data in same transaction */ -+ r = sc_lock(card); /* do check len and get data in same transaction */ -+ if (r != SC_SUCCESS) { -+ sc_log(card->ctx, "sc_lock failed"); -+ return r; -+ } - - /* assert(enumtag >= 0 && enumtag < PIV_OBJ_LAST_ENUM); */ - -@@ -1481,7 +1485,7 @@ static int piv_get_key(sc_card_t *card, unsigned int alg_id, u8 **key, size_t *l - FILE *f = NULL; - char * keyfilename = NULL; - size_t expected_keylen; -- size_t keylen; -+ size_t keylen, readlen; - u8 * keybuf = NULL; - u8 * tkey = NULL; - -@@ -1530,11 +1534,12 @@ static int piv_get_key(sc_card_t *card, unsigned int alg_id, u8 **key, size_t *l - } - keybuf[fsize] = 0x00; /* in case it is text need null */ - -- if (fread(keybuf, 1, fsize, f) != fsize) { -+ if ((readlen = fread(keybuf, 1, fsize, f)) != fsize) { - sc_log(card->ctx, " Unable to read key\n"); - r = SC_ERROR_WRONG_LENGTH; - goto err; - } -+ keybuf[readlen] = '\0'; - - tkey = malloc(expected_keylen); - if (!tkey) { -@@ -2126,14 +2131,16 @@ piv_get_serial_nr_from_CHUI(sc_card_t* card, sc_serial_number_t* serial) - /* test if guid and the fascn starts with ;9999 (in ISO 4bit + parity code) */ - if (!(gbits && fascn[0] == 0xD4 && fascn[1] == 0xE7 - && fascn[2] == 0x39 && (fascn[3] | 0x7F) == 0xFF)) { -- serial->len = fascnlen < SC_MAX_SERIALNR ? fascnlen : SC_MAX_SERIALNR; -+ /* fascnlen is 25 */ -+ serial->len = fascnlen; - memcpy (serial->value, fascn, serial->len); - r = SC_SUCCESS; - gbits = 0; /* set to skip using guid below */ - } - } - if (guid && gbits) { -- serial->len = guidlen < SC_MAX_SERIALNR ? guidlen : SC_MAX_SERIALNR; -+ /* guidlen is 16 */ -+ serial->len = guidlen; - memcpy (serial->value, guid, serial->len); - r = SC_SUCCESS; - } -@@ -2981,7 +2988,7 @@ static int piv_match_card(sc_card_t *card) - - static int piv_match_card_continued(sc_card_t *card) - { -- int i; -+ int i, r; - int type = -1; - piv_private_data_t *priv = NULL; - int saved_type = card->type; -@@ -3080,7 +3087,13 @@ static int piv_match_card_continued(sc_card_t *card) - if(piv_objects[i].flags & PIV_OBJECT_NOT_PRESENT) - priv->obj_cache[i].flags |= PIV_OBJ_CACHE_NOT_PRESENT; - -- sc_lock(card); -+ r = sc_lock(card); -+ if (r != SC_SUCCESS) { -+ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "sc_lock failed\n"); -+ piv_finish(card); -+ card->type = saved_type; -+ return 0; -+ } - - /* - * detect if active AID is PIV. NIST 800-73 says Only one PIV application per card -@@ -3464,7 +3477,11 @@ piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) - if (data->cmd == SC_PIN_CMD_VERIFY && data->pin_type == SC_AC_CONTEXT_SPECIFIC) { - priv->context_specific = 1; - sc_log(card->ctx,"Starting CONTEXT_SPECIFIC verify"); -- sc_lock(card); -+ r = sc_lock(card); -+ if (r != SC_SUCCESS) { -+ sc_log(card->ctx, "sc_lock failed"); -+ return r; -+ } - } - - priv->pin_cmd_verify = 1; /* tell piv_check_sw its a verify to save sw1, sw2 */ -diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c -index 626686a7..f24a61ca 100644 ---- a/src/libopensc/ctx.c -+++ b/src/libopensc/ctx.c -@@ -452,6 +452,10 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name - const char *(*modversion)(void) = NULL; - const char *(**tmodv)(void) = &modversion; - -+ if (dll == NULL) { -+ sc_log(ctx, "No dll parameter specified"); -+ return NULL; -+ } - if (name == NULL) { /* should not occur, but... */ - sc_log(ctx, "No module specified"); - return NULL; -@@ -481,8 +485,8 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name - sc_dlclose(handle); - return NULL; - } -- if (dll) -- *dll = handle; -+ -+ *dll = handle; - sc_log(ctx, "successfully loaded card driver '%s'", name); - return modinit(name); - } -diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c -index 718d92ff..6abd2d76 100644 ---- a/src/libopensc/iso7816.c -+++ b/src/libopensc/iso7816.c -@@ -841,13 +841,18 @@ iso7816_set_security_env(struct sc_card *card, - if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) { - if (env->file_ref.len > 0xFF) - return SC_ERROR_INVALID_ARGUMENTS; -+ if (sizeof(sbuf) - (p - sbuf) < env->file_ref.len + 2) -+ return SC_ERROR_OFFSET_TOO_LARGE; -+ - *p++ = 0x81; - *p++ = (u8) env->file_ref.len; -- assert(sizeof(sbuf) - (p - sbuf) >= env->file_ref.len); - memcpy(p, env->file_ref.value, env->file_ref.len); - p += env->file_ref.len; - } - if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { -+ if (sizeof(sbuf) - (p - sbuf) < env->key_ref_len + 2) -+ return SC_ERROR_OFFSET_TOO_LARGE; -+ - if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC) - *p++ = 0x83; - else -@@ -855,7 +860,6 @@ iso7816_set_security_env(struct sc_card *card, - if (env->key_ref_len > 0xFF) - return SC_ERROR_INVALID_ARGUMENTS; - *p++ = env->key_ref_len & 0xFF; -- assert(sizeof(sbuf) - (p - sbuf) >= env->key_ref_len); - memcpy(p, env->key_ref, env->key_ref_len); - p += env->key_ref_len; - } -diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c -index 93032113..f34425a5 100644 ---- a/src/libopensc/pkcs15-cac.c -+++ b/src/libopensc/pkcs15-cac.c -@@ -388,6 +388,7 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) - if (r == SC_SUCCESS) { - token_name = malloc (cn_len+1); - if (!token_name) { -+ free(cn_name); - r = SC_ERROR_OUT_OF_MEMORY; - goto fail; - } -diff --git a/src/libopensc/pkcs15-oberthur.c b/src/libopensc/pkcs15-oberthur.c -index 3415be7c..8c126e46 100644 ---- a/src/libopensc/pkcs15-oberthur.c -+++ b/src/libopensc/pkcs15-oberthur.c -@@ -206,8 +206,10 @@ sc_oberthur_get_certificate_authority(struct sc_pkcs15_der *der, int *out_author - buf_mem.max = buf_mem.length = der->len; - - bio = BIO_new(BIO_s_mem()); -- if(!bio) -+ if (!bio) { -+ free(buf_mem.data); - return SC_ERROR_OUT_OF_MEMORY; -+ } - - BIO_set_mem_buf(bio, &buf_mem, BIO_NOCLOSE); - x = d2i_X509_bio(bio, 0); -diff --git a/src/pkcs15init/pkcs15-authentic.c b/src/pkcs15init/pkcs15-authentic.c -index ddccd032..0b6f9c17 100644 ---- a/src/pkcs15init/pkcs15-authentic.c -+++ b/src/pkcs15init/pkcs15-authentic.c -@@ -355,7 +355,6 @@ authentic_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card, - sc_file_free(file); - LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate 'sc_authentic_sdo'"); - } -- *out = sdo; - - sdo->magic = AUTHENTIC_SDO_MAGIC; - sdo->docp.id = key_info->key_reference & ~AUTHENTIC_OBJECT_REF_FLAG_LOCAL; -@@ -364,11 +363,16 @@ authentic_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card, - rv = authentic_docp_set_acls(card, file, authentic_v3_rsa_ac_ops, - sizeof(authentic_v3_rsa_ac_ops)/sizeof(authentic_v3_rsa_ac_ops[0]), &sdo->docp); - sc_file_free(file); -- LOG_TEST_RET(ctx, rv, "Cannot set key ACLs from file"); -+ if (rv != SC_SUCCESS) { -+ free(sdo); -+ sc_log(ctx, "Cannot set key ACLs from file"); -+ LOG_FUNC_RETURN(ctx, rv); -+ } - - sc_log(ctx, "sdo(mech:%X,id:%X,acls:%s)", sdo->docp.mech, sdo->docp.id, - sc_dump_hex(sdo->docp.acl_data, sdo->docp.acl_data_len)); - -+ *out = sdo; - LOG_FUNC_RETURN(ctx, SC_SUCCESS); - } - -diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c -index 29f9aa22..10258667 100644 ---- a/src/pkcs15init/pkcs15-myeid.c -+++ b/src/pkcs15init/pkcs15-myeid.c -@@ -232,6 +232,7 @@ myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df - for (ii = 0; create_dfs[ii]; ii++) { - sc_log(ctx, "Create '%s'", create_dfs[ii]); - -+ file = NULL; - r = sc_profile_get_file(profile, create_dfs[ii], &file); - sc_file_free(file); - if (r) { -@@ -433,7 +434,11 @@ _add_supported_algo(struct sc_profile *profile, struct sc_pkcs15_card *p15card, - unsigned operations, unsigned mechanism, const struct sc_object_id *oid) - { - struct sc_supported_algo_info *algo; -+ struct sc_context *ctx = p15card->card->ctx; - algo = sc_pkcs15_get_supported_algo(p15card, operations, mechanism); -+ int rv; -+ -+ LOG_FUNC_CALLED(ctx); - if (!algo) { - unsigned ref = 1, ii; - -@@ -451,7 +456,10 @@ _add_supported_algo(struct sc_profile *profile, struct sc_pkcs15_card *p15card, - } - - } -- sc_pkcs15_add_supported_algo_ref(object, algo); -+ rv = sc_pkcs15_add_supported_algo_ref(object, algo); -+ if (rv != SC_SUCCESS) { -+ sc_log(ctx, "Failed to add algorithms refs"); -+ } - } - - static void -@@ -742,7 +750,6 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, - break; - default: - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key type"); -- break; - } - - sc_log(ctx, "Generate key with ID:%s and path:%s", -diff --git a/src/pkcs15init/pkcs15-oberthur-awp.c b/src/pkcs15init/pkcs15-oberthur-awp.c -index f9c96373..9b12f06c 100644 ---- a/src/pkcs15init/pkcs15-oberthur-awp.c -+++ b/src/pkcs15init/pkcs15-oberthur-awp.c -@@ -284,9 +284,10 @@ awp_create_container_record (struct sc_pkcs15_card *p15card, struct sc_profile * - memset(buff, 0, list_file->record_length); - - rv = awp_new_container_entry(p15card, buff, list_file->record_length); -- if (rv < 0) { -+ if (rv < 0) { - free(buff); -- SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot create container"); -+ sc_log(ctx, "Cannot create container"); -+ SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); - } - - *(buff + 0) = (acc->pubkey_id >> 8) & 0xFF; -diff --git a/src/tools/npa-tool-cmdline.c b/src/tools/npa-tool-cmdline.c -index 117c6cb1..26eed929 100644 ---- a/src/tools/npa-tool-cmdline.c -+++ b/src/tools/npa-tool-cmdline.c -@@ -1685,7 +1685,14 @@ void update_multiple_arg(void *field, char ***orig_field, - struct generic_list *tmp; - - if (prev_given && list) { -+ char **old = *orig_field; -+ char *old_field = field; - *orig_field = (char **) realloc (*orig_field, (field_given + prev_given) * sizeof (char *)); -+ if (*orig_field == NULL) { -+ free(*old); -+ fprintf(stderr, "Failed to allocate memory: aborting"); -+ exit(1); -+ } - - switch(arg_type) { - case ARG_INT: -@@ -1695,6 +1702,11 @@ void update_multiple_arg(void *field, char ***orig_field, - default: - break; - }; -+ if (*((void **)field) == NULL) { -+ free(old_field); -+ fprintf(stderr, "Failed to allocate memory: aborting"); -+ exit(1); -+ } - - for (i = (prev_given - 1); i >= 0; --i) - { -diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c -index ac5292f9..7bc5a3ff 100644 ---- a/src/tools/opensc-explorer.c -+++ b/src/tools/opensc-explorer.c -@@ -1399,7 +1399,7 @@ static int do_get(int argc, char **argv) - if (r == SC_SUCCESS) - r = sc_select_file(card, &path, &file); - sc_unlock(card); -- if (r) { -+ if (r || file == NULL) { - check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); - goto err; - } -diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c -index 6dc8213d..23a58ce6 100644 ---- a/src/tools/piv-tool.c -+++ b/src/tools/piv-tool.c -@@ -477,6 +477,7 @@ int main(int argc, char *argv[]) - const char *key_info = NULL; - const char *admin_info = NULL; - sc_context_param_t ctx_param; -+ char **old_apdus = NULL; - - setbuf(stderr, NULL); - setbuf(stdout, NULL); -@@ -493,9 +494,11 @@ int main(int argc, char *argv[]) - action_count++; - break; - case 's': -+ old_apdus = opt_apdus; - opt_apdus = (char **) realloc(opt_apdus, - (opt_apdu_count + 1) * sizeof(char *)); - if (!opt_apdus) { -+ free(old_apdus); - err = 1; - goto end; - } -diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c -index 64525f6a..5795a8ba 100644 ---- a/src/tools/pkcs11-tool.c -+++ b/src/tools/pkcs11-tool.c -@@ -2695,6 +2695,7 @@ static int write_object(CK_SESSION_HANDLE session) - if (!(f = fopen(opt_attr_from_file, "rb"))) - util_fatal("Couldn't open file \"%s\"", opt_attr_from_file); - certdata_len = fread(certdata, 1, sizeof(certdata), f); -+ certdata[certdata_len] = '\0'; - if (certdata_len < 0) - util_fatal("Couldn't read from file \"%s\"", opt_attr_from_file); - fclose(f); -diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c -index 02cdfcc6..2b424cf7 100644 ---- a/src/tools/sc-hsm-tool.c -+++ b/src/tools/sc-hsm-tool.c -@@ -1503,13 +1503,13 @@ static int unwrap_key(sc_card_t *card, int keyid, const char *inf, const char *p - return -1; - } - -- if ((keybloblen = fread(keyblob, 1, sizeof(keyblob), in)) < 0) { -+ keybloblen = fread(keyblob, 1, sizeof(keyblob), in); -+ fclose(in); -+ if (keybloblen < 0) { - perror(inf); - return -1; - } - -- fclose(in); -- - ptr = keyblob; - if ((sc_asn1_read_tag(&ptr, keybloblen, &cla, &tag, &len) != SC_SUCCESS) - || ((cla & SC_ASN1_TAG_CONSTRUCTED) != SC_ASN1_TAG_CONSTRUCTED) diff --git a/SOURCES/opensc-0.19.0-dual.patch b/SOURCES/opensc-0.19.0-dual.patch deleted file mode 100644 index d11869f..0000000 --- a/SOURCES/opensc-0.19.0-dual.patch +++ /dev/null @@ -1,609 +0,0 @@ -diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c -index 03c83868f1..794472134c 100644 ---- a/src/libopensc/card-piv.c -+++ b/src/libopensc/card-piv.c -@@ -3,7 +3,7 @@ - * card-default.c: Support for cards with no driver - * - * Copyright (C) 2001, 2002 Juha Yrjölä -- * Copyright (C) 2005-2016 Douglas E. Engert -+ * Copyright (C) 2005-2018 Douglas E. Engert - * Copyright (C) 2006, Identity Alliance, Thomas Harning - * Copyright (C) 2007, EMC, Russell Larner - * -@@ -53,6 +53,7 @@ - #ifdef ENABLE_ZLIB - #include "compression.h" - #endif -+#include "simpletlv.h" - - enum { - PIV_OBJ_CCC = 0, -@@ -146,6 +147,16 @@ enum { - PIV_STATE_INIT - }; - -+/* ccc_flags */ -+#define PIV_CCC_FOUND 0x00000001 -+#define PIV_CCC_F0_PIV 0x00000002 -+#define PIV_CCC_F0_CAC 0x00000004 -+#define PIV_CCC_F0_JAVA 0x00000008 -+#define PIV_CCC_F3_CAC_PKI 0x00000010 -+ -+#define PIV_CCC_TAG_F0 0xF0 -+#define PIV_CCC_TAG_F3 0xF3 -+ - typedef struct piv_private_data { - int enumtag; - int selected_obj; /* The index into the piv_objects last selected */ -@@ -174,6 +185,7 @@ typedef struct piv_private_data { - unsigned int card_issues; /* card_issues flags for this card */ - int object_test_verify; /* Can test this object to set verification state of card */ - int yubico_version; /* 3 byte version number of NEO or Yubikey4 as integer */ -+ unsigned int ccc_flags; /* From CCC indicate if CAC card */ - } piv_private_data_t; - - #define PIV_DATA(card) ((piv_private_data_t*)card->drv_data) -@@ -198,6 +210,37 @@ struct piv_aid { - * These can be discovered by trying GET DATA - */ - -+/* ATRs of cards known to have PIV applet. But must still be tested for a PIV applet */ -+static const struct sc_atr_table piv_atrs[] = { -+ /* CAC cards with PIV from: CAC-utilziation-and-variation-matrix-v2.03-20May2016.doc */ -+ /* Oberthur Card Systems (PIV Endpoint) with PIV endpoint applet and PIV auth cert OBSOLETE */ -+ { "3B:DB:96:00:80:1F:03:00:31:C0:64:77:E3:03:00:82:90.00:C1", NULL, NULL, SC_CARD_TYPE_PIV_II_OBERTHUR, 0, NULL }, -+ -+ /* Gemalto (PIV Endpoint) with PIV endpoint applet and PIV auth cert OBSOLETE */ -+ { "3B 7D 96 00 00 80 31 80 65 B0 83 11 13 AC 83 00 90 00", NULL, NULL, SC_CARD_TYPE_PIV_II_GEMALTO, 0, NULL }, -+ -+ /* Gemalto (PIV Endpoint) 2 entries */ -+ { "3B:7D:96:00:00:80:31:80:65:B0:83:11:17:D6:83:00:90:00", NULL, NULL, SC_CARD_TYPE_PIV_II_GEMALTO, 0, NULL }, -+ -+ /* Oberthur Card System (PIV Endpoint) 2 entries*/ -+ { "3B:DB:96:00:80:1F:03:00:31:C0:64:B0:F3:10:00:07:90:00:80", NULL, NULL, SC_CARD_TYPE_PIV_II_OBERTHUR, 0, NULL }, -+ -+ /* Giesecke & Devrient (PIV Endpoint) 2 entries */ -+ { "3B:7A:18:00:00:73:66:74:65:20:63:64:31:34:34", NULL, NULL, SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC, 0, NULL }, -+ -+ /* PIVKEY from Taligo */ -+ /* PIVKEY T600 token and T800 on Feitian eJAVA */ -+ { "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:00:64:2D:70:C1:72:FE:E0:FE", NULL, NULL, SC_CARD_TYPE_PIV_II_PIVKEY, 0, NULL }, -+ -+ /* PIVKEY C910 */ -+ { "3b:fc:18:00:00:81:31:80:45:90:67:46:4a:00:64:16:06:f2:72:7e:00:e0", NULL, NULL, SC_CARD_TYPE_PIV_II_PIVKEY, 0, NULL }, -+ -+ /* PIVKEY C980 */ -+ { "3B:f9:96:00:00:81:31:fe:45:53:50:49:56:4b:45:59:37:30:28", NULL, NULL, SC_CARD_TYPE_PIV_II_PIVKEY, 0, NULL }, -+ -+ { NULL, NULL, NULL, 0, 0, NULL } -+}; -+ - /* all have same AID */ - static struct piv_aid piv_aids[] = { - {SC_CARD_TYPE_PIV_II_GENERIC, /* TODO not really card type but what PIV AID is supported */ -@@ -209,9 +252,10 @@ static struct piv_aid piv_aids[] = { - #define CI_VERIFY_630X 0x00000001U /* VERIFY tries left returns 630X rather then 63CX */ - #define CI_VERIFY_LC0_FAIL 0x00000002U /* VERIFY Lc=0 never returns 90 00 if PIN not needed */ - /* will also test after first PIN verify if protected object can be used instead */ -+#define CI_NO_RANDOM 0x00000004U /* can not use Challenge to get random data or no 9B key */ - #define CI_CANT_USE_GETDATA_FOR_STATE 0x00000008U /* No object to test verification inplace of VERIFY Lc=0 */ - #define CI_LEAKS_FILE_NOT_FOUND 0x00000010U /* GET DATA of empty object returns 6A 82 even if PIN not verified */ --#define CI_DISCOVERY_USELESS 0x00000020U /* Discovery can not be used to query active AID */ -+#define CI_DISCOVERY_USELESS 0x00000020U /* Discovery can not be used to query active AID invalid or no data returned */ - #define CI_PIV_AID_LOSE_STATE 0x00000040U /* PIV AID can lose the login state run with out it*/ - - #define CI_OTHER_AID_LOSE_STATE 0x00000100U /* Other drivers match routines may reset our security state and lose AID!!! */ -@@ -219,7 +263,7 @@ static struct piv_aid piv_aids[] = { - - #define CI_NO_RSA2048 0x00010000U /* does not have RSA 2048 */ - #define CI_NO_EC384 0x00020000U /* does not have EC 384 */ -- -+#define CI_NO_EC 0x00040000U /* No EC at all */ - - /* - * Flags in the piv_object: -@@ -2222,11 +2266,33 @@ static int piv_get_challenge(sc_card_t *card, u8 *rnd, size_t len) - size_t rbuf_len = 0, out_len = 0; - int r; - unsigned int tag, cla; -+ piv_private_data_t * priv = PIV_DATA(card); - - LOG_FUNC_CALLED(card->ctx); - -+ if (priv->card_issues & CI_NO_RANDOM) { -+ r = SC_ERROR_NOT_SUPPORTED; -+ LOG_TEST_GOTO_ERR(card->ctx, r, "No support for random data"); -+ } -+ - /* NIST 800-73-3 says use 9B, previous verisons used 00 */ - r = piv_general_io(card, 0x87, 0x00, 0x9B, sbuf, sizeof sbuf, &rbuf, &rbuf_len); -+ /* -+ * piv_get_challenge is called in a loop. -+ * some cards may allow 1 challenge expecting it to be part of -+ * NIST 800-73-3 part 2 "Authentication of PIV Card Application Administrator" -+ * and return "6A 80" if last command was a get_challenge. -+ * Now that the card returned error, we can try one more time. -+ */ -+ if (r == SC_ERROR_INCORRECT_PARAMETERS) { -+ if (rbuf) -+ free(rbuf); -+ rbuf_len = 0; -+ r = piv_general_io(card, 0x87, 0x00, 0x9B, sbuf, sizeof sbuf, &rbuf, &rbuf_len); -+ if (r == SC_ERROR_INCORRECT_PARAMETERS) { -+ r = SC_ERROR_NOT_SUPPORTED; -+ } -+ } - LOG_TEST_GOTO_ERR(card->ctx, r, "GENERAL AUTHENTICATE failed"); - - p = rbuf; -@@ -2635,6 +2701,91 @@ static int piv_process_discovery(sc_card_t *card) - LOG_FUNC_RETURN(card->ctx, r); - } - -+/* -+ * parse a CCC to test if this is a Dual CAC/PIV -+ * We read teh CCC using the PIV API. -+ * Look for CAC RID=A0 00 00 00 79 -+ */ -+ static int piv_parse_ccc(sc_card_t *card, u8* rbuf, size_t rbuflen) -+{ -+ int r = 0; -+ const u8 * body; -+ size_t bodylen; -+ unsigned int cla_out, tag_out; -+ -+ u8 tag; -+ const u8 * end; -+ size_t len; -+ -+ piv_private_data_t * priv = PIV_DATA(card); -+ -+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); -+ -+ if (rbuf == NULL || rbuflen == 0) { -+ r = SC_ERROR_WRONG_LENGTH; -+ goto err; -+ } -+ -+ /* Outer layer is a DER tlv */ -+ body = rbuf; -+ if ((r = sc_asn1_read_tag(&body, rbuflen, &cla_out, &tag_out, &bodylen)) != SC_SUCCESS) { -+ sc_log(card->ctx, "DER problem %d",r); -+ r = SC_ERROR_INVALID_ASN1_OBJECT; -+ goto err; -+ } -+ -+ priv->ccc_flags |= PIV_CCC_FOUND; -+ -+ /* CCC entries are simple tlv */ -+ end = body + bodylen; -+ -+ for(; (body < end); body += len) { -+ -+ r = sc_simpletlv_read_tag((u8**)&body, end - body , &tag, &len); -+ if (r < 0) -+ goto err; -+ switch (tag) { -+ case PIV_CCC_TAG_F0: -+ if (len == 0x15) { -+ if (memcmp(body ,"\xA0\x00\x00\x03\08", 5) == 0) -+ priv->ccc_flags |= PIV_CCC_F0_PIV; -+ else if (memcmp(body ,"\xA0\x00\x00\x00\x79", 5) == 0) -+ priv->ccc_flags |= PIV_CCC_F0_CAC; -+ if (*(body + 6) == 0x02) -+ priv->ccc_flags |= PIV_CCC_F0_JAVA; -+ } -+ break; -+ case PIV_CCC_TAG_F3: -+ if (len == 0x10) { -+ if (memcmp(body ,"\xA0\x00\x00\x00\x79\x04", 6) == 0) -+ priv->ccc_flags |= PIV_CCC_F3_CAC_PKI; -+ } -+ break; -+ } -+ } -+ -+err: -+ LOG_FUNC_RETURN(card->ctx, r); -+} -+ -+static int piv_process_ccc(sc_card_t *card) -+{ -+ int r = 0; -+ u8 * rbuf = NULL; -+ size_t rbuflen = 0; -+ -+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); -+ r = piv_get_cached_data(card, PIV_OBJ_CCC, &rbuf, &rbuflen); -+ -+ if (r < 0) -+ goto err; -+ -+ /* the object is now cached, see what we have */ -+ r = piv_parse_ccc(card, rbuf, rbuflen); -+err: -+ LOG_FUNC_RETURN(card->ctx, r); -+} -+ - - static int piv_find_discovery(sc_card_t *card) - { -@@ -2922,7 +3073,8 @@ piv_finish(sc_card_t *card) - static int piv_match_card(sc_card_t *card) - { - int r = 0; -- -+ -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d\n", card->type); - /* piv_match_card may be called with card->type, set by opensc.conf */ - /* user provide card type must be one we know */ - switch (card->type) { -@@ -2931,7 +3083,13 @@ static int piv_match_card(sc_card_t *card) - case SC_CARD_TYPE_PIV_II_HIST: - case SC_CARD_TYPE_PIV_II_NEO: - case SC_CARD_TYPE_PIV_II_YUBIKEY4: -+ case SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC: - case SC_CARD_TYPE_PIV_II_GI_DE: -+ case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_GEMALTO: -+ case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_OBERTHUR: -+ case SC_CARD_TYPE_PIV_II_PIVKEY: - break; - default: - return 0; /* can not handle the card */ -@@ -2950,13 +3108,14 @@ static int piv_match_card(sc_card_t *card) - piv_finish(card); - } - -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d r:%d\n", card->type,r); - return r; - } - - - static int piv_match_card_continued(sc_card_t *card) - { -- int i, r; -+ int i, r = 0; - int type = -1; - piv_private_data_t *priv = NULL; - int saved_type = card->type; -@@ -2973,12 +3132,19 @@ static int piv_match_card_continued(sc_card_t *card) - case SC_CARD_TYPE_PIV_II_HIST: - case SC_CARD_TYPE_PIV_II_NEO: - case SC_CARD_TYPE_PIV_II_YUBIKEY4: -+ case SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC: - case SC_CARD_TYPE_PIV_II_GI_DE: -+ case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_GEMALTO: -+ case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_OBERTHUR: -+ case SC_CARD_TYPE_PIV_II_PIVKEY: - type = card->type; - break; - default: - return 0; /* can not handle the card */ - } -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d type:%d r:%d\n", card->type, type, r); - if (type == -1) { - - /* -@@ -2997,18 +3163,6 @@ static int piv_match_card_continued(sc_card_t *card) - !(memcmp(card->reader->atr_info.hist_bytes, "Yubikey", 7))) { - type = SC_CARD_TYPE_PIV_II_NEO; - } -- /* -- * https://csrc.nist.gov/csrc/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp1239.pdf -- * lists 2 ATRS with historical bytes: -- * 73 66 74 65 2D 63 64 30 38 30 -- * 73 66 74 65 20 63 64 31 34 34 -- * will check for 73 66 74 65 -- */ -- else if (card->reader->atr_info.hist_bytes_len >= 4 -- && !(memcmp(card->reader->atr_info.hist_bytes, "sfte", 4))) { -- type = SC_CARD_TYPE_PIV_II_GI_DE; -- } -- - else if (card->reader->atr_info.hist_bytes_len > 0 - && card->reader->atr_info.hist_bytes[0] == 0x80u) { /* compact TLV */ - size_t datalen; -@@ -3029,10 +3183,17 @@ static int piv_match_card_continued(sc_card_t *card) - } - } - } -- if (type == -1) -- type = SC_CARD_TYPE_PIV_II_GENERIC; -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d type:%d r:%d\n", card->type, type, r); -+ -+ if (type == -1) { -+ /* use known ATRs */ -+ i = _sc_match_atr(card, piv_atrs, &type); -+ if (type == -1) -+ type = SC_CARD_TYPE_PIV_II_GENERIC; /* may still be CAC with PIV Endpoint */ -+ } - } - -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d type:%d r:%d\n", card->type, type, r); - /* allocate and init basic fields */ - - priv = calloc(1, sizeof(piv_private_data_t)); -@@ -3046,6 +3207,7 @@ static int piv_match_card_continued(sc_card_t *card) - card->drv_data = priv; /* will free if no match, or pass on to piv_init */ - priv->selected_obj = -1; - priv->pin_preference = 0x80; /* 800-73-3 part 1, table 3 */ -+ /* TODO Dual CAC/PIV are bases on 800-73-1 were priv->pin_preference = 0. need to check later */ - priv->logged_in = SC_PIN_STATE_UNKNOWN; - priv->tries_left = 10; /* will assume OK at start */ - priv->pstate = PIV_STATE_MATCH; -@@ -3064,38 +3226,104 @@ static int piv_match_card_continued(sc_card_t *card) - } - - /* -- * detect if active AID is PIV. NIST 800-73 says Only one PIV application per card -- * and PIV must be the default application -- * This can avoid doing doing a select_aid and losing the login state on some cards -+ * Detect if active AID is PIV. NIST 800-73 says only one PIV application per card -+ * and PIV must be the default application. -+ * Try to avoid doing a select_aid and losing the login state on some cards. - * We may get interference on some cards by other drivers trying SELECT_AID before -- * we get to see if PIV application is still active. -+ * we get to see if PIV application is still active - * putting PIV driver first might help. -- * This may fail if the wrong AID is active -+ * This may fail if the wrong AID is active. -+ * Discovery Object introduced in 800-73-3 so will return 0 if found and PIV applet active. -+ * Will fail with SC_ERROR_FILE_NOT_FOUND if 800-73-3 and no Discovery object. -+ * But some other card could also return SC_ERROR_FILE_NOT_FOUND. -+ * Will fail for other reasons if wrong applet is selected, or bad PIV implimentation. - */ -- i = piv_find_discovery(card); -+ -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d CI:%08x r:%d\n", card->type, priv->card_issues, r); -+ if (priv->card_issues & CI_DISCOVERY_USELESS) /* TODO may be in wrong place */ -+ i = -1; -+ else -+ i = piv_find_discovery(card); - -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r); - if (i < 0) { - /* Detect by selecting applet */ - i = piv_find_aid(card); - } - -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r); - if (i >= 0) { -+ int iccc = 0; -+ /* We now know PIV AID is active, test CCC object 800-73-* say CCC is required */ -+ switch (card->type) { -+ /* -+ * For cards that may also be CAC, try and read the CCC -+ * CCC is required and all Dual PIV/CAC will have a CCC -+ * Currently Dual PIV/CAC are based on NIST 800-73-1 which does not have Discovery or History -+ */ -+ case SC_CARD_TYPE_PIV_II_GENERIC: /* i.e. really dont know what this is */ -+ case SC_CARD_TYPE_PIV_II_HIST: -+ case SC_CARD_TYPE_PIV_II_GI_DE: -+ case SC_CARD_TYPE_PIV_II_GEMALTO: -+ case SC_CARD_TYPE_PIV_II_OBERTHUR: -+ iccc = piv_process_ccc(card); -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d iccc:%d ccc_flags:%08x CI:%08x r:%d\n", -+ card->type, iccc, priv->ccc_flags, priv->card_issues, r); -+ /* ignore an error? */ -+ /* if CCC says it has CAC with PKI on card set to one of the SC_CARD_TYPE_PIV_II_*_DUAL_CAC */ -+ if (priv->ccc_flags & PIV_CCC_F3_CAC_PKI) { -+ switch (card->type) { -+ case SC_CARD_TYPE_PIV_II_GENERIC: -+ case SC_CARD_TYPE_PIV_II_HIST: -+ case SC_CARD_TYPE_PIV_II_GI_DE: -+ card->type = SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC; -+ priv->card_issues |= CI_DISCOVERY_USELESS; -+ priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT; -+ break; -+ case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_GEMALTO: -+ card->type = SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC; -+ priv->card_issues |= CI_DISCOVERY_USELESS; -+ priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT; -+ break; -+ case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_OBERTHUR: -+ card->type = SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC; -+ priv->card_issues |= CI_DISCOVERY_USELESS; -+ priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT; -+ break; -+ } -+ } -+ break; -+ -+ /* if user forced it to be one of the CAC types, assume it is CAC */ -+ case SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC: -+ priv->card_issues |= CI_DISCOVERY_USELESS; -+ priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT; -+ break; -+ } -+ } -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r); -+ if (i >= 0 && (priv->card_issues & CI_DISCOVERY_USELESS) == 0) { - /* -- * We now know PIV AID is active, test DISCOVERY object -- * Some CAC cards with PIV don't support DISCOVERY and return -- * SC_ERROR_INCORRECT_PARAMETERS. Any error other then -- * SC_ERROR_FILE_NOT_FOUND means we cannot use discovery -+ * We now know PIV AID is active, test DISCOVERY object again -+ * Some PIV don't support DISCOVERY and return -+ * SC_ERROR_INCORRECT_PARAMETERS. Any error -+ * including SC_ERROR_FILE_NOT_FOUND means we cannot use discovery - * to test for active AID. - */ - int i7e = piv_find_discovery(card); - -- if (i7e != 0 && i7e != SC_ERROR_FILE_NOT_FOUND) { -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i7e:%d CI:%08x r:%d\n", card->type, i7e, priv->card_issues, r); -+ if (i7e != 0) { - priv->card_issues |= CI_DISCOVERY_USELESS; - priv->obj_cache[PIV_OBJ_DISCOVERY].flags |= PIV_OBJ_CACHE_NOT_PRESENT; - } - } - -- -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r); - if (i < 0) { - /* don't match. Does not have a PIV applet. */ - sc_unlock(card); -@@ -3104,6 +3332,7 @@ static int piv_match_card_continued(sc_card_t *card) - return 0; - } - -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r); - /* Matched, caller will use or free priv and sc_lock as needed */ - priv->pstate=PIV_STATE_INIT; - return 1; /* match */ -@@ -3124,7 +3353,7 @@ static int piv_init(sc_card_t *card) - /* continue the matching get a lock and the priv */ - r = piv_match_card_continued(card); - if (r != 1) { -- sc_log(card->ctx,"piv_match_card_continued failed"); -+ sc_log(card->ctx,"piv_match_card_continued failed card->type:%d", card->type); - piv_finish(card); - /* tell sc_connect_card to try other drivers */ - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD); -@@ -3147,6 +3376,7 @@ static int piv_init(sc_card_t *card) - * Set card_issues based on card type either set by piv_match_card or by opensc.conf - */ - -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d CI:%08x r:%d\n", card->type, priv->card_issues, r); - switch(card->type) { - case SC_CARD_TYPE_PIV_II_NEO: - case SC_CARD_TYPE_PIV_II_YUBIKEY4: -@@ -3178,6 +3408,7 @@ static int piv_init(sc_card_t *card) - * may be set earlier or later then in the following code. - */ - -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d CI:%08x r:%d\n", card->type, priv->card_issues, r); - switch(card->type) { - case SC_CARD_TYPE_PIV_II_NEO: - priv->card_issues |= CI_NO_EC384 -@@ -3196,30 +3427,53 @@ static int piv_init(sc_card_t *card) - priv->card_issues |= CI_VERIFY_LC0_FAIL; - break; - -+ case SC_CARD_TYPE_PIV_II_GI_DE: -+ case SC_CARD_TYPE_PIV_II_OBERTHUR: -+ case SC_CARD_TYPE_PIV_II_GEMALTO: -+ priv->card_issues |= 0; /* could add others here */ -+ break; -+ - case SC_CARD_TYPE_PIV_II_HIST: -- priv->card_issues |= 0; -+ priv->card_issues |= 0; /* could add others here */ - break; - -- case SC_CARD_TYPE_PIV_II_GI_DE: -+ case SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC: -+ case SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC: - priv->card_issues |= CI_VERIFY_LC0_FAIL - | CI_PIV_AID_LOSE_STATE -- | CI_OTHER_AID_LOSE_STATE;; -+ | CI_NO_RANDOM -+ | CI_OTHER_AID_LOSE_STATE; - /* TODO may need more research */ - break; - -+ - case SC_CARD_TYPE_PIV_II_GENERIC: - priv->card_issues |= CI_VERIFY_LC0_FAIL - | CI_OTHER_AID_LOSE_STATE; - /* TODO may need more research */ - break; - -+ case SC_CARD_TYPE_PIV_II_PIVKEY: -+ priv->card_issues |= CI_VERIFY_LC0_FAIL -+ | CI_PIV_AID_LOSE_STATE /* be conservative */ -+ | CI_NO_EC384 | CI_NO_EC -+ | CI_NO_RANDOM; /* does not have 9B key */ -+ /* Discovery object returns 6A 82 so is not on card by default */ -+ /* TODO may need more research */ -+ break; -+ - default: -- priv->card_issues = 0; /* opensc.conf may have it wrong, continue anyway */ -- sc_log(card->ctx, "Unknown PIV card->type %d", card->type); -- card->type = SC_CARD_TYPE_PIV_II_BASE; -+ priv->card_issues |= CI_VERIFY_LC0_FAIL -+ | CI_OTHER_AID_LOSE_STATE; -+ /* opensc.conf may have it wrong, continue anyway */ -+ sc_log(card->ctx, "Unknown PIV card->type %d", card->type); -+ card->type = SC_CARD_TYPE_PIV_II_GENERIC; - } - sc_log(card->ctx, "PIV card-type=%d card_issues=0x%08x", card->type, priv->card_issues); - -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d CI:%08x r:%d\n", card->type, priv->card_issues, r); -+ - priv->enumtag = piv_aids[0].enumtag; - - /* PKCS#11 may try to generate session keys, and get confused -@@ -3233,15 +3487,20 @@ static int piv_init(sc_card_t *card) - _sc_card_add_rsa_alg(card, 2048, flags, 0); /* optional */ - _sc_card_add_rsa_alg(card, 3072, flags, 0); /* optional */ - -- flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ECDSA_HASH_NONE; -- ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; -+ if (!(priv->card_issues & CI_NO_EC)) { -+ flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ECDSA_HASH_NONE; -+ ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; -+ -+ _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); -+ if (!(priv->card_issues & CI_NO_EC384)) -+ _sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL); -+ } - -- _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); -- if (!(priv->card_issues & CI_NO_EC384)) -- _sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL); -+ if (!(priv->card_issues & CI_NO_RANDOM)) -+ card->caps |= SC_CARD_CAP_RNG; - -- /* TODO may turn off SC_CARD_CAP_ISO7816_PIN_INFO later */ -- card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO; -+ /* May turn off SC_CARD_CAP_ISO7816_PIN_INFO later */ -+ card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; - - /* - * 800-73-3 cards may have a history object and/or a discovery object -@@ -3565,11 +3824,13 @@ static int piv_card_reader_lock_obtained(sc_card_t *card, int was_reset) - r = SC_ERROR_NO_CARD_SUPPORT; - } else { - r = piv_find_discovery(card); -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH piv_find_discovery card->type:%d r:%d\n", card->type, r); - } - - if (r < 0) { - if (was_reset > 0 || !(priv->card_issues & CI_PIV_AID_LOSE_STATE)) { - r = piv_select_aid(card, piv_aids[0].value, piv_aids[0].len_short, temp, &templen); -+ sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH piv_select_aid card->type:%d r:%d\n", card->type, r); - } else { - r = 0; /* cant do anything with this card, hope there was no interference */ - } -diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h -index f4df17fb04..121182bb6a 100644 ---- a/src/libopensc/cards.h -+++ b/src/libopensc/cards.h -@@ -136,7 +136,13 @@ enum { - SC_CARD_TYPE_PIV_II_HIST, - SC_CARD_TYPE_PIV_II_NEO, - SC_CARD_TYPE_PIV_II_YUBIKEY4, -+ SC_CARD_TYPE_PIV_II_GI_DE_DUAL_CAC, - SC_CARD_TYPE_PIV_II_GI_DE, -+ SC_CARD_TYPE_PIV_II_GEMALTO_DUAL_CAC, -+ SC_CARD_TYPE_PIV_II_GEMALTO, -+ SC_CARD_TYPE_PIV_II_OBERTHUR_DUAL_CAC, -+ SC_CARD_TYPE_PIV_II_OBERTHUR, -+ SC_CARD_TYPE_PIV_II_PIVKEY, - - /* MuscleApplet */ - SC_CARD_TYPE_MUSCLE_BASE = 15000, - diff --git a/SOURCES/opensc-0.19.0-idprime.patch b/SOURCES/opensc-0.19.0-idprime.patch index dfc460d..7858e19 100644 --- a/SOURCES/opensc-0.19.0-idprime.patch +++ b/SOURCES/opensc-0.19.0-idprime.patch @@ -1,7 +1,68 @@ -diff -up opensc-0.19.0/src/libopensc/card-cac1.c.idprime opensc-0.19.0/src/libopensc/card-cac1.c ---- opensc-0.19.0/src/libopensc/card-cac1.c.idprime 2019-11-14 09:42:03.557198986 +0100 -+++ opensc-0.19.0/src/libopensc/card-cac1.c 2019-11-14 09:42:03.563199045 +0100 -@@ -59,6 +59,7 @@ +diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am +index 49d122682f..a9f200c959 100644 +--- a/src/libopensc/Makefile.am ++++ b/src/libopensc/Makefile.am +@@ -48,14 +48,14 @@ libopensc_la_SOURCES_BASE = \ + card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ + card-dnie.c cwa14890.c cwa-dnie.c \ + card-isoApplet.c card-masktech.c card-gids.c card-jpki.c \ +- card-npa.c card-esteid2018.c \ ++ card-npa.c card-esteid2018.c card-idprime.c \ + \ + pkcs15-openpgp.c pkcs15-starcert.c \ + pkcs15-tcos.c pkcs15-esteid.c pkcs15-gemsafeGPK.c \ + pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \ + pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ + pkcs15-oberthur.c pkcs15-itacns.c pkcs15-gemsafeV1.c pkcs15-sc-hsm.c \ +- pkcs15-coolkey.c pkcs15-din-66291.c \ ++ pkcs15-coolkey.c pkcs15-din-66291.c pkcs15-idprime.c \ + pkcs15-dnie.c pkcs15-gids.c pkcs15-iasecc.c pkcs15-jpki.c pkcs15-esteid2018.c \ + compression.c p15card-helper.c sm.c \ + aux-data.c +@@ -131,14 +131,14 @@ TIDY_FILES = \ + card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ + cwa14890.c cwa-dnie.c \ + card-isoApplet.c card-masktech.c card-jpki.c \ +- card-npa.c card-esteid2018.c \ ++ card-npa.c card-esteid2018.c card-idprime.c \ + \ + pkcs15-openpgp.c \ + pkcs15-tcos.c pkcs15-esteid.c \ + pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c \ + pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ + pkcs15-oberthur.c pkcs15-itacns.c pkcs15-sc-hsm.c \ +- pkcs15-coolkey.c pkcs15-din-66291.c \ ++ pkcs15-coolkey.c pkcs15-din-66291.c pkcs15-idprime.c \ + pkcs15-dnie.c pkcs15-gids.c pkcs15-iasecc.c pkcs15-jpki.c pkcs15-esteid2018.c \ + compression.c p15card-helper.c sm.c \ + aux-data.c \ +diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak +index 487fbeb4a6..2e3c30c22b 100644 +--- a/src/libopensc/Makefile.mak ++++ b/src/libopensc/Makefile.mak +@@ -27,7 +27,7 @@ OBJECTS = \ + card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \ + card-sc-hsm.obj card-dnie.obj card-isoApplet.obj pkcs15-coolkey.obj \ + card-masktech.obj card-gids.obj card-jpki.obj \ +- card-npa.obj card-esteid2018.obj \ ++ card-npa.obj card-esteid2018.obj card-idprime.obj \ + \ + pkcs15-openpgp.obj pkcs15-starcert.obj \ + pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-gemsafeGPK.obj \ +@@ -35,7 +35,7 @@ OBJECTS = \ + pkcs15-cac.obj pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-din-66291.obj \ + pkcs15-oberthur.obj pkcs15-itacns.obj pkcs15-gemsafeV1.obj pkcs15-sc-hsm.obj \ + pkcs15-dnie.obj pkcs15-gids.obj pkcs15-iasecc.obj pkcs15-jpki.obj \ +- pkcs15-esteid2018.obj \ ++ pkcs15-esteid2018.obj pkcs15-idprime.obj \ + compression.obj p15card-helper.obj sm.obj \ + aux-data.obj \ + $(TOPDIR)\win32\versioninfo.res +diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c +index d59b4337c8..2c9361df88 100644 +--- a/src/libopensc/card-cac.c ++++ b/src/libopensc/card-cac.c +@@ -54,6 +54,7 @@ #endif #include "iso7816.h" #include "card-cac-common.h" @@ -9,10 +70,11 @@ diff -up opensc-0.19.0/src/libopensc/card-cac1.c.idprime opensc-0.19.0/src/libop /* * CAC hardware and APDU constants -diff -up opensc-0.19.0/src/libopensc/card-cac.c.idprime opensc-0.19.0/src/libopensc/card-cac.c ---- opensc-0.19.0/src/libopensc/card-cac.c.idprime 2019-11-14 09:42:03.556198976 +0100 -+++ opensc-0.19.0/src/libopensc/card-cac.c 2019-11-14 09:42:03.563199045 +0100 -@@ -59,6 +59,7 @@ +diff --git a/src/libopensc/card-cac1.c b/src/libopensc/card-cac1.c +index 08d62b62cc..67035d64e6 100644 +--- a/src/libopensc/card-cac1.c ++++ b/src/libopensc/card-cac1.c +@@ -54,6 +54,7 @@ #endif #include "iso7816.h" #include "card-cac-common.h" @@ -20,30 +82,12 @@ diff -up opensc-0.19.0/src/libopensc/card-cac.c.idprime opensc-0.19.0/src/libope /* * CAC hardware and APDU constants -diff -up opensc-0.19.0/src/libopensc/cardctl.h.idprime opensc-0.19.0/src/libopensc/cardctl.h ---- opensc-0.19.0/src/libopensc/cardctl.h.idprime 2018-09-13 13:52:42.000000000 +0200 -+++ opensc-0.19.0/src/libopensc/cardctl.h 2019-11-14 09:42:03.563199045 +0100 -@@ -303,6 +303,16 @@ enum { - SC_CARDCTL_GIDS_INITIALIZE, - SC_CARDCTL_GIDS_SET_ADMIN_KEY, - SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, -+ -+ /* -+ * IDPrime specific calls -+ */ -+ SC_CARDCTL_IDPRIME_BASE = _CTL_PREFIX('I', 'D', 'P'), -+ SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS, -+ SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT, -+ SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, -+ SC_CARDCTL_IDPRIME_GET_TOKEN_NAME, -+ - }; - - enum { -diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/libopensc/card-idprime.c ---- opensc-0.19.0/src/libopensc/card-idprime.c.idprime 2019-11-14 09:42:03.563199045 +0100 -+++ opensc-0.19.0/src/libopensc/card-idprime.c 2019-11-14 09:42:03.563199045 +0100 -@@ -0,0 +1,789 @@ +diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c +new file mode 100644 +index 0000000000..7399830afd +--- /dev/null ++++ b/src/libopensc/card-idprime.c +@@ -0,0 +1,803 @@ +/* + * card-idprime.c: Support for Gemalto IDPrime smart cards + * @@ -124,6 +168,7 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + size_t file_size; /* this is real file size since IDPrime is quite strict about lengths */ + list_t pki_list; /* list of pki containers */ + idprime_object_t *pki_current; /* current pki object _ctl function */ ++ int tinfo_present; /* Token Info Label object is present*/ + u8 tinfo_df[2]; /* DF of object with Token Info Label */ +} idprime_private_data_t; + @@ -189,12 +234,14 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + /* Returns FCI with expected length of data */ + sc_format_path("0101", &index_path); + r = iso_ops->select_file(card, &index_path, &file); -+ if (r != SC_SUCCESS) { -+ sc_file_free(file); -+ LOG_FUNC_RETURN(card->ctx, r); ++ if (r == SC_SUCCESS) { ++ r = file->size; + } -+ r = file->size; + sc_file_free(file); ++ /* Ignore too large files */ ++ if (r > MAX_FILE_SIZE) { ++ r = SC_ERROR_INVALID_DATA; ++ } + return r; +} + @@ -230,7 +277,7 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + new_object.df[0] = start[0]; + new_object.df[1] = start[1]; + /* Second two bytes refer to the object size */ -+ new_object.length = bebytes2ushort(&start[2]); ++ new_object.length = bebytes2ushort(&start[2]); + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "df=%s, len=%u", + sc_dump_hex(new_object.df, sizeof(new_object.df)), new_object.length); + /* in minidriver, mscp/kxcNN or kscNN lists certificates */ @@ -244,7 +291,6 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + /* The key reference is one bigger than the value found here for some reason */ + new_object.key_reference = start[8] + 1; + } -+ new_object.fd++; + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found certificate with fd=%d, key_ref=%d", + new_object.fd, new_object.key_reference); + idprime_add_object_to_list(&priv->pki_list, &new_object); @@ -252,13 +298,13 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + /* This looks like non-standard extension listing pkcs11 token info label in my card */ + } else if ((memcmp(&start[4], "tinfo", 6) == 0) && (memcmp(&start[12], "p11", 4) == 0)) { + memcpy(priv->tinfo_df, new_object.df, sizeof(priv->tinfo_df)); ++ priv->tinfo_present = 1; + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found p11/tinfo object"); + } + } + r = SC_SUCCESS; +done: -+ if (buf) -+ free(buf); ++ free(buf); + LOG_FUNC_RETURN(card->ctx, r); +} + @@ -322,7 +368,18 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + + card->drv_data = priv; + -+ card->name = "Gemalto IDPrime"; ++ switch (card->type) { ++ case SC_CARD_TYPE_IDPRIME_V1: ++ card->name = "Gemalto IDPrime (OSv1)"; ++ break; ++ case SC_CARD_TYPE_IDPRIME_V2: ++ card->name = "Gemalto IDPrime (OSv2)"; ++ break; ++ case SC_CARD_TYPE_IDPRIME_GENERIC: ++ default: ++ card->name = "Gemalto IDPrime (generic)"; ++ break; ++ } + card->cla = 0x00; + + /* Set up algorithm info. */ @@ -424,13 +481,15 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + r = iso_ops->select_file(card, &cardid_path, &file); + if (r != SC_SUCCESS || file->size != IDPRIME_CARDID_LEN) { /* The cardid is always 16 B */ + sc_file_free(file); -+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH); ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH); + } + + r = iso_ops->read_binary(card, 0, buf, file->size, 0); + sc_file_free(file); + if (r < 1) { -+ LOG_FUNC_RETURN(card->ctx, r); ++ LOG_FUNC_RETURN(card->ctx, r); ++ } else if (r != IDPRIME_CARDID_LEN) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); + } + + serial->len = MIN(IDPRIME_CARDID_LEN, SC_MAX_SERIALNR); @@ -452,7 +511,7 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + } + -+ if (memcmp(priv->tinfo_df, "\0\0", 2) == 0) { ++ if (!priv->tinfo_present) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); + } + @@ -460,14 +519,14 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + r = iso_ops->select_file(card, &tinfo_path, &file); + if (r != SC_SUCCESS || file->size == 0) { + sc_file_free(file); -+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); + } + + /* First two bytes lists 0x01, the second indicates length */ -+ r = iso_ops->read_binary(card, 0, buf, 2, 0); ++ r = iso_ops->read_binary(card, 0, buf, 2, 0); + if (r < 2 || buf[1] > file->size) { /* make sure we do not overrun */ + sc_file_free(file); -+ LOG_FUNC_RETURN(card->ctx, r); ++ LOG_FUNC_RETURN(card->ctx, r); + } + sc_file_free(file); + @@ -479,7 +538,7 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + r = iso_ops->read_binary(card, 2, (unsigned char *)*tname, buf[1], 0); + if (r < 1) { + free(*tname); -+ LOG_FUNC_RETURN(card->ctx, r); ++ LOG_FUNC_RETURN(card->ctx, r); + } + + if ((*tname)[r-1] != '\0') { @@ -527,15 +586,14 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + -+ if (priv) { /* don't record anything if we haven't been initialized yet */ -+ /* forget any old cached values */ -+ if (priv->cache_buf) { -+ free(priv->cache_buf); -+ priv->cache_buf = NULL; -+ } -+ priv->cache_buf_len = 0; -+ priv->cached = 0; ++ /* forget any old cached values */ ++ if (priv->cache_buf) { ++ free(priv->cache_buf); ++ priv->cache_buf = NULL; + } ++ priv->cache_buf_len = 0; ++ priv->cached = 0; ++ + r = iso_ops->select_file(card, in_path, file_out); + if (r == SC_SUCCESS && priv && file_out != NULL) { + /* Try to read first bytes of the file to fix FCI in case of @@ -561,7 +619,7 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + int size; + + sc_log(card->ctx, "called; %"SC_FORMAT_LEN_SIZE_T"u bytes at offset %d", -+ count, offset); ++ count, offset); + + if (!priv->cached && offset == 0) { + // this function is called to read and uncompress the certificate @@ -583,7 +641,7 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + r = sc_decompress_alloc(&priv->cache_buf, &(priv->cache_buf_len), + buffer+4, priv->file_size-4, COMPRESSION_AUTO); + if (r != SC_SUCCESS) { -+ sc_log(card->ctx, "Zlib error: %d", r); ++ sc_log(card->ctx, "Zlib error: %d", r); + LOG_FUNC_RETURN(card->ctx, r); + } + if (priv->cache_buf_len != expectedsize) { @@ -686,7 +744,7 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + int r; + struct sc_apdu apdu; + u8 *p; -+ u8 sbuf[4096]; /* needs work. for 3072 keys, needs 384+10 or so */ ++ u8 sbuf[128]; /* For SHA-512 we need 64 + 2 bytes */ + u8 rbuf[4096]; /* needs work. for 3072 keys, needs 384+2 or so */ + size_t rbuflen = sizeof(rbuf); + @@ -766,8 +824,8 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li + } + LOG_FUNC_CALLED(card->ctx); + sc_log(card->ctx, -+ "IDPrime decipher: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u", -+ crgram_len, outlen); ++ "IDPrime decipher: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u", ++ crgram_len, outlen); + + sbuf = malloc(crgram_len + 1); + if (sbuf == NULL) @@ -833,10 +891,32 @@ diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/li +{ + return sc_get_driver(); +} -diff -up opensc-0.19.0/src/libopensc/cards.h.idprime opensc-0.19.0/src/libopensc/cards.h ---- opensc-0.19.0/src/libopensc/cards.h.idprime 2019-11-14 09:42:03.561199025 +0100 -+++ opensc-0.19.0/src/libopensc/cards.h 2019-11-14 09:45:23.000180086 +0100 -@@ -240,6 +240,7 @@ enum { +diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h +index ac1969256b..7bba7e6687 100644 +--- a/src/libopensc/cardctl.h ++++ b/src/libopensc/cardctl.h +@@ -303,6 +303,16 @@ enum { + SC_CARDCTL_GIDS_INITIALIZE, + SC_CARDCTL_GIDS_SET_ADMIN_KEY, + SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, ++ ++ /* ++ * IDPrime specific calls ++ */ ++ SC_CARDCTL_IDPRIME_BASE = _CTL_PREFIX('I', 'D', 'P'), ++ SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS, ++ SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT, ++ SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, ++ SC_CARDCTL_IDPRIME_GET_TOKEN_NAME, ++ + }; + + enum { +diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h +index 24d73c094a..cb0501c3aa 100644 +--- a/src/libopensc/cards.h ++++ b/src/libopensc/cards.h +@@ -234,6 +234,7 @@ enum { /* JPKI cards */ SC_CARD_TYPE_JPKI_BASE = 31000, @@ -844,10 +924,10 @@ diff -up opensc-0.19.0/src/libopensc/cards.h.idprime opensc-0.19.0/src/libopensc SC_CARD_TYPE_COOLKEY_BASE = 32000, SC_CARD_TYPE_COOLKEY_GENERIC, -@@ -253,6 +254,12 @@ enum { - SC_CARD_TYPE_NPA = 34000, - SC_CARD_TYPE_NPA_TEST, - SC_CARD_TYPE_NPA_ONLINE, +@@ -258,6 +259,12 @@ enum { + SC_CARD_TYPE_RUTOKEN_ECP_SC, + SC_CARD_TYPE_RUTOKEN_LITE, + SC_CARD_TYPE_RUTOKEN_LITE_SC, + + /* IDPrime cards */ + SC_CARD_TYPE_IDPRIME_BASE = 37000, @@ -857,69 +937,31 @@ diff -up opensc-0.19.0/src/libopensc/cards.h.idprime opensc-0.19.0/src/libopensc }; extern sc_card_driver_t *sc_get_default_driver(void); -@@ -296,6 +303,7 @@ extern sc_card_driver_t *sc_get_coolkey_ - extern sc_card_driver_t *sc_get_cac_driver(void); +@@ -301,6 +308,7 @@ extern sc_card_driver_t *sc_get_cac_driver(void); extern sc_card_driver_t *sc_get_cac1_driver(void); extern sc_card_driver_t *sc_get_npa_driver(void); + extern sc_card_driver_t *sc_get_esteid2018_driver(void); +extern sc_card_driver_t *sc_get_idprime_driver(void); #ifdef __cplusplus } -diff -up opensc-0.19.0/src/libopensc/ctx.c.idprime opensc-0.19.0/src/libopensc/ctx.c ---- opensc-0.19.0/src/libopensc/ctx.c.idprime 2019-11-14 09:42:03.564199055 +0100 -+++ opensc-0.19.0/src/libopensc/ctx.c 2019-11-14 09:46:07.142618618 +0100 -@@ -147,6 +147,7 @@ static const struct _sc_driver_entry int - { "jpki", (void *(*)(void)) sc_get_jpki_driver }, - { "npa", (void *(*)(void)) sc_get_npa_driver }, - { "cac1", (void *(*)(void)) sc_get_cac1_driver }, +diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c +index 40f573ed0f..4c5adc6e5f 100644 +--- a/src/libopensc/ctx.c ++++ b/src/libopensc/ctx.c +@@ -128,6 +128,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = { + { "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver }, + { "westcos", (void *(*)(void)) sc_get_westcos_driver }, + { "esteid2018", (void *(*)(void)) sc_get_esteid2018_driver }, + { "idprime", (void *(*)(void)) sc_get_idprime_driver }, - /* The default driver should be last, as it handles all the - * unrecognized cards. */ - { "default", (void *(*)(void)) sc_get_default_driver }, -diff -up opensc-0.19.0/src/libopensc/Makefile.am.idprime opensc-0.19.0/src/libopensc/Makefile.am ---- opensc-0.19.0/src/libopensc/Makefile.am.idprime 2019-11-14 09:42:03.562199036 +0100 -+++ opensc-0.19.0/src/libopensc/Makefile.am 2019-11-14 09:43:42.168178253 +0100 -@@ -48,14 +48,14 @@ libopensc_la_SOURCES_BASE = \ - card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ - card-dnie.c cwa14890.c cwa-dnie.c \ - card-isoApplet.c card-masktech.c card-gids.c card-jpki.c \ -- card-npa.c \ -+ card-npa.c card-idprime.c \ - \ - pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \ - pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \ - pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \ - pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ - pkcs15-oberthur.c pkcs15-itacns.c pkcs15-gemsafeV1.c pkcs15-sc-hsm.c \ -- pkcs15-coolkey.c pkcs15-din-66291.c \ -+ pkcs15-coolkey.c pkcs15-din-66291.c pkcs15-idprime.c \ - pkcs15-dnie.c pkcs15-gids.c pkcs15-iasecc.c pkcs15-jpki.c \ - compression.c p15card-helper.c sm.c \ - aux-data.c -diff -up opensc-0.19.0/src/libopensc/Makefile.mak.idprime opensc-0.19.0/src/libopensc/Makefile.mak ---- opensc-0.19.0/src/libopensc/Makefile.mak.idprime 2019-11-14 09:42:03.563199045 +0100 -+++ opensc-0.19.0/src/libopensc/Makefile.mak 2019-11-14 09:44:42.339776109 +0100 -@@ -27,14 +27,14 @@ OBJECTS = \ - card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \ - card-sc-hsm.obj card-dnie.obj card-isoApplet.obj pkcs15-coolkey.obj \ - card-masktech.obj card-gids.obj card-jpki.obj \ -- card-npa.obj \ -+ card-npa.obj card-idprime.obj \ - \ - pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \ - pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.obj \ - pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \ - pkcs15-cac.obj pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-din-66291.obj \ - pkcs15-oberthur.obj pkcs15-itacns.obj pkcs15-gemsafeV1.obj pkcs15-sc-hsm.obj \ -- pkcs15-dnie.obj pkcs15-gids.obj pkcs15-iasecc.obj pkcs15-jpki.obj \ -+ pkcs15-dnie.obj pkcs15-gids.obj pkcs15-iasecc.obj pkcs15-jpki.obj pkcs15-idprime.obj \ - compression.obj p15card-helper.obj sm.obj \ - aux-data.obj \ - $(TOPDIR)\win32\versioninfo.res -diff -up opensc-0.19.0/src/libopensc/opensc.h.idprime opensc-0.19.0/src/libopensc/opensc.h ---- opensc-0.19.0/src/libopensc/opensc.h.idprime 2019-11-14 09:42:03.524198658 +0100 -+++ opensc-0.19.0/src/libopensc/opensc.h 2019-11-14 09:42:03.564199055 +0100 -@@ -98,12 +98,13 @@ extern "C" { + + /* Here should be placed drivers that need some APDU transactions in the + * driver's `match_card()` function. */ +diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h +index d8ec42174e..10bea0a013 100644 +--- a/src/libopensc/opensc.h ++++ b/src/libopensc/opensc.h +@@ -107,12 +107,13 @@ extern "C" { * 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 @@ -934,10 +976,11 @@ diff -up opensc-0.19.0/src/libopensc/opensc.h.idprime opensc-0.19.0/src/libopens /* If the card is willing to produce a cryptogram with the following * hash values, set these flags accordingly. The interpretation of the hash -diff -up opensc-0.19.0/src/libopensc/padding.c.idprime opensc-0.19.0/src/libopensc/padding.c ---- opensc-0.19.0/src/libopensc/padding.c.idprime 2019-11-14 09:42:03.540198817 +0100 -+++ opensc-0.19.0/src/libopensc/padding.c 2019-11-14 09:42:03.564199055 +0100 -@@ -499,6 +499,7 @@ int sc_get_encoding_flags(sc_context_t * +diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c +index 4a8fc17b9c..5bcb2bb8d9 100644 +--- a/src/libopensc/padding.c ++++ b/src/libopensc/padding.c +@@ -499,6 +499,7 @@ int sc_get_encoding_flags(sc_context_t *ctx, /* Use the card's raw RSA capability on the padded input */ *sflags = SC_ALGORITHM_RSA_PAD_NONE; *pflags = iflags; @@ -945,10 +988,11 @@ diff -up opensc-0.19.0/src/libopensc/padding.c.idprime opensc-0.19.0/src/libopen } else if ((caps & (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) && (iflags & SC_ALGORITHM_RSA_PAD_PKCS1)) { -diff -up opensc-0.19.0/src/libopensc/pkcs15-cac.c.idprime opensc-0.19.0/src/libopensc/pkcs15-cac.c ---- opensc-0.19.0/src/libopensc/pkcs15-cac.c.idprime 2019-11-14 09:42:03.546198876 +0100 -+++ opensc-0.19.0/src/libopensc/pkcs15-cac.c 2019-11-14 09:46:46.655011155 +0100 -@@ -87,89 +87,6 @@ static const char * cac_get_name(int typ +diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c +index d637dedf19..e8c13d5fea 100644 +--- a/src/libopensc/pkcs15-cac.c ++++ b/src/libopensc/pkcs15-cac.c +@@ -84,89 +84,6 @@ static const char * cac_get_name(int type) return ("CAC"); } @@ -1038,7 +1082,7 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-cac.c.idprime opensc-0.19.0/src/libo static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) { static const pindata pins[] = { -@@ -408,9 +325,9 @@ static int sc_pkcs15emu_cac_init(sc_pkcs +@@ -407,9 +324,9 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL); if (r < 0) { @@ -1047,13 +1091,14 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-cac.c.idprime opensc-0.19.0/src/libo } - cac_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); + sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n", + sc_log(card->ctx, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n", sc_dump_hex(cert_info.id.value, cert_info.id.len), usage, pubkey_info.usage, prkey_info.usage); -diff -up opensc-0.19.0/src/libopensc/pkcs15-cert.c.idprime opensc-0.19.0/src/libopensc/pkcs15-cert.c ---- opensc-0.19.0/src/libopensc/pkcs15-cert.c.idprime 2018-09-13 13:52:42.000000000 +0200 -+++ opensc-0.19.0/src/libopensc/pkcs15-cert.c 2019-11-14 09:42:03.565199065 +0100 -@@ -257,6 +257,8 @@ sc_pkcs15_get_extension(struct sc_contex +diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c +index 8606d14af0..7850fad8d8 100644 +--- a/src/libopensc/pkcs15-cert.c ++++ b/src/libopensc/pkcs15-cert.c +@@ -257,6 +257,8 @@ sc_pkcs15_get_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert, { NULL, 0, 0, 0, NULL, NULL } }; @@ -1062,7 +1107,7 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-cert.c.idprime opensc-0.19.0/src/lib for (next_ext = cert->extensions, next_ext_len = cert->extensions_len; next_ext_len; ) { /* unwrap the set and point to the next ava */ ext = sc_asn1_skip_tag(ctx, &next_ext, &next_ext_len, -@@ -322,6 +324,8 @@ sc_pkcs15_get_bitstring_extension(struct +@@ -324,6 +326,8 @@ sc_pkcs15_get_bitstring_extension(struct sc_context *ctx, { NULL, 0, 0, 0, NULL, NULL } }; @@ -1071,7 +1116,7 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-cert.c.idprime opensc-0.19.0/src/lib r = sc_pkcs15_get_extension(ctx, cert, type, &bit_string, &bit_string_len, is_critical); LOG_TEST_RET(ctx, r, "Get extension error"); -@@ -533,6 +537,88 @@ sc_pkcs15_encode_cdf_entry(sc_context_t +@@ -550,6 +554,88 @@ sc_pkcs15_encode_cdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj return r; } @@ -1160,22 +1205,11 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-cert.c.idprime opensc-0.19.0/src/lib void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert) -diff -up opensc-0.19.0/src/libopensc/pkcs15.h.idprime opensc-0.19.0/src/libopensc/pkcs15.h ---- opensc-0.19.0/src/libopensc/pkcs15.h.idprime 2018-09-13 13:52:42.000000000 +0200 -+++ opensc-0.19.0/src/libopensc/pkcs15.h 2019-11-14 09:42:03.565199065 +0100 -@@ -732,6 +732,9 @@ int sc_pkcs15_get_name_from_dn(struct sc - const u8 *dn, size_t dn_len, - const struct sc_object_id *type, - u8 **name, size_t *name_len); -+int sc_pkcs15_map_usage(unsigned int cert_usage, int algorithm, -+ unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, -+ int allow_nonrepudiation); - int sc_pkcs15_get_extension(struct sc_context *ctx, - struct sc_pkcs15_cert *cert, - const struct sc_object_id *type, -diff -up opensc-0.19.0/src/libopensc/pkcs15-idprime.c.idprime opensc-0.19.0/src/libopensc/pkcs15-idprime.c ---- opensc-0.19.0/src/libopensc/pkcs15-idprime.c.idprime 2019-11-14 09:42:03.565199065 +0100 -+++ opensc-0.19.0/src/libopensc/pkcs15-idprime.c 2019-11-14 09:49:19.494529520 +0100 +diff --git a/src/libopensc/pkcs15-idprime.c b/src/libopensc/pkcs15-idprime.c +new file mode 100644 +index 0000000000..d882696997 +--- /dev/null ++++ b/src/libopensc/pkcs15-idprime.c @@ -0,0 +1,286 @@ +/* + * partial PKCS15 emulation for IDPrime cards. @@ -1212,6 +1246,8 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-idprime.c.idprime opensc-0.19.0/src/ +#include "pkcs15.h" + +#define CERT_LABEL_TEMPLATE "Certificate %d" ++#define PUBKEY_LABEL_TEMPLATE "Public key %d" ++#define PRIVKEY_LABEL_TEMPLATE "Private key %d" + +static int idprime_detect_card(sc_pkcs15_card_t *p15card) +{ @@ -1271,8 +1307,8 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-idprime.c.idprime opensc-0.19.0/src/ + pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_INITIALIZED; + pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; + pin_info.attrs.pin.min_length = 4; -+ pin_info.attrs.pin.stored_length = 12; -+ pin_info.attrs.pin.max_length = 12; ++ pin_info.attrs.pin.stored_length = 0; ++ pin_info.attrs.pin.max_length = 16; + pin_info.tries_left = -1; + + sc_log(card->ctx, "IDPrime Adding pin with label=%s", pin_label); @@ -1339,8 +1375,8 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-idprime.c.idprime opensc-0.19.0/src/ + prkey_info.native = 1; + + snprintf(cert_obj.label, SC_PKCS15_MAX_LABEL_SIZE, CERT_LABEL_TEMPLATE, i+1); -+ snprintf(pubkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, CERT_LABEL_TEMPLATE, i+1); -+ snprintf(prkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, CERT_LABEL_TEMPLATE, i+1); ++ snprintf(pubkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, PUBKEY_LABEL_TEMPLATE, i+1); ++ snprintf(prkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, PRIVKEY_LABEL_TEMPLATE, i+1); + prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; + sc_pkcs15_format_id(pin_id, &prkey_obj.auth_id); + @@ -1426,12 +1462,14 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-idprime.c.idprime opensc-0.19.0/src/ + } else { + pubkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; + prkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; -+ r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); + sc_log(card->ctx, "adding rsa public key r=%d usage=%x",r, pubkey_info.usage); ++ r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); + if (r < 0) + goto fail; -+ r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); + sc_log(card->ctx, "adding rsa private key r=%d usage=%x",r, prkey_info.usage); ++ r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); ++ if (r < 0) ++ goto fail; + } + + cert_out->key = NULL; @@ -1448,46 +1486,82 @@ diff -up opensc-0.19.0/src/libopensc/pkcs15-idprime.c.idprime opensc-0.19.0/src/ +} + +int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, -+ struct sc_aid *aid, sc_pkcs15emu_opt_t *opts) ++ struct sc_aid *aid) +{ + sc_card_t *card = p15card->card; + sc_context_t *ctx = card->ctx; + + LOG_FUNC_CALLED(ctx); + -+ if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK) -+ return sc_pkcs15emu_idprime_init(p15card); -+ else { -+ if (idprime_detect_card(p15card)) -+ return SC_ERROR_WRONG_CARD; -+ return sc_pkcs15emu_idprime_init(p15card); -+ } ++ if (idprime_detect_card(p15card)) ++ return SC_ERROR_WRONG_CARD; ++ return sc_pkcs15emu_idprime_init(p15card); +} -diff -up opensc-0.19.0/src/libopensc/pkcs15-syn.c.idprime opensc-0.19.0/src/libopensc/pkcs15-syn.c ---- opensc-0.19.0/src/libopensc/pkcs15-syn.c.idprime 2019-11-14 09:42:03.565199065 +0100 -+++ opensc-0.19.0/src/libopensc/pkcs15-syn.c 2019-11-14 09:47:10.851251524 +0100 -@@ -45,6 +45,7 @@ struct sc_pkcs15_emulator_handler builti - { "postecert", sc_pkcs15emu_postecert_init_ex }, +diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c +index facb0a607c..279a001e9d 100644 +--- a/src/libopensc/pkcs15-syn.c ++++ b/src/libopensc/pkcs15-syn.c +@@ -43,22 +43,23 @@ struct sc_pkcs15_emulator_handler builtin_emulators[] = { + { "itacns", sc_pkcs15emu_itacns_init_ex }, { "PIV-II", sc_pkcs15emu_piv_init_ex }, { "cac", sc_pkcs15emu_cac_init_ex }, + { "idprime", sc_pkcs15emu_idprime_init_ex }, { "gemsafeGPK", sc_pkcs15emu_gemsafeGPK_init_ex }, { "gemsafeV1", sc_pkcs15emu_gemsafeV1_init_ex }, { "actalis", sc_pkcs15emu_actalis_init_ex }, -diff -up opensc-0.19.0/src/libopensc/pkcs15-syn.h.idprime opensc-0.19.0/src/libopensc/pkcs15-syn.h ---- opensc-0.19.0/src/libopensc/pkcs15-syn.h.idprime 2019-11-14 09:42:03.565199065 +0100 -+++ opensc-0.19.0/src/libopensc/pkcs15-syn.h 2019-11-14 09:47:34.499486456 +0100 -@@ -54,6 +54,7 @@ int sc_pkcs15emu_iasecc_init_ex(sc_pkcs1 - int sc_pkcs15emu_jpki_init_ex(sc_pkcs15_card_t *, struct sc_aid *, sc_pkcs15emu_opt_t *); - int sc_pkcs15emu_coolkey_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *, sc_pkcs15emu_opt_t *opts); - int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *, sc_pkcs15emu_opt_t *opts); -+int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *, sc_pkcs15emu_opt_t *opts); + { "atrust-acos",sc_pkcs15emu_atrust_acos_init_ex}, + { "tccardos", sc_pkcs15emu_tccardos_init_ex }, +- { "entersafe", sc_pkcs15emu_entersafe_init_ex }, ++ { "entersafe", sc_pkcs15emu_entersafe_init_ex }, + { "pteid", sc_pkcs15emu_pteid_init_ex }, + { "oberthur", sc_pkcs15emu_oberthur_init_ex }, + { "sc-hsm", sc_pkcs15emu_sc_hsm_init_ex }, +- { "dnie", sc_pkcs15emu_dnie_init_ex }, +- { "gids", sc_pkcs15emu_gids_init_ex }, +- { "iasecc", sc_pkcs15emu_iasecc_init_ex }, +- { "jpki", sc_pkcs15emu_jpki_init_ex }, ++ { "dnie", sc_pkcs15emu_dnie_init_ex }, ++ { "gids", sc_pkcs15emu_gids_init_ex }, ++ { "iasecc", sc_pkcs15emu_iasecc_init_ex }, ++ { "jpki", sc_pkcs15emu_jpki_init_ex }, + { "coolkey", sc_pkcs15emu_coolkey_init_ex }, +- { "din66291", sc_pkcs15emu_din_66291_init_ex }, +- { "esteid2018", sc_pkcs15emu_esteid2018_init_ex }, ++ { "din66291", sc_pkcs15emu_din_66291_init_ex }, ++ { "esteid2018", sc_pkcs15emu_esteid2018_init_ex }, + + { NULL, NULL } + }; +diff --git a/src/libopensc/pkcs15-syn.h b/src/libopensc/pkcs15-syn.h +index 6811b3dab1..ccaf693ca4 100644 +--- a/src/libopensc/pkcs15-syn.h ++++ b/src/libopensc/pkcs15-syn.h +@@ -53,6 +53,7 @@ int sc_pkcs15emu_iasecc_init_ex(sc_pkcs15_card_t *, struct sc_aid *); + int sc_pkcs15emu_jpki_init_ex(sc_pkcs15_card_t *, struct sc_aid *); + int sc_pkcs15emu_coolkey_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); + int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); ++int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); struct sc_pkcs15_emulator_handler { const char *name; -diff -up opensc-0.19.0/src/libopensc/simpletlv.h.idprime opensc-0.19.0/src/libopensc/simpletlv.h ---- opensc-0.19.0/src/libopensc/simpletlv.h.idprime 2018-09-13 13:52:42.000000000 +0200 -+++ opensc-0.19.0/src/libopensc/simpletlv.h 2019-11-14 09:42:03.565199065 +0100 +diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h +index f2ccc42aed..df1435ce92 100644 +--- a/src/libopensc/pkcs15.h ++++ b/src/libopensc/pkcs15.h +@@ -754,6 +754,9 @@ int sc_pkcs15_get_name_from_dn(struct sc_context *ctx, + const u8 *dn, size_t dn_len, + const struct sc_object_id *type, + u8 **name, size_t *name_len); ++int sc_pkcs15_map_usage(unsigned int cert_usage, int algorithm, ++ unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, ++ int allow_nonrepudiation); + int sc_pkcs15_get_extension(struct sc_context *ctx, + struct sc_pkcs15_cert *cert, + const struct sc_object_id *type, +diff --git a/src/libopensc/simpletlv.h b/src/libopensc/simpletlv.h +index a952779733..6bcd4f0856 100644 +--- a/src/libopensc/simpletlv.h ++++ b/src/libopensc/simpletlv.h @@ -29,7 +29,6 @@ extern "C" { #endif @@ -1496,10 +1570,11 @@ diff -up opensc-0.19.0/src/libopensc/simpletlv.h.idprime opensc-0.19.0/src/libop /* * Create a tag/length file in Simple TLV based on the val_len content length -diff -up opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime opensc-0.19.0/src/pkcs11/framework-pkcs15.c ---- opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime 2019-11-14 09:42:03.537198787 +0100 -+++ opensc-0.19.0/src/pkcs11/framework-pkcs15.c 2019-11-14 09:42:03.566199075 +0100 -@@ -3796,7 +3796,7 @@ pkcs15_prkey_sign(struct sc_pkcs11_sessi +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index 22081ffef1..e94eeeffec 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -3976,7 +3976,7 @@ pkcs15_prkey_sign(struct sc_pkcs11_session *session, void *obj, /* Check the data length matches the selected hash */ rv = pkcs15_prkey_check_pss_param(pMechanism, (int)ulDataLen); if (rv != CKR_OK) { @@ -1508,7 +1583,7 @@ diff -up opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime opensc-0.19.0/src/p "PSS parameters"); return rv; } -@@ -3931,6 +3931,39 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se +@@ -4179,6 +4179,39 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj, case CKM_RSA_X_509: flags |= SC_ALGORITHM_RSA_RAW; break; @@ -1548,7 +1623,7 @@ diff -up opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime opensc-0.19.0/src/p default: return CKR_MECHANISM_INVALID; } -@@ -4100,6 +4133,7 @@ pkcs15_prkey_init_params(struct sc_pkcs1 +@@ -4352,6 +4385,7 @@ pkcs15_prkey_init_params(struct sc_pkcs11_session *session, 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 }; @@ -1556,7 +1631,7 @@ diff -up opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime opensc-0.19.0/src/p switch (pMechanism->mechanism) { case CKM_RSA_PKCS_PSS: -@@ -4155,6 +4189,18 @@ pkcs15_prkey_init_params(struct sc_pkcs1 +@@ -4407,6 +4441,26 @@ pkcs15_prkey_init_params(struct sc_pkcs11_session *session, /* TODO support different salt lengths */ break; @@ -1566,16 +1641,24 @@ diff -up opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime opensc-0.19.0/src/p + return CKR_MECHANISM_PARAM_INVALID; + + oaep_params = (CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter; -+ if (oaep_params->mgf < CKG_MGF1_SHA1 || oaep_params->mgf > CKG_MGF1_SHA224) ++ switch (oaep_params->mgf) { ++ case CKG_MGF1_SHA1: ++ case CKG_MGF1_SHA224: ++ case CKG_MGF1_SHA256: ++ case CKG_MGF1_SHA384: ++ case CKG_MGF1_SHA512: ++ /* OK */ ++ break; ++ default: + return CKR_MECHANISM_PARAM_INVALID; -+ ++ } + /* TODO support different salt lengths */ + /* TODO is there something more to check */ + break; } return CKR_OK; } -@@ -5117,6 +5163,7 @@ register_mechanisms(struct sc_pkcs11_car +@@ -5619,6 +5673,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) rsa_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; #ifdef ENABLE_OPENSSL rsa_flags |= SC_ALGORITHM_RSA_PAD_PSS; @@ -1583,7 +1666,7 @@ diff -up opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime opensc-0.19.0/src/p #endif } -@@ -5197,6 +5244,7 @@ register_mechanisms(struct sc_pkcs11_car +@@ -5699,6 +5754,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) } if (rsa_flags & SC_ALGORITHM_RSA_PAD_PSS) { @@ -1591,7 +1674,7 @@ diff -up opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime opensc-0.19.0/src/p 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); -@@ -5233,6 +5281,18 @@ register_mechanisms(struct sc_pkcs11_car +@@ -5735,6 +5791,18 @@ register_mechanisms(struct sc_pkcs11_card *p11card) if (rc != CKR_OK) return rc; } @@ -1610,11 +1693,12 @@ diff -up opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime opensc-0.19.0/src/p } if (rsa_flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { -diff -up opensc-0.19.0/src/pkcs11/mechanism.c.idprime opensc-0.19.0/src/pkcs11/mechanism.c ---- opensc-0.19.0/src/pkcs11/mechanism.c.idprime 2019-11-14 09:42:03.525198668 +0100 -+++ opensc-0.19.0/src/pkcs11/mechanism.c 2019-11-14 09:42:03.566199075 +0100 -@@ -803,6 +803,15 @@ sc_pkcs11_decr_init(struct sc_pkcs11_ses - memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM)); +diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c +index 358cad40fd..983d8dcbdf 100644 +--- a/src/pkcs11/mechanism.c ++++ b/src/pkcs11/mechanism.c +@@ -811,6 +811,15 @@ sc_pkcs11_decr_init(struct sc_pkcs11_session *session, + } rv = mt->decrypt_init(operation, key); + /* Validate the mechanism parameters */ @@ -1629,10 +1713,99 @@ diff -up opensc-0.19.0/src/pkcs11/mechanism.c.idprime opensc-0.19.0/src/pkcs11/m if (rv != CKR_OK) session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT); -diff -up opensc-0.19.0/src/tools/opensc-tool.c.idprime opensc-0.19.0/src/tools/opensc-tool.c ---- opensc-0.19.0/src/tools/opensc-tool.c.idprime 2018-09-13 13:52:42.000000000 +0200 -+++ opensc-0.19.0/src/tools/opensc-tool.c 2019-11-14 09:42:03.566199075 +0100 -@@ -593,6 +593,7 @@ static int list_algorithms(void) +diff --git a/src/tests/p11test/p11test_case_common.c b/src/tests/p11test/p11test_case_common.c +index bd4b39af74..22e639cf49 100644 +--- a/src/tests/p11test/p11test_case_common.c ++++ b/src/tests/p11test/p11test_case_common.c +@@ -422,7 +422,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + CK_OBJECT_HANDLE object_handle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE_PTR object_handles = NULL; + unsigned long i = 0, objects_length = 0; +- int j; ++ int j, ret = -1; + + /* FindObjects first + * https://wiki.oasis-open.org/pkcs11/CommonBugs +@@ -439,16 +439,18 @@ int search_objects(test_certs_t *objects, token_info_t *info, + break; + if (rv != CKR_OK) { + fprintf(stderr, "C_FindObjects: rv = 0x%.8lX\n", rv); +- return -1; ++ goto out; + } + /* store handle */ + if (i >= objects_length) { ++ CK_OBJECT_HANDLE_PTR new_object_handles = NULL; + objects_length += 4; // do not realloc after each row +- object_handles = realloc(object_handles, objects_length * sizeof(CK_OBJECT_HANDLE)); +- if (object_handles == NULL) { ++ new_object_handles = realloc(object_handles, objects_length * sizeof(CK_OBJECT_HANDLE)); ++ if (new_object_handles == NULL) { + fail_msg("Realloc failed. Need to store object handles.\n"); +- return -1; ++ goto out; + } ++ object_handles = new_object_handles; + } + object_handles[i++] = object_handle; + } +@@ -458,8 +460,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + if (rv != CKR_OK) { + fprintf(stderr, "C_FindObjectsFinal: rv = 0x%.8lX\n", rv); + fail_msg("Could not find certificate.\n"); +- free(object_handles); +- return -1; ++ goto out; + } + + for (i = 0; i < objects_length; i++) { +@@ -476,8 +477,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + continue; + } else if (rv != CKR_OK) { + fail_msg("C_GetAttributeValue: rv = 0x%.8lX\n", rv); +- free(object_handles); +- return -1; ++ goto out; + } + + /* Allocate memory to hold the data we want */ +@@ -487,8 +487,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + template[j].pValue = malloc(template[j].ulValueLen); + if (template[j].pValue == NULL) { + fail_msg("malloc failed"); +- free(object_handles); +- return -1; ++ goto out; + } + } + /* Call again to get actual attribute */ +@@ -496,8 +495,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + &(template[j]), 1); + if (rv != CKR_OK) { + fail_msg("C_GetAttributeValue: rv = 0x%.8lX\n", rv); +- free(object_handles); +- return -1; ++ goto out; + } + } + +@@ -506,8 +504,10 @@ int search_objects(test_certs_t *objects, token_info_t *info, + for (j = 0; j < template_size; j++) + free(template[j].pValue); + } ++ ret = 0; ++out: + free(object_handles); +- return 0; ++ return ret; + } + + void search_for_all_objects(test_certs_t *objects, token_info_t *info) +diff --git a/src/tools/opensc-tool.c b/src/tools/opensc-tool.c +index f829332fd8..52b570d9bf 100644 +--- a/src/tools/opensc-tool.c ++++ b/src/tools/opensc-tool.c +@@ -594,6 +594,7 @@ static int list_algorithms(void) { SC_ALGORITHM_RSA_PAD_PKCS1, "pkcs1" }, { SC_ALGORITHM_RSA_PAD_ANSI, "ansi" }, { SC_ALGORITHM_RSA_PAD_PSS, "pss" }, @@ -1640,10 +1813,11 @@ diff -up opensc-0.19.0/src/tools/opensc-tool.c.idprime opensc-0.19.0/src/tools/o { SC_ALGORITHM_RSA_PAD_ISO9796, "iso9796" }, { SC_ALGORITHM_RSA_HASH_SHA1, "sha1" }, { SC_ALGORITHM_RSA_HASH_MD5, "MD5" }, -diff -up opensc-0.19.0/src/tools/pkcs11-tool.c.idprime opensc-0.19.0/src/tools/pkcs11-tool.c ---- opensc-0.19.0/src/tools/pkcs11-tool.c.idprime 2019-11-14 09:42:03.550198916 +0100 -+++ opensc-0.19.0/src/tools/pkcs11-tool.c 2019-11-14 09:50:17.950110055 +0100 -@@ -2037,9 +2037,15 @@ static void decrypt_data(CK_SLOT_ID slot +diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c +index 92c8d8a506..6a8e27ee69 100644 +--- a/src/tools/pkcs11-tool.c ++++ b/src/tools/pkcs11-tool.c +@@ -2127,9 +2127,15 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, case CKM_RSA_PKCS_OAEP: oaep_params.hashAlg = opt_hash_alg; switch (opt_hash_alg) { @@ -1659,11 +1833,11 @@ diff -up opensc-0.19.0/src/tools/pkcs11-tool.c.idprime opensc-0.19.0/src/tools/p case CKM_SHA256: oaep_params.mgf = CKG_MGF1_SHA256; break; -@@ -2049,12 +2055,6 @@ static void decrypt_data(CK_SLOT_ID slot +@@ -2139,12 +2145,6 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, case CKM_SHA512: oaep_params.mgf = CKG_MGF1_SHA512; break; -- default: +- default: - oaep_params.hashAlg = CKM_SHA_1; - /* fall through */ - case CKM_SHA_1: @@ -1671,4 +1845,4 @@ diff -up opensc-0.19.0/src/tools/pkcs11-tool.c.idprime opensc-0.19.0/src/tools/p - break; } break; - case CKM_RSA_PKCS: + case CKM_RSA_X_509: diff --git a/SOURCES/opensc-0.19.0-rsa-pss.patch b/SOURCES/opensc-0.19.0-rsa-pss.patch deleted file mode 100644 index 2842071..0000000 --- a/SOURCES/opensc-0.19.0-rsa-pss.patch +++ /dev/null @@ -1,2385 +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 - -From d517d8e18d9c7f918e38de7e613e34f6b3d21f09 Mon Sep 17 00:00:00 2001 -From: Luka Logar -Date: Thu, 11 Oct 2018 11:22:15 +0200 -Subject: [PATCH] Fix minidriver padding - -Commit e5707b545e5a2dc33b0ca52a8bf63f36f71b3d85 broke signing using minidriver on Windows. - -More specifically changing #define SC_ALGORITHM_RSA_PAD_NONE from 0x00000000 to 0x00000001 caused a call to sc_pkcs1_encode() to fail as the padding algorithm was not specified anywhere in the CardSignData() implementation. It kind of worked as long as SC_ALGORITHM_RSA_PAD_NONE was 0x00000000, but the above mentioned commit broke this. - -Now padding algorithm has to be explicitly specified, otherwise a call to sc_pkcs1_encode() will fail. ---- - src/libopensc/padding.c | 2 +- - src/minidriver/minidriver.c | 1 + - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c -index 53a87c352e..934fc67d11 100644 ---- a/src/libopensc/padding.c -+++ b/src/libopensc/padding.c -@@ -412,7 +412,7 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags, - pad_algo = flags & SC_ALGORITHM_RSA_PADS; - sc_log(ctx, "hash algorithm 0x%X, pad algorithm 0x%X", hash_algo, pad_algo); - -- if ((pad_algo == SC_ALGORITHM_RSA_PAD_PKCS1 || !pad_algo) && -+ if ((pad_algo == SC_ALGORITHM_RSA_PAD_PKCS1 || pad_algo == SC_ALGORITHM_RSA_PAD_NONE) && - 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) { - -From ba2bcb3fd763a791750506ec30283cca0d1870cd Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 12 Dec 2018 10:55:39 +0100 -Subject: [PATCH 5/7] padding: Resotre the PAD_NONE if nothing else is - specified - -Patch from Doug Engert ---- - src/libopensc/padding.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c -index 047b3bc82c..3456a6265a 100644 ---- a/src/libopensc/padding.c -+++ b/src/libopensc/padding.c -@@ -410,6 +410,8 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags, - - hash_algo = flags & SC_ALGORITHM_RSA_HASHES; - pad_algo = flags & SC_ALGORITHM_RSA_PADS; -+ if (pad_algo == 0) -+ pad_algo = SC_ALGORITHM_RSA_PAD_NONE; - sc_log(ctx, "hash algorithm 0x%X, pad algorithm 0x%X", hash_algo, pad_algo); - - if ((pad_algo == SC_ALGORITHM_RSA_PAD_PKCS1 || pad_algo == SC_ALGORITHM_RSA_PAD_NONE) && - -From 8c535c184f41dff417eb23069fec511f911f8ae6 Mon Sep 17 00:00:00 2001 -From: Frank Morgner -Date: Thu, 4 Oct 2018 15:59:11 +0200 -Subject: [PATCH] removed duplicate code for adding padding - -Fixes padding handling of SC_ALGORITHM_RSA_PAD_NONE introduced with -e5707b545e5a2dc33b0ca52a8bf63f36f71b3d85 ---- - src/libopensc/padding.c | 9 ++- - src/minidriver/minidriver.c | 144 +++++++++++++++--------------------- - 2 files changed, 64 insertions(+), 89 deletions(-) - -diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c -index 934fc67d11..75c92b651a 100644 ---- a/src/libopensc/padding.c -+++ b/src/libopensc/padding.c -@@ -487,18 +487,19 @@ int sc_get_encoding_flags(sc_context_t *ctx, - *pflags = 0; - - } else if ((caps & SC_ALGORITHM_RSA_PAD_PSS) && -- (iflags & 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) { -+ (iflags & SC_ALGORITHM_RSA_PAD_PKCS1)) -+ || iflags & SC_ALGORITHM_RSA_PAD_PSS -+ || iflags & SC_ALGORITHM_RSA_PAD_NONE) { - /* 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)) { -+ (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; - -From b01beec4f82294d59b1cf737d5b74d0c194e98da Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 12 Dec 2018 11:56:31 +0100 -Subject: [PATCH 6/7] padding: Do not set wrong flags if the raw capability is - not available - -Thanks Doug Engert for pointing the issue out ---- - src/libopensc/padding.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c -index 3456a6265a..4a8fc17b9c 100644 ---- a/src/libopensc/padding.c -+++ b/src/libopensc/padding.c -@@ -492,10 +492,10 @@ int sc_get_encoding_flags(sc_context_t *ctx, - (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 -- || iflags & SC_ALGORITHM_RSA_PAD_NONE) { -+ } else if ((caps & SC_ALGORITHM_RSA_RAW) && -+ (iflags & SC_ALGORITHM_RSA_PAD_PKCS1 -+ || iflags & SC_ALGORITHM_RSA_PAD_PSS -+ || iflags & SC_ALGORITHM_RSA_PAD_NONE)) { - /* Use the card's raw RSA capability on the padded input */ - *sflags = SC_ALGORITHM_RSA_PAD_NONE; - *pflags = iflags; - diff --git a/SOURCES/opensc-0.20.0-cardos.patch b/SOURCES/opensc-0.20.0-cardos.patch new file mode 100644 index 0000000..b26b4ce --- /dev/null +++ b/SOURCES/opensc-0.20.0-cardos.patch @@ -0,0 +1,1338 @@ +From 592a641cb9f8eb17d4d1b1c9a96a1581f61e169b Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Sun, 29 Mar 2020 05:56:21 -0500 +Subject: [PATCH 2/6] pkcs11-tool - use valid data for decription tests + +In tests, make sute test data is either padded, or "zero" padded +so size if data <= modlen - 11. The smallest pad in 11 bytes, +00 | NN | PS | 00. PS is at least 8 bytes. +"zero" padding has N = 00, PS >= 8 byte of 00. + + On branch cardos-5.3 + Changes to be committed: + modified: tools/pkcs11-tool.c +--- + src/tools/pkcs11-tool.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c +index 3ad9289033..b1674a76cf 100644 +--- a/src/tools/pkcs11-tool.c ++++ b/src/tools/pkcs11-tool.c +@@ -5044,8 +5044,8 @@ static int test_signature(CK_SESSION_HANDLE sess) + } + + if (firstMechType == CKM_RSA_X_509) { +- /* make sure our data is smaller than the modulus */ +- data[0] = 0x00; ++ /* make sure our data is smaller than the modulus - 11 */ ++ memset(data, 0, 11); /* in effect is zero padding */ + } + + ck_mech.mechanism = firstMechType; + +From 3043f5b8a15c7cff90adcd2d31095afa734e663c Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Sun, 5 Apr 2020 11:04:42 -0500 +Subject: [PATCH 3/6] Increase SC_MAX_SUPPORTED_ALGORITHMS from 8 to 16 + +CardOS cards may have more then 8 supported_algo_info entries in tokenInfo. +We may bemissing some. We have seen 8 in some pkcs15-tool -i -v output. + +Simple fix is to incrase the limit. More appropriate fix is to remove the limit, +much like is done with sc_algorithm_info. and use realloc of the array. + + On branch cardos-5.3 + Changes to be committed: + modified: src/libopensc/pkcs15-prkey.c + modified: src/libopensc/pkcs15-skey.c + modified: src/libopensc/pkcs15.c + modified: src/libopensc/types.h +--- + src/libopensc/pkcs15-prkey.c | 10 +++++++++- + src/libopensc/pkcs15-skey.c | 10 +++++++++- + src/libopensc/pkcs15.c | 10 +++++++++- + src/libopensc/types.h | 6 ++++-- + 4 files changed, 31 insertions(+), 5 deletions(-) + +diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c +index ed008ede14..a6c05415ec 100644 +--- a/src/libopensc/pkcs15-prkey.c ++++ b/src/libopensc/pkcs15-prkey.c +@@ -48,10 +48,18 @@ + #include "aux-data.h" + + /* +- * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 ++ * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 + */ + #define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1) + static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = { ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, +diff --git a/src/libopensc/pkcs15-skey.c b/src/libopensc/pkcs15-skey.c +index b22e619723..4e58355ad7 100644 +--- a/src/libopensc/pkcs15-skey.c ++++ b/src/libopensc/pkcs15-skey.c +@@ -28,10 +28,18 @@ + #include + + /* +- * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 ++ * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 + */ + #define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1) + static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = { ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, +diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c +index ba04f531ef..d4a4496980 100644 +--- a/src/libopensc/pkcs15.c ++++ b/src/libopensc/pkcs15.c +@@ -64,9 +64,17 @@ static const struct sc_asn1_entry c_asn1_algorithm_info_parameters[3] = { + }; + + /* +- * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 ++ * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 + */ + static const struct sc_asn1_entry c_asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1] = { ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, +diff --git a/src/libopensc/types.h b/src/libopensc/types.h +index 76cf4c1a71..17035b5505 100644 +--- a/src/libopensc/types.h ++++ b/src/libopensc/types.h +@@ -52,9 +52,11 @@ typedef unsigned char u8; + + /* When changing this value, pay attention to the initialization of the ASN1 + * static variables that use this macro, like, for example, +- * 'c_asn1_supported_algorithms' in src/libopensc/pkcs15.c ++ * 'c_asn1_supported_algorithms' in src/libopensc/pkcs15.c, ++ * src/libopensc/pkcs15-prkey.c and src/libopensc/pkcs15-skey.c ++ * `grep "src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as"' + */ +-#define SC_MAX_SUPPORTED_ALGORITHMS 8 ++#define SC_MAX_SUPPORTED_ALGORITHMS 16 + + struct sc_lv_data { + unsigned char *value; + +From 8292ff57ad581995eca8209764813725594dd34f Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Fri, 17 Apr 2020 12:26:14 -0500 +Subject: [PATCH 4/6] sc_supported_algo_info - Put ECDSA OID as inline + + Mismatch of ASN1 parsing of tokeninfo.supported_algos[n].paramters + in one place parameter was treated as a pointer to sc_object_id + and in another as inline structure. This caused segfaults + in pkcs15-tool when it tried to print the OID. + + Changes to be committed: + modified: src/libopensc/opensc.h + modified: src/libopensc/pkcs15.c +--- + src/libopensc/opensc.h | 2 +- + src/libopensc/pkcs15.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h +index 9e764665b2..0c3c73e229 100644 +--- a/src/libopensc/opensc.h ++++ b/src/libopensc/opensc.h +@@ -223,7 +223,7 @@ extern "C" { + struct sc_supported_algo_info { + unsigned int reference; + unsigned int mechanism; +- struct sc_object_id *parameters; /* OID for ECC, NULL for RSA */ ++ struct sc_object_id parameters; /* OID for ECC */ + unsigned int operations; + struct sc_object_id algo_id; + unsigned int algo_ref; +diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c +index d4a4496980..c58c34fd13 100644 +--- a/src/libopensc/pkcs15.c ++++ b/src/libopensc/pkcs15.c +@@ -318,7 +318,7 @@ sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, + sc_format_asn1_entry(asn1_algo_infos[ii] + 1, &ti->supported_algos[ii].mechanism, &mechanism_len, 1); + sc_format_asn1_entry(asn1_algo_infos[ii] + 2, + asn1_algo_infos_parameters[ii], NULL, 1); +- if (!ti->supported_algos[ii].parameters) { ++ if (!sc_valid_oid(&ti->supported_algos[ii].parameters)) { + sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0, + NULL, NULL, 1); + } + +From f9665e4d46ed278b6cf1188e0e7adb5b6e119ac9 Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Thu, 26 Mar 2020 13:51:33 -0500 +Subject: [PATCH 5/6] pkcs15-tool.c - print Supported_algorithms from tokenInfo + +Some cards can provide supported algorithms in tokenInfo +which contain ECDSA OID, and PKCS11 mechanism + +Don't know how many Algo_refs were actually read, +and a ref of 0 may be valid. print at least one Algo_refs. + +Print the mechanism from PKCS11, and print operations +Use the $(top_srcdir)/src/pkcs11/pkcs11-display.c on Unix +Use the $(TOPDIR)\src\pkcs11\pkcs11-display.obj on Windows + +pkcs15.tool.c treat ECDSA OID as inline + +pkcs15-tool prints PKCS11 mechanisms using pkcs11-display.c +Automake now warns that the default will change, in the future +so "[subdir-objects]" is added to configure.ac + + Changes to be committed: + modified: configure.ac + modified: src/tools/Makefile.am + modified: src/tools/Makefile.mak + modified: src/tools/pkcs15-tool.c +--- + configure.ac | 2 +- + src/tools/Makefile.am | 2 +- + src/tools/Makefile.mak | 5 ++++ + src/tools/pkcs15-tool.c | 57 +++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 64 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 705bc027f1..f54093b0aa 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -27,7 +27,7 @@ AC_INIT([PRODUCT_NAME],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERS + AC_CONFIG_AUX_DIR([.]) + AC_CONFIG_HEADERS([config.h]) + AC_CONFIG_MACRO_DIR([m4]) +-AM_INIT_AUTOMAKE(foreign 1.10) ++AM_INIT_AUTOMAKE(foreign 1.10 [subdir-objects]) + + OPENSC_VERSION_MAJOR="PACKAGE_VERSION_MAJOR" + OPENSC_VERSION_MINOR="PACKAGE_VERSION_MINOR" +diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am +index 5ee5edfb29..55beb631d5 100644 +--- a/src/tools/Makefile.am ++++ b/src/tools/Makefile.am +@@ -52,7 +52,7 @@ piv_tool_SOURCES = piv-tool.c util.c + piv_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) + opensc_explorer_SOURCES = opensc-explorer.c util.c + opensc_explorer_LDADD = $(OPTIONAL_READLINE_LIBS) +-pkcs15_tool_SOURCES = pkcs15-tool.c util.c ++pkcs15_tool_SOURCES = pkcs15-tool.c util.c ../pkcs11/pkcs11-display.c ../pkcs11/pkcs11-display.h + pkcs15_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) + pkcs11_tool_SOURCES = pkcs11-tool.c util.c + pkcs11_tool_LDADD = \ +diff --git a/src/tools/Makefile.mak b/src/tools/Makefile.mak +index 4637a44dc6..38e5ba4e7e 100644 +--- a/src/tools/Makefile.mak ++++ b/src/tools/Makefile.mak +@@ -52,6 +52,11 @@ pkcs11-register.exe: pkcs11-register-cmdline.obj fread_to_eof.obj $(LIBS) + link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj pkcs11-register-cmdline.obj fread_to_eof.obj versioninfo-tools.res $(LIBS) gdi32.lib shell32.lib User32.lib ws2_32.lib + mt -manifest exe.manifest -outputresource:$@;1 + ++pkcs15-tool.exe: pkcs15-tool.obj $(TOPDIR)\src\pkcs11\pkcs11-display.obj ++ cl $(COPTS) /c $*.c ++ link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj $(TOPDIR)\src\pkcs11\pkcs11-display.obj $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib ++ mt -manifest exe.manifest -outputresource:$@;1 ++ + .c.exe: + cl $(COPTS) /c $< + link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib +diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c +index e901e17d0d..363bfb8272 100644 +--- a/src/tools/pkcs15-tool.c ++++ b/src/tools/pkcs15-tool.c +@@ -57,6 +57,7 @@ typedef unsigned __int32 uint32_t; + #include "libopensc/pkcs15.h" + #include "libopensc/asn1.h" + #include "util.h" ++#include "pkcs11/pkcs11-display.h" + + static const char *app_name = "pkcs15-tool"; + +@@ -607,6 +608,8 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj) + struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; + unsigned char guid[40]; + size_t guid_len; ++ int i; ++ int last_algo_refs = 0; + + if (compact) { + printf("\t%-3s", key_types[7 & obj->type]); +@@ -635,6 +638,16 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj) + printf("\tAccess Flags : [0x%02X]", prkey->access_flags); + print_key_access_flags(prkey->access_flags); + printf("\n"); ++ printf("\tAlgo_refs : "); ++ /* zero may be valid and don't know how many were read print at least 1*/ ++ for (i = 0; i< SC_MAX_SUPPORTED_ALGORITHMS; i++) { ++ if (prkey->algo_refs[i] != 0) ++ last_algo_refs = i; ++ } ++ for (i = 0; i< last_algo_refs + 1; i++) { ++ printf("%s%u", (i == 0) ? "" : ", ", prkey->algo_refs[i]); ++ } ++ printf("\n"); + + print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); + +@@ -1645,6 +1658,21 @@ static int list_apps(FILE *fout) + return 0; + } + ++ ++static void print_supported_algo_info_operations(unsigned int operation) ++ ++{ ++ size_t i; ++ const char *operations[] = { ++ "compute_checksum", "compute_signature", "verify_checksum", "verify_signature", ++ "encipher", "decipher", "hash", "generate/derive_key" ++ }; ++ const size_t operations_count = NELEMENTS(operations); ++ for (i = 0; i < operations_count; i++) ++ if (operation & (1 << i)) ++ printf(", %s", operations[i]); ++} ++ + static void list_info(void) + { + const char *flags[] = { +@@ -1655,6 +1683,7 @@ static void list_info(void) + }; + char *last_update = sc_pkcs15_get_lastupdate(p15card); + int i, count = 0; ++ int idx; + + printf("PKCS#15 Card [%s]:\n", p15card->tokeninfo->label); + printf("\tVersion : %d\n", p15card->tokeninfo->version); +@@ -1675,6 +1704,34 @@ static void list_info(void) + count++; + } + } ++ printf("\n"); ++ for (i = 0; i < SC_MAX_SUPPORTED_ALGORITHMS; i++) { ++ struct sc_supported_algo_info * sa = &p15card->tokeninfo->supported_algos[i]; ++ ++ if (sa->reference == 0 && sa->reference == 0 && sa->mechanism == 0 ++ && sa->operations == 0 && sa->algo_ref == 0) ++ break; ++ printf("\t\t sc_supported_algo_info[%d]:\n", i); ++ printf("\t\t\t reference : %u (0x%02x)\n", sa->reference, sa->reference); ++ printf("\t\t\t mechanism : [0x%02x] %s\n", sa->mechanism, lookup_enum(MEC_T, sa->mechanism)); ++ if (sc_valid_oid(&sa->parameters)) { ++ printf("\t\t\t parameters: %i", sa->parameters.value[0]); ++ for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && sa->parameters.value[idx] != -1 ; idx++) ++ printf(".%i", sa->parameters.value[idx]); ++ printf("\n"); ++ } ++ printf("\t\t\t operations : [0x%2.2x]",sa->operations); ++ print_supported_algo_info_operations(sa->operations); ++ printf("\n"); ++ if (sc_valid_oid((const struct sc_object_id*)&sa->algo_id)) { ++ printf("\t\t\t algo_id : %i", sa->algo_id.value[0]); ++ for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && sa->algo_id.value[idx] != -1 ; idx++) ++ printf(".%i", sa->algo_id.value[idx]); ++ printf("\n"); ++ } ++ printf("\t\t\t algo_ref : [0x%02x]\n",sa->algo_ref); ++ } ++ + printf((compact) ? "\n" : "\n\n"); + } + + +From f472f0ec213adc096508997bf7e1786ffb557d52 Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Fri, 17 Apr 2020 11:36:48 -0500 +Subject: [PATCH 6/6] Various CardOS V5_* improvements +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Treat CardOS V5_0 and V5_3 cards differently then older versions: + +Use card->dvr_data as a pointer to cardos_data_t to store private driver +data to pass internally, especially between set security environment +and the crypto operations. Sc_get_encoding_flags sets sec_flags from +algo_info->flags in pkcs15-sec.c and it passed to decipher. + +Some cards when doing a decipher may drop leading 00 byte when +returning data from RSA_RAW decipher. Add leading byte(s) as needed. + +Get Cryptographic Mechanism Reference from Key Reference: + +Key reference byte appears to be a 4 bit Cryptographic Mechanism Reference +and a 4 bit key reference. + +This is only done if key reference & 0xF0 != 0 i.e. default Cryptographic +mechanism reference is 0. which appears to be the case for RSA RAW. +PKCS1 appears to be 0x10 and ECDSA 0x30 + + See iso 7816-4 table 55 for DST: + 84 Reference of a private key + 95 Usage qualifier byte - Table 57 - 40 looks OK + 80 Cryptographic mechanism reference and referes to section 9.2 + +The 4 bit key reference limits card to 16 keys. In future this may not work, +but we can derive a Cryptographic Mechanism Reference from what OpenSC +thinks the card needs to do. Only know RSA RAW, PKCS1 and ECDSA. + +ECDSA code has not been tested, but expected to work. + +Allow setting CardOS type and flags from opensc.conf using card_atr stanza +This is a fallback if newer cards are added or older cards have problems +giving us time to make need changes in next release. + +It will help in identifying what flags are needed for each card. +As user can report what combination of flags work for them. They do this by +adding to opensc.conf with something like this. (Change the ATR to your card's ATR): + + card_atr 3b:d2:18:00:81:31:fe:58:c9:03:16 { + driver = "cardos"; + # type is decimal from cards.h: + # SC_CARD_TYPE_CARDOS_V5_0 is 1009 + # SC_CARD_TYPE_CARDOS_V5_3 is 1010 + type = 1010; + + # flags is hex from opensc.h: + #define SC_ALGORITHM_ONBOARD_KEY_GEN 0x80000000 + #define SC_ALGORITHM_NEED_USAGE 0x40000000 + + #define SC_ALGORITHM_RSA_RAW 0x00000001 /* RSA_RAW is PAD_NONE */ + #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 /* PKCS#1 v2.0 PSS */ + #define SC_ALGORITHM_RSA_PAD_OAEP 0x00000020 /* PKCS#1 v2.0 OAEP */ + #define SC_ALGORITHM_RSA_HASH_NONE 0x00000100 /* only applies to PKCS1 padding */ + # example: SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_RAW + flags = 80000101; + #example: SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_PAD_PKCS1 + flags = 80000002; + } + +For V5_0 and v5_3 cards, use sc_get_max_send_size and sc_get_max_recv_size +which takes care or reader sizes even on Windows where SCardControl can not get PART_10 sizes. + +(commit eddea6f3c2d3dafc2c09eba6695c745a61b5186f on Windows forces reader sizes to 255, 256 +in reader-pcsc.c if not already set. It should not do this, but leave that up to card drivers.) + +pkcs15-cardos.c added: + +New file, pkcs15-cardos.c, added as emulation only for CardOS +V5_0 and V5_3 cards. + +sc_pkcs15_bind_internal is called to get tokenInfo as CardOS +cards are substantially PKCS15 cards. But some V5_* cards have +errors in the tokenInfo, Which are corrected. + +For older CardOS cards, card-cardos.c will create all the +card->algorithms. + +Pkcs15-cardos.c will check for card->algorithms and if there +are none, it will do the following: + +SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS is called twice. First to get +the flags as set by user via opensc.conf card_atr or default +flags set by the card driver. Then after determining from the +tokenInfo what algorithms the card can support, the new flags +are passed to card_cardos.c to create card->algorithms. + +https://atos.net/wp-content/uploads/2018/11/CT_181026_LPM_CardOS_V5-3_Multifunctionality_FS_en3_web.pdf +says card supports: "“Command chaining” in accordance with ISO/IEC 7816-4" + +To take advantage of this with older readers, max_send_size and max_recv_size +is now based on minimum of reader limits and "data_field_length" from card. +This should allow card to work in older readers not capable of extended APDU. +So far current cards we have seen do no appear to support “Command chaining”. + + Changes to be committed: + modified: src/libopensc/Makefile.am + modified: src/libopensc/Makefile.mak + modified: src/libopensc/card-cardos.c + modified: src/libopensc/cardctl.h + modified: src/libopensc/cards.h + new file: src/libopensc/pkcs15-cardos.c + modified: src/libopensc/pkcs15-syn.c + modified: src/libopensc/pkcs15-syn.h +--- + src/libopensc/Makefile.am | 4 +- + src/libopensc/Makefile.mak | 2 +- + src/libopensc/card-cardos.c | 336 +++++++++++++++++++++++++++++----- + src/libopensc/cardctl.h | 18 ++ + src/libopensc/cards.h | 1 + + src/libopensc/pkcs15-cardos.c | 177 ++++++++++++++++++ + src/libopensc/pkcs15-syn.c | 3 + + src/libopensc/pkcs15-syn.h | 1 + + 8 files changed, 492 insertions(+), 50 deletions(-) + create mode 100644 src/libopensc/pkcs15-cardos.c + +diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am +index 140665c8a6..9f0dda5ecb 100644 +--- a/src/libopensc/Makefile.am ++++ b/src/libopensc/Makefile.am +@@ -51,7 +51,7 @@ libopensc_la_SOURCES_BASE = \ + ctbcs.c reader-ctapi.c reader-pcsc.c reader-openct.c reader-tr03119.c \ + \ + card-setcos.c card-miocos.c card-flex.c card-gpk.c \ +- card-cardos.c card-tcos.c card-default.c \ ++ card-cardos.c card-tcos.c pkcs15-cardos.c card-default.c \ + card-mcrd.c card-starcos.c card-openpgp.c card-jcop.c \ + card-oberthur.c card-belpic.c card-atrust-acos.c \ + card-entersafe.c card-epass2003.c card-coolkey.c card-incrypto34.c \ +@@ -134,7 +134,7 @@ TIDY_FILES = \ + card-npa.c card-esteid2018.c card-idprime.c \ + \ + pkcs15-openpgp.c \ +- pkcs15-tcos.c pkcs15-esteid.c \ ++ pkcs15-tcos.c pkcs15-esteid.c pkcs15-cardos.c \ + pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c \ + pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ + pkcs15-oberthur.c pkcs15-itacns.c pkcs15-sc-hsm.c \ +diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak +index 2e3c30c22b..1b0ff45c9b 100644 +--- a/src/libopensc/Makefile.mak ++++ b/src/libopensc/Makefile.mak +@@ -29,7 +29,7 @@ OBJECTS = \ + card-masktech.obj card-gids.obj card-jpki.obj \ + card-npa.obj card-esteid2018.obj card-idprime.obj \ + \ +- pkcs15-openpgp.obj pkcs15-starcert.obj \ ++ pkcs15-openpgp.obj pkcs15-starcert.obj pkcs15-cardos.obj \ + pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-gemsafeGPK.obj \ + pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \ + pkcs15-cac.obj pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-din-66291.obj \ +diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c +index 306822b974..4ef6ead0d2 100644 +--- a/src/libopensc/card-cardos.c ++++ b/src/libopensc/card-cardos.c +@@ -53,13 +53,42 @@ static const struct sc_atr_table cardos_atrs[] = { + /* CardOS v5.0 */ + { "3b:d2:18:00:81:31:fe:58:c9:01:14", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL}, + /* CardOS v5.3 */ +- { "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL}, +- { "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL}, ++ { "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL}, ++ { "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL}, + { NULL, NULL, NULL, 0, 0, NULL } + }; + +-static unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS]; +-static unsigned int algorithm_ids_in_tokeninfo_count=0; ++/* private data for cardos driver */ ++typedef struct cardos_data { ++ /* constructed internally */ ++ unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS]; ++ unsigned int algorithm_ids_in_tokeninfo_count; ++ unsigned long flags; /* flags used by init to create sc_algorithms */ ++ unsigned long ec_flags; ++ unsigned long ext_flags; ++ int rsa_2048; ++ const sc_security_env_t * sec_env; ++} cardos_data_t; ++ ++/* copied from iso7816.c */ ++static void fixup_transceive_length(const struct sc_card *card, ++ struct sc_apdu *apdu) ++{ ++ if (card == NULL || apdu == NULL) { ++ return; ++ } ++ ++ if (apdu->lc > sc_get_max_send_size(card)) { ++ /* The lower layers will automatically do chaining */ ++ apdu->flags |= SC_APDU_FLAGS_CHAINING; ++ } ++ ++ if (apdu->le > sc_get_max_recv_size(card)) { ++ /* The lower layers will automatically do a GET RESPONSE, if possible. ++ * All other workarounds must be carried out by the upper layers. */ ++ apdu->le = sc_get_max_recv_size(card); ++ } ++} + + static int cardos_match_card(sc_card_t *card) + { +@@ -79,6 +108,8 @@ static int cardos_match_card(sc_card_t *card) + return 1; + if (card->type == SC_CARD_TYPE_CARDOS_V5_0) + return 1; ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_3) ++ return 1; + if (card->type == SC_CARD_TYPE_CARDOS_M4_2) { + int rv; + sc_apdu_t apdu; +@@ -159,42 +190,102 @@ static int cardos_have_2048bit_package(sc_card_t *card) + return 0; + } + ++ ++/* Called from cardos_init for old cards, from cardos_cardctl_parsed_token_info for new cards */ ++/* TODO see if works from old cards too */ ++static int cardos_add_algs(sc_card_t *card, unsigned long flags, unsigned long ec_flags, unsigned long ext_flags) ++{ ++ ++ cardos_data_t * priv = (cardos_data_t *)card->drv_data; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ _sc_card_add_rsa_alg(card, 512, flags, 0); ++ _sc_card_add_rsa_alg(card, 768, flags, 0); ++ _sc_card_add_rsa_alg(card, 1024, flags, 0); ++ if (priv->rsa_2048 == 1) { ++ _sc_card_add_rsa_alg(card, 1280, flags, 0); ++ _sc_card_add_rsa_alg(card, 1536, flags, 0); ++ _sc_card_add_rsa_alg(card, 1792, flags, 0); ++ _sc_card_add_rsa_alg(card, 2048, flags, 0); ++ } ++ ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ /* Starting with CardOS 5, the card supports PIN query commands */ ++ card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; ++ _sc_card_add_rsa_alg(card, 3072, flags, 0); ++ _sc_card_add_rsa_alg(card, 4096, flags, 0); ++ } ++ ++ /* TODO need to get sizes from supported_algos too */ ++ if (ec_flags != 0) { ++ _sc_card_add_ec_alg(card, 256, ec_flags, priv->ext_flags, NULL); ++ _sc_card_add_ec_alg(card, 384, ec_flags, priv->ext_flags, NULL); ++ } ++ ++ return 0; ++} ++ + static int cardos_init(sc_card_t *card) + { +- unsigned long flags = 0, rsa_2048 = 0; ++ cardos_data_t * priv = NULL; ++ unsigned long flags = 0; + size_t data_field_length; + sc_apdu_t apdu; + u8 rbuf[2]; + int r; + ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ priv = calloc(1, sizeof(cardos_data_t)); ++ if (!priv) ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); ++ card->drv_data = priv; ++ + card->name = "Atos CardOS"; + card->cla = 0x00; + +- /* Set up algorithm info. */ +- flags = 0; +- if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { +- flags |= SC_ALGORITHM_RSA_PAD_PKCS1; ++ /* let user override flags and type from opensc.conf */ ++ /* user can override card->type too.*/ ++ if (card->flags) { ++ flags = card->flags; + } else { +- flags |= SC_ALGORITHM_RSA_RAW +- | SC_ALGORITHM_RSA_HASH_NONE +- | SC_ALGORITHM_NEED_USAGE +- | SC_ALGORITHM_ONBOARD_KEY_GEN; ++ ++ /* Set up algorithm info. */ ++ flags = 0; ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { ++ flags |= SC_ALGORITHM_RSA_PAD_PKCS1; ++ } else if(card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ flags |= SC_ALGORITHM_RSA_RAW ++ | SC_ALGORITHM_RSA_HASH_NONE ++ | SC_ALGORITHM_ONBOARD_KEY_GEN; ++ } else { ++ flags |= SC_ALGORITHM_RSA_RAW ++ | SC_ALGORITHM_RSA_HASH_NONE ++ | SC_ALGORITHM_NEED_USAGE ++ | SC_ALGORITHM_ONBOARD_KEY_GEN; ++ } + } + ++ priv->flags = flags; ++ + if (card->type == SC_CARD_TYPE_CARDOS_M4_2) { + r = cardos_have_2048bit_package(card); + if (r < 0) + return SC_ERROR_INVALID_CARD; + if (r == 1) +- rsa_2048 = 1; ++ priv->rsa_2048 = 1; + card->caps |= SC_CARD_CAP_APDU_EXT; +- } else if (card->type == SC_CARD_TYPE_CARDOS_M4_3 ++ } else if (card->type == SC_CARD_TYPE_CARDOS_M4_3 + || card->type == SC_CARD_TYPE_CARDOS_M4_2B + || card->type == SC_CARD_TYPE_CARDOS_M4_2C + || card->type == SC_CARD_TYPE_CARDOS_M4_4 +- || card->type == SC_CARD_TYPE_CARDOS_V5_0) { +- rsa_2048 = 1; ++ || card->type == SC_CARD_TYPE_CARDOS_V5_0 ++ || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ priv->rsa_2048 = 1; + card->caps |= SC_CARD_CAP_APDU_EXT; ++ /* TODO check this. EC only if in supported_algo */ ++ priv->ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; + } + + /* probe DATA FIELD LENGTH with GET DATA */ +@@ -202,6 +293,7 @@ static int cardos_init(sc_card_t *card) + apdu.le = sizeof rbuf; + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); ++ + r = sc_transmit_apdu(card, &apdu); + if (r < 0) + LOG_TEST_RET(card->ctx, +@@ -216,34 +308,99 @@ static int cardos_init(sc_card_t *card) + return SC_ERROR_INVALID_CARD; + data_field_length = ((rbuf[0] << 8) | rbuf[1]); + +- /* strip the length of possible Lc and Le bytes */ +- if (card->caps & SC_CARD_CAP_APDU_EXT) +- card->max_send_size = data_field_length - 6; +- else +- card->max_send_size = data_field_length - 3; +- /* strip the length of SW bytes */ +- card->max_recv_size = data_field_length - 2; ++ /* TODO is this really needed? strip the length of possible Lc and Le bytes */ ++ ++ /* Use Min card sizes and reader too. for V5_3 at least*/ ++ ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "data_field_length:%"SC_FORMAT_LEN_SIZE_T"u " ++ "card->reader->max_send_size:%"SC_FORMAT_LEN_SIZE_T"u " ++ "card->reader->max_recv_size:%"SC_FORMAT_LEN_SIZE_T"u %s", ++ data_field_length, card->reader->max_send_size, card->reader->max_recv_size, ++ (card->caps & SC_CARD_CAP_APDU_EXT) ? "SC_CARD_CAP_APDU_EXT" : " "); ++ ++ if (card->caps & SC_CARD_CAP_APDU_EXT) { ++ card->max_send_size = data_field_length - 6; ++#ifdef _WIN32 ++ /* Windows does not support PCSC PART_10 and may have forced reader to 255/256 ++ * https://github.com/OpenSC/OpenSC/commit/eddea6f3c2d3dafc2c09eba6695c745a61b5186f ++ * may have reset this. if so, will override and force extended ++ * Most, if not all, cardos cards do extended, but not chaining ++ */ ++ if (card->reader->max_send_size == 255 && card->reader->max_recv_size == 256) { ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "reseting reader to use data_field_length"); ++ card->reader->max_send_size = data_field_length - 6; ++ card->reader->max_recv_size = data_field_length - 3; ++ } ++#endif ++ } else ++ card->max_send_size = data_field_length - 3; + +- _sc_card_add_rsa_alg(card, 512, flags, 0); +- _sc_card_add_rsa_alg(card, 768, flags, 0); +- _sc_card_add_rsa_alg(card, 1024, flags, 0); +- if (rsa_2048 == 1) { +- _sc_card_add_rsa_alg(card, 1280, flags, 0); +- _sc_card_add_rsa_alg(card, 1536, flags, 0); +- _sc_card_add_rsa_alg(card, 1792, flags, 0); +- _sc_card_add_rsa_alg(card, 2048, flags, 0); ++ card->max_send_size = sc_get_max_send_size(card); /* include reader sizes and protocol */ ++ card->max_recv_size = data_field_length - 2; ++ card->max_recv_size = sc_get_max_recv_size(card); ++ } else { ++ /* old way, disregards reader capabilities */ ++ if (card->caps & SC_CARD_CAP_APDU_EXT) ++ card->max_send_size = data_field_length - 6; ++ else ++ card->max_send_size = data_field_length - 3; ++ /* strip the length of SW bytes */ ++ card->max_recv_size = data_field_length - 2; + } + +- if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { +- /* Starting with CardOS 5, the card supports PIN query commands */ +- card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; +- _sc_card_add_rsa_alg(card, 3072, flags, 0); +- _sc_card_add_rsa_alg(card, 4096, flags, 0); ++ /*for new cards, wait till after sc_pkcs15_bind_internal reads tokeninfo */ ++ if (card->type != SC_CARD_TYPE_CARDOS_V5_0 && card->type != SC_CARD_TYPE_CARDOS_V5_3) { ++ r = cardos_add_algs(card, flags, 0, 0); + } + + return 0; + } + ++static int cardos_pass_algo_flags(sc_card_t *card, struct sc_cardctl_cardos_pass_algo_flags * ptr) ++{ ++ cardos_data_t * priv = (cardos_data_t *)card->drv_data; ++ int r = 0; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ switch (ptr->pass) { ++ case 1: ++ ptr->card_flags = card->flags; ++ ptr->used_flags = priv->flags; ++ ptr->ec_flags = priv->ec_flags; ++ ptr->ext_flags = priv->ext_flags; ++ break; ++ case 2: ++ r = cardos_add_algs(card,ptr->new_flags, ptr->ec_flags, ptr->ext_flags); ++ break; ++ default: ++ sc_log(card->ctx, "ptr->pass: %ul invalid", ptr->pass); ++ r = SC_ERROR_INTERNAL; ++ } ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ ++ ++static int cardos_finish(sc_card_t *card) ++{ ++ int r = 0; ++ ++ if (card) ++ return 0; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ /* free priv data */ ++ if (card->drv_data) { /* priv */ ++ free(card->drv_data); ++ card->drv_data = NULL; ++ } ++ ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); ++} ++ ++ ++ + static const struct sc_card_error cardos_errors[] = { + /* some error inside the card */ + /* i.e. nothing you can do */ +@@ -772,8 +929,9 @@ cardos_set_security_env(sc_card_t *card, + const sc_security_env_t *env, + int se_num) + { ++ cardos_data_t* priv = (cardos_data_t*)card->drv_data; + sc_apdu_t apdu; +- u8 data[6]; ++ u8 data[9]; + int key_id, r; + + assert(card != NULL && env != NULL); +@@ -782,6 +940,15 @@ cardos_set_security_env(sc_card_t *card, + sc_log(card->ctx, "No or invalid key reference\n"); + return SC_ERROR_INVALID_ARGUMENTS; + } ++ priv->sec_env = env; /* pass on to crypto routines */ ++ ++ /* key_ref includes card mechanism and key number ++ * But newer cards appear to get this some other way, ++ * We can use flags passed to know what OpenSC expects from the card ++ * and have derived what these machanisums are. ++ * Newer cards may change how this is done ++ */ ++ + key_id = env->key_ref[0]; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); +@@ -802,16 +969,39 @@ cardos_set_security_env(sc_card_t *card, + return SC_ERROR_INVALID_ARGUMENTS; + } + +- if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ /* some cards appear to have key_id be both Cryptographic mechanism reference 4 bits ++ * and key_ref 4 bits. But this limits card to 16 keys. ++ * TODO may need to be looked at at a later time ++ */ + /* Private key reference */ + data[0] = 0x84; + data[1] = 0x01; +- data[2] = key_id; ++ data[2] = key_id & 0x0F; + /* Usage qualifier byte */ + data[3] = 0x95; + data[4] = 0x01; + data[5] = 0x40; + apdu.lc = apdu.datalen = 6; ++ if (key_id & 0xF0) { ++ /* Cryptographic mechanism reference */ ++ data[6] = 0x80; ++ data[7] = 0x01; ++ data[8] = key_id & 0xF0; ++ apdu.lc = apdu.datalen = 9; ++ } else if (priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { ++ /* TODO this may only apply to c903 cards */ ++ /* TODO or only for cards without any supported_algos or EIDComplient only */ ++ data[6] = 0x80; ++ data[7] = 0x01; ++ data[8] = 0x10; ++ apdu.lc = apdu.datalen = 9; ++ } else if (priv->sec_env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW) { ++ data[6] = 0x80; ++ data[7] = 0x01; ++ data[8] = 0x30; ++ apdu.lc = apdu.datalen = 9; ++ } + } else { + data[0] = 0x83; + data[1] = 0x01; +@@ -839,12 +1029,12 @@ cardos_set_security_env(sc_card_t *card, + + sc_log(card->ctx, "is signature"); + sc_log(card->ctx, "Adding ID %d at index %d", algorithm_id, algorithm_id_count); +- algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id; ++ priv->algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id; + } + sc_log(card->ctx, "reference=%d, mechanism=%d, operations=%d, algo_ref=%d", + alg.reference, alg.mechanism, alg.operations, alg.algo_ref); + } +- algorithm_ids_in_tokeninfo_count = algorithm_id_count; ++ priv -> algorithm_ids_in_tokeninfo_count = algorithm_id_count; + } while (0); + + LOG_FUNC_RETURN(card->ctx, r); +@@ -859,6 +1049,7 @@ static int + do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + u8 *out, size_t outlen) + { ++ /* cardos_data_t* priv = (cardos_data_t*)card->drv_dataa */; + int r; + sc_apdu_t apdu; + +@@ -873,6 +1064,7 @@ do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + apdu.data = data; + apdu.lc = datalen; + apdu.datalen = datalen; ++ fixup_transceive_length(card, &apdu); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + +@@ -886,6 +1078,7 @@ static int + cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + u8 *out, size_t outlen) + { ++ cardos_data_t* priv; + int r; + sc_context_t *ctx; + int do_rsa_pure_sig = 0; +@@ -895,8 +1088,21 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + + assert(card != NULL && data != NULL && out != NULL); + ctx = card->ctx; ++ priv = (cardos_data_t*)card->drv_data; + SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); + ++ /* sec_env has algorithm_flags set from sc_get_encoding_flags sec_flags ++ * If flags are set correctly we don't need to test anything ++ * TODO this assumes RSA is PSS, PKCS1 or RAW and we are passing ++ * the correct data. Should work for ECDSA too. ++ * use for V5 cards and TODO should for older cards too ++ */ ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ ++ r = do_compute_signature(card, data, datalen, out, outlen); ++ LOG_FUNC_RETURN(ctx, r); ++ } ++ + /* There are two ways to create a signature, depending on the way, + * the key was created: RSA_SIG and RSA_PURE_SIG. + * We can use the following reasoning, to determine the correct operation: +@@ -913,8 +1119,8 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + */ + + /* check the the algorithmIDs from the AlgorithmInfo */ +- for (i = 0; i < algorithm_ids_in_tokeninfo_count; ++i) { +- unsigned int id = algorithm_ids_in_tokeninfo[i]; ++ for (i = 0; i < priv->algorithm_ids_in_tokeninfo_count; ++i) { ++ unsigned int id = priv->algorithm_ids_in_tokeninfo[i]; + if (id == 0x86 || id == 0x88) { + do_rsa_sig = 1; + } else if (id == 0x8C || id == 0x8A) { +@@ -985,10 +1191,41 @@ cardos_decipher(struct sc_card *card, + const u8 * crgram, size_t crgram_len, + u8 * out, size_t outlen) + { ++ cardos_data_t* priv = (cardos_data_t*)card->drv_data; + int r; + size_t card_max_send_size = card->max_send_size; + size_t reader_max_send_size = card->reader->max_send_size; + ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ /* 5.3 supports command chaining. Others may also ++ * card_max_send_size for 5.3 is already based on reader max_send_size */ ++ ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ ++ r = iso_ops->decipher(card, crgram, crgram_len, out, outlen); ++ /* ++ * 5.3 supports RAW as well as PKCS1 and PSS ++ * decription may strip padding if card supports it ++ * with cards that support RAW, it always appears to ++ * drop first 00 that is start of padding. ++ */ ++ ++ if (r > 0 && priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_RAW) { ++ size_t rsize = r; ++ /* RSA RAW crgram_len == modlen */ ++ /* removed padding is always > 1 byte */ ++ /* add back missing leading zero if card dropped it */ ++ if (rsize == crgram_len - 1 && rsize < outlen) { ++ memmove(out+1, out, rsize); ++ out[0] =0x00; ++ r++; ++ } ++ } ++ ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); ++ } ++ + if (sc_get_max_send_size(card) < crgram_len + 1) { + /* CardOS doesn't support chaining for PSO:DEC, so we just _hope_ + * that both, the reader and the card are able to send enough data. +@@ -1003,7 +1240,7 @@ cardos_decipher(struct sc_card *card, + card->max_send_size = card_max_send_size; + card->reader->max_send_size = reader_max_send_size; + +- return r; ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); + } + + static int +@@ -1188,7 +1425,7 @@ static int cardos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) + return SC_ERROR_INTERNAL; +- if ((apdu.resplen == 8) && (card->type == SC_CARD_TYPE_CARDOS_V5_0)) { ++ if ((apdu.resplen == 8) && (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3)) { + /* cache serial number */ + memcpy(card->serialnr.value, rbuf, 8); + card->serialnr.len = 8; +@@ -1223,6 +1460,9 @@ cardos_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) + case SC_CARDCTL_CARDOS_GENERATE_KEY: + return cardos_generate_key(card, + (struct sc_cardctl_cardos_genkey_info *) ptr); ++ case SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS: ++ return cardos_pass_algo_flags(card, ++ (struct sc_cardctl_cardos_pass_algo_flags *) ptr); + case SC_CARDCTL_LIFECYCLE_GET: + return cardos_lifecycle_get(card, (int *) ptr); + case SC_CARDCTL_LIFECYCLE_SET: +@@ -1279,7 +1519,8 @@ cardos_logout(sc_card_t *card) + || card->type == SC_CARD_TYPE_CARDOS_M4_2C + || card->type == SC_CARD_TYPE_CARDOS_M4_3 + || card->type == SC_CARD_TYPE_CARDOS_M4_4 +- || card->type == SC_CARD_TYPE_CARDOS_V5_0) { ++ || card->type == SC_CARD_TYPE_CARDOS_V5_0 ++ || card->type == SC_CARD_TYPE_CARDOS_V5_3) { + sc_apdu_t apdu; + int r; + sc_path_t path; +@@ -1309,6 +1550,7 @@ static struct sc_card_driver * sc_get_driver(void) + cardos_ops = *iso_ops; + cardos_ops.match_card = cardos_match_card; + cardos_ops.init = cardos_init; ++ cardos_ops.finish = cardos_finish; + cardos_ops.select_file = cardos_select_file; + cardos_ops.create_file = cardos_create_file; + cardos_ops.set_security_env = cardos_set_security_env; +diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h +index 0c68c4c625..10ddfa0545 100644 +--- a/src/libopensc/cardctl.h ++++ b/src/libopensc/cardctl.h +@@ -83,6 +83,7 @@ enum { + SC_CARDCTL_CARDOS_PUT_DATA_OCI, + SC_CARDCTL_CARDOS_PUT_DATA_SECI, + SC_CARDCTL_CARDOS_GENERATE_KEY, ++ SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, + + /* + * Starcos SPK 2.3 specific calls +@@ -350,6 +351,14 @@ typedef struct sc_cardctl_pkcs11_init_pin { + size_t pin_len; + } sc_cardctl_pkcs11_init_pin_t; + ++/* ++ * Generic cardctl - card driver can examine token info ++ */ ++struct sc_cardctl_parsed_token_info { ++ unsigned int flags; ++ struct sc_pkcs15_tokeninfo * tokeninfo; ++}; ++ + /* + * GPK lock file. + * Parent DF of file must be selected. +@@ -419,6 +428,15 @@ struct sc_cardctl_cardos_genkey_info { + unsigned short fid; + }; + ++struct sc_cardctl_cardos_pass_algo_flags { ++ unsigned int pass; ++ unsigned long card_flags; /* from card->flags i.e. user set */ ++ unsigned long used_flags; /* as set by default */ ++ unsigned long new_flags; /* set in pkcs15-cardos.c */ ++ unsigned long ec_flags; /* for EC keys */ ++ unsigned long ext_flags; /* for EC keys */ ++}; ++ + /* + * Incrypto34 PIN info + */ +diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h +index cb0501c3aa..8d58fb9368 100644 +--- a/src/libopensc/cards.h ++++ b/src/libopensc/cards.h +@@ -47,6 +47,7 @@ enum { + SC_CARD_TYPE_CARDOS_CIE_V1, /* Italian CIE (eID) v1 */ + SC_CARD_TYPE_CARDOS_M4_4, + SC_CARD_TYPE_CARDOS_V5_0, ++ SC_CARD_TYPE_CARDOS_V5_3, + + /* flex/cyberflex drivers */ + SC_CARD_TYPE_FLEX_BASE = 2000, +diff --git a/src/libopensc/pkcs15-cardos.c b/src/libopensc/pkcs15-cardos.c +new file mode 100644 +index 0000000000..752631ce88 +--- /dev/null ++++ b/src/libopensc/pkcs15-cardos.c +@@ -0,0 +1,177 @@ ++/* ++ * PKCS15 emulation layer for CardOS cards ++ * Adapted from PKCS15 emulation layer for IAS/ECC card. ++ * ++ * Copyright (C) 2020, Douglas E. Engert ++ * Copyright (C) 2016, Viktor Tarasov ++ * Copyright (C) 2004, Bud P. Bruegger ++ * Copyright (C) 2004, Antonino Iacono ++ * Copyright (C) 2003, Olaf Kirch ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#if HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include ++#include ++#include ++ ++#include "internal.h" ++#include "pkcs15.h" ++ ++ ++/* ++ * Called after sc_pkcs15_bind_internal ++ * Create new flags based on supported_algos. ++ */ ++static int cardos_fix_token_info(sc_pkcs15_card_t *p15card) ++{ ++ sc_card_t *card; ++ struct sc_supported_algo_info (*saa)[SC_MAX_SUPPORTED_ALGORITHMS]; ++ struct sc_supported_algo_info *sa; ++ struct sc_cardctl_cardos_pass_algo_flags *passed = NULL; ++ int r = 0; ++ int i; ++ ++ card = p15card->card; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ passed = calloc(1, sizeof(struct sc_cardctl_cardos_pass_algo_flags)); ++ if (!passed) ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); ++ ++ passed->pass = 1; /* get used_flags and card_flags from card */ ++ r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed); ++ if (r < 0) { ++ free(passed); ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ ++ saa = &(p15card->tokeninfo->supported_algos); ++ ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Original Flags: 0x%8.8lx card->flags:0x%8.8lx", passed->used_flags, passed->card_flags); ++ ++ if (passed->card_flags) { /* user forced the flags, use them */ ++ passed->new_flags = passed->card_flags; /* from card_atr flags */ ++ } else { ++ ++ for (i = 0, sa = saa[0]; i < SC_MAX_SUPPORTED_ALGORITHMS; i++, sa++) { ++ ++ if (sa->reference == 0 && sa->reference == 0 && sa->mechanism == 0 ++ && sa->operations == 0 && sa->algo_ref == 0) ++ break; ++ ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "supported_algos[%d] mechamism:0x%8.8x", i, sa->mechanism); ++ switch(sa->mechanism) { ++ case 0x01 : ++ /* ++ * Card appears to use lower 4 bits of reference as key, and upper ++ * 4 bits as mech for card. ++ * Also has a bug if mechanism = 1 (CKM_RSA_PKCS1) and reference 0x10 ++ * bit is set mechanism should be 3 (CKM_RSA_X_509) ++ * correct the mechanism in tokenInfo ++ */ ++ if (sa->reference & 0x10) { ++ sc_log(card->ctx, "Changeing mechanism to CKM_RSA_X_509 based on reference"); ++ passed->new_flags |= SC_ALGORITHM_RSA_RAW ++ | SC_ALGORITHM_RSA_PAD_NONE; ++ sa->mechanism = 0x03; ++ } else ++ passed->new_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; ++ break; ++ case 0x03 : ++ passed->new_flags |= SC_ALGORITHM_RSA_RAW ++ | SC_ALGORITHM_RSA_PAD_NONE; ++ break; ++ case 0x06 : ++ passed->new_flags |= SC_ALGORITHM_RSA_HASH_SHA1; ++ break; ++ case 0x1041: ++ passed->ec_flags |= SC_ALGORITHM_ECDSA_RAW; ++ /* no old_ec_flags */ ++ /* TODO turn on sizes from ec curves OIDS */ ++ break; ++ default: ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "UNKNOWN MECH: 0x%8.8x", sa->mechanism); ++ } ++ ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", ++ passed->new_flags, passed->ec_flags); ++ } ++ ++ if (passed->new_flags == 0) { ++ if (p15card->tokeninfo && p15card->tokeninfo->flags & SC_PKCS15_TOKEN_EID_COMPLIANT) { ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EID_COMPLIANT flag found"); ++ passed->new_flags = (passed->used_flags & ~SC_ALGORITHM_SPECIFIC_FLAGS) | SC_ALGORITHM_RSA_PAD_PKCS1; ++ } else ++ passed->new_flags = passed->used_flags; /* from default cardos_init */ ++ } ++ } ++ ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Final New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", passed->new_flags, passed->ec_flags); ++ ++ passed->pass = 2; /* tell card driver to use the new flags */ ++ r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed); ++ ++ free(passed); ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ ++static int ++cardos_pkcs15emu_detect_card(sc_pkcs15_card_t *p15card) ++{ ++ if (p15card->card->type < SC_CARD_TYPE_CARDOS_BASE) ++ return SC_ERROR_WRONG_CARD; ++ ++ if (p15card->card->type >= SC_CARD_TYPE_CARDOS_BASE + 1000) ++ return SC_ERROR_WRONG_CARD; ++ ++ return SC_SUCCESS; ++} ++ ++ ++static int ++sc_pkcs15emu_cardos_init(struct sc_pkcs15_card *p15card, struct sc_aid *aid) ++{ ++ sc_card_t *card = p15card->card; ++ int r; ++ ++ LOG_FUNC_CALLED(card->ctx); ++ ++ r = sc_pkcs15_bind_internal(p15card, aid); ++ LOG_TEST_RET(card->ctx, r, "sc_pkcs15_bind_internal failed"); ++ ++ /* If card has created algorithms, return */ ++ sc_log(card->ctx, " card->algorithms:%p card->algorithm_count:%d", card->algorithms, card->algorithm_count); ++ if (!card->algorithms && card->algorithm_count == 0) { ++ r = cardos_fix_token_info(p15card); ++ } ++ ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ ++ ++int ++sc_pkcs15emu_cardos_init_ex(struct sc_pkcs15_card *p15card, struct sc_aid *aid) ++{ ++ if (cardos_pkcs15emu_detect_card(p15card)) ++ return SC_ERROR_WRONG_CARD; ++ ++ return sc_pkcs15emu_cardos_init(p15card, aid); ++} +diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c +index aba6f52c0e..ecd06b13c6 100644 +--- a/src/libopensc/pkcs15-syn.c ++++ b/src/libopensc/pkcs15-syn.c +@@ -60,6 +60,7 @@ struct sc_pkcs15_emulator_handler builtin_emulators[] = { + { "coolkey", sc_pkcs15emu_coolkey_init_ex }, + { "din66291", sc_pkcs15emu_din_66291_init_ex }, + { "esteid2018", sc_pkcs15emu_esteid2018_init_ex }, ++ { "cardos", sc_pkcs15emu_cardos_init_ex }, + + { NULL, NULL } + }; +@@ -95,6 +96,8 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card) + case SC_CARD_TYPE_PIV_II_NEO: + case SC_CARD_TYPE_PIV_II_YUBIKEY4: + case SC_CARD_TYPE_ESTEID_2018: ++ case SC_CARD_TYPE_CARDOS_V5_0: ++ case SC_CARD_TYPE_CARDOS_V5_3: + + return 1; + default: +diff --git a/src/libopensc/pkcs15-syn.h b/src/libopensc/pkcs15-syn.h +index ccaf693ca4..a15e0d95cf 100644 +--- a/src/libopensc/pkcs15-syn.h ++++ b/src/libopensc/pkcs15-syn.h +@@ -54,6 +54,7 @@ int sc_pkcs15emu_jpki_init_ex(sc_pkcs15_card_t *, struct sc_aid *); + int sc_pkcs15emu_coolkey_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); + int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); + int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); ++int sc_pkcs15emu_cardos_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); + + struct sc_pkcs15_emulator_handler { + const char *name; + diff --git a/SPECS/opensc.spec b/SPECS/opensc.spec index 50862de..dd17e23 100644 --- a/SPECS/opensc.spec +++ b/SPECS/opensc.spec @@ -2,8 +2,8 @@ %define nssdb %{_sysconfdir}/pki/nssdb Name: opensc -Version: 0.19.0 -Release: 7%{?dist} +Version: 0.20.0 +Release: 2%{?dist} Summary: Smart card library and applications Group: System Environment/Libraries @@ -11,26 +11,11 @@ License: LGPLv2+ URL: https://github.com/OpenSC/OpenSC/wiki Source0: https://github.com/OpenSC/OpenSC/releases/download/%{version}/%{name}-%{version}.tar.gz Source1: opensc.module -# https://github.com/OpenSC/OpenSC/pull/1435 -# https://github.com/OpenSC/OpenSC/pull/1521 -# parts of -# https://github.com/OpenSC/OpenSC/pull/1556 -# https://github.com/OpenSC/OpenSC/pull/1503 -# https://github.com/OpenSC/OpenSC/pull/1505 -Patch2: opensc-0.19.0-rsa-pss.patch -# https://github.com/OpenSC/OpenSC/pull/1489 -Patch3: opensc-0.19.0-coverity.patch -# https://github.com/OpenSC/OpenSC/pull/1500 -Patch4: opensc-0.19.0-coolkey-matching.patch -# https://github.com/OpenSC/OpenSC/pull/1502 -Patch5: opensc-0.19.0-cac1.patch Patch6: opensc-0.19.0-pinpad.patch -# https://github.com/OpenSC/OpenSC/pull/1549 -Patch7: opensc-0.19.0-dual.patch # https://github.com/OpenSC/OpenSC/pull/1772 Patch8: opensc-0.19.0-idprime.patch -# https://github.com/OpenSC/OpenSC/pull/1532 -Patch9: opensc-0.19.0-coolkey-2k.patch +# https://github.com/OpenSC/OpenSC/pull/1987 +Patch9: opensc-0.20.0-cardos.patch BuildRequires: pcsc-lite-devel BuildRequires: readline-devel @@ -40,6 +25,7 @@ BuildRequires: docbook-style-xsl BuildRequires: autoconf automake libtool gcc BuildRequires: desktop-file-utils BuildRequires: bash-completion +BuildRequires: zlib-devel Requires: pcsc-lite-libs%{?_isa} Requires: pcsc-lite Obsoletes: mozilla-opensc-signer < 0.12.0 @@ -58,14 +44,9 @@ every software/card that does so, too. %prep %setup -q -%patch2 -p1 -b .pss -%patch3 -p1 -b .coverity -%patch4 -p1 -b .coolkey-match -%patch5 -p1 -b .cac1 %patch6 -p1 -b .pinpad -%patch7 -p1 -b .dual %patch8 -p1 -b .idprime -%patch9 -p1 -b .coolkey-2k +%patch9 -p1 -b .cardos cp -p src/pkcs15init/README ./README.pkcs15init cp -p src/scconf/README.scconf . @@ -80,6 +61,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 \ --disable-tests \ @@ -123,6 +105,11 @@ rm -rf %{buildroot}%{_datadir}/bash-completion/ rm -rf %{buildroot}%{_bindir}/npa-tool rm -rf %{buildroot}%{_mandir}/man1/npa-tool.1* +# We use p11-kit for pkcs11 modules registration +rm -rf %{buildroot}%{_bindir}/pkcs11-register +# It is even missing the manual page +#rm -rf %{buildroot}%{_mandir}/man1/pkcs11-register.1* + desktop-file-validate %{buildroot}/%{_datadir}/applications/org.opensc.notify.desktop %post @@ -183,6 +170,7 @@ fi %{_bindir}/westcos-tool %{_bindir}/egk-tool %{_datadir}/applications/org.opensc.notify.desktop +%{_bindir}/goid-tool %{_libdir}/lib*.so.* %{_libdir}/opensc-pkcs11.so %{_libdir}/pkcs11-spy.so @@ -217,6 +205,12 @@ fi %changelog +* Wed May 27 2020 Jakub Jelen - 0.20.0-2 +- Unbreak different CardOS 5 configurations supporting raw RSA (#1830856) + +* Wed Apr 22 2020 Jakub Jelen - 0.20.0-1 +- Rebase to current upstream release (#1810660) + * Mon Nov 25 2019 Jakub Jelen - 0.19.0-7 - Unbreak RSA-PSS mechanisms in -6 release (#1775673)