From b7ace2a2d0457934e2285d5da71678a9dd4b2b4a Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 06 2019 10:05:16 +0000 Subject: import opensc-0.19.0-3.el7 --- diff --git a/.gitignore b/.gitignore index 3b06172..846cace 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/opensc-0.16.0-git777e2a3.zip +SOURCES/opensc-0.19.0.tar.gz diff --git a/.opensc.metadata b/.opensc.metadata index 36a688c..ec57eb9 100644 --- a/.opensc.metadata +++ b/.opensc.metadata @@ -1 +1 @@ -508b0ff2ed863ba71cda081b4df1ed00af428748 SOURCES/opensc-0.16.0-git777e2a3.zip +56cd654550aed081eb8ed86edba86e6d766133c4 SOURCES/opensc-0.19.0.tar.gz diff --git a/SOURCES/opensc-0.16.0-cac-alt.patch b/SOURCES/opensc-0.16.0-cac-alt.patch deleted file mode 100644 index fccdbf9..0000000 --- a/SOURCES/opensc-0.16.0-cac-alt.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 6dc118e1c3b89c50cda1998de1d62fa6fa666e60 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 3 Nov 2017 10:55:35 +0100 -Subject: [PATCH 1/3] Enable CAC ALT token card operations - ---- - src/libopensc/card-cac.c | 33 +++++++++++++++++++++++++++++++++ - 1 file changed, 33 insertions(+) - -diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c -index 82f5c7869..bc0a754a5 100644 ---- a/src/libopensc/card-cac.c -+++ b/src/libopensc/card-cac.c -@@ -229,6 +229,12 @@ static int cac_add_object_to_list(list_t *list, const cac_object_t *object) - #define CAC_1_RID "\xA0\x00\x00\x00\x79" - #define CAC_1_CM_AID "\xA0\x00\x00\x00\x30\x00\00" - -+static const sc_path_t cac_ACA_Path = { -+ "", 0, -+ 0,0,SC_PATH_TYPE_DF_NAME, -+ { CAC_TO_AID(CAC_1_RID "\x10\x00") } -+}; -+ - static const sc_path_t cac_CCC_Path = { - "", 0, - 0,0,SC_PATH_TYPE_DF_NAME, -@@ -284,6 +290,8 @@ static const cac_object_t cac_1_objects[] = { - static const int cac_1_object_count = sizeof(cac_1_objects)/sizeof(cac_1_objects[0]); - - -+static int cac_select_ACA(sc_card_t *card); -+ - /* - * use the object id to find our object info on the object in our CAC-1 list - */ -@@ -815,6 +823,8 @@ static int cac_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) - case SC_CARDCTL_CAC_FINAL_GET_GENERIC_OBJECTS: - return cac_final_iterator(&priv->general_list); - case SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS: -+ /* select ACA to be able to verify PIN */ -+ cac_select_ACA(card); - return cac_final_iterator(&priv->pki_list); - } - -@@ -1157,6 +1167,12 @@ 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); - } - -+/* 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); -+} -+ - static int cac_path_from_cardurl(sc_card_t *card, sc_path_t *path, cac_card_url_t *val, int len) - { - if (len < 10) { -@@ -1476,6 +1492,23 @@ static int cac_find_and_initialize(sc_card_t *card, int initialize) - } - } - -+ /* Even some ALT tokens can be missing CCC so we should try with ACA */ -+ r = cac_select_ACA(card); -+ if (r == SC_SUCCESS) { -+ r = cac_find_first_pki_applet(card, &index); -+ if (r == SC_SUCCESS) { -+ priv = cac_new_private_data(); -+ if (!priv) -+ return SC_ERROR_OUT_OF_MEMORY; -+ r = cac_populate_cac_1(card, index, priv); -+ if (r == SC_SUCCESS) { -+ card->type = SC_CARD_TYPE_CAC_II; -+ card->drv_data = priv; -+ return r; -+ } -+ } -+ } -+ - /* is this a CAC-1 specified in DoD "CAC Applet Developer Guide" version 1.0 September 2002 */ - r = cac_find_first_pki_applet(card, &index); - if (r == SC_SUCCESS) { - -From 68c52640a3eff078243fd2db627cf2d12fdd37de Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Mon, 6 Nov 2017 12:37:40 +0100 -Subject: [PATCH 2/3] Add the ACA path to the PIN structure if we have one - ---- - src/libopensc/card-cac.c | 25 +++++++++++++++++++------ - src/libopensc/cardctl.h | 1 + - src/libopensc/pkcs15-cac.c | 6 ++++++ - 3 files changed, 26 insertions(+), 6 deletions(-) - -diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c -index bc0a754a5..178150d35 100644 ---- a/src/libopensc/card-cac.c -+++ b/src/libopensc/card-cac.c -@@ -169,6 +169,7 @@ typedef struct cac_private_data { - 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) -@@ -207,6 +208,7 @@ 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); -@@ -289,9 +291,6 @@ static const cac_object_t cac_1_objects[] = { - - static const int cac_1_object_count = sizeof(cac_1_objects)/sizeof(cac_1_objects[0]); - -- --static int cac_select_ACA(sc_card_t *card); -- - /* - * use the object id to find our object info on the object in our CAC-1 list - */ -@@ -793,11 +792,21 @@ static int cac_get_serial_nr_from_CUID(sc_card_t* card, sc_serial_number_t* seri - if (priv->cac_id_len) { - serial->len = MIN(priv->cac_id_len, SC_MAX_SERIALNR); - memcpy(serial->value, priv->cac_id, priv->cac_id_len); -- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); - } - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_NOT_FOUND); - } - -+static int cac_get_ACA_path(sc_card_t *card, sc_path_t *path) -+{ -+ cac_private_data_t * priv = CAC_DATA(card); -+ -+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL); -+ if (priv->aca_path) { -+ *path = *priv->aca_path; -+ } -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); -+} - - static int cac_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) - { -@@ -810,6 +819,8 @@ static int cac_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); - } - switch(cmd) { -+ case SC_CARDCTL_CAC_GET_ACA_PATH: -+ return cac_get_ACA_path(card, (sc_path_t *) ptr); - case SC_CARDCTL_GET_SERIALNR: - return cac_get_serial_nr_from_CUID(card, (sc_serial_number_t *) ptr); - case SC_CARDCTL_CAC_INIT_GET_GENERIC_OBJECTS: -@@ -823,8 +834,6 @@ static int cac_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) - case SC_CARDCTL_CAC_FINAL_GET_GENERIC_OBJECTS: - return cac_final_iterator(&priv->general_list); - case SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS: -- /* select ACA to be able to verify PIN */ -- cac_select_ACA(card); - return cac_final_iterator(&priv->pki_list); - } - -@@ -1502,6 +1511,10 @@ static int cac_find_and_initialize(sc_card_t *card, int initialize) - return SC_ERROR_OUT_OF_MEMORY; - r = cac_populate_cac_1(card, index, priv); - if (r == SC_SUCCESS) { -+ priv->aca_path = malloc(sizeof(sc_path_t)); -+ if (!priv->aca_path) -+ return SC_ERROR_OUT_OF_MEMORY; -+ memcpy(priv->aca_path, &cac_ACA_Path, sizeof(sc_path_t)); - card->type = SC_CARD_TYPE_CAC_II; - card->drv_data = priv; - return r; -diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h -index b647b0537..b610eacc7 100644 ---- a/src/libopensc/cardctl.h -+++ b/src/libopensc/cardctl.h -@@ -220,6 +220,7 @@ enum { - SC_CARDCTL_CAC_INIT_GET_CERT_OBJECTS, - SC_CARDCTL_CAC_GET_NEXT_CERT_OBJECT, - SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS, -+ SC_CARDCTL_CAC_GET_ACA_PATH, - - /* - * AuthentIC v3 -diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c -index fd463a9b4..ff87a2345 100644 ---- a/src/libopensc/pkcs15-cac.c -+++ b/src/libopensc/pkcs15-cac.c -@@ -250,6 +250,12 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) - strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1); - pin_obj.flags = pins[i].obj_flags; - -+ /* get the ACA path in case it needs to be selected before PIN verify */ -+ r = sc_card_ctl(card, SC_CARDCTL_CAC_GET_ACA_PATH, &pin_info.path); -+ if (r < 0) { -+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); -+ } -+ - r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); - if (r < 0) - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); diff --git a/SOURCES/opensc-0.16.0-cardos.patch b/SOURCES/opensc-0.16.0-cardos.patch deleted file mode 100644 index 0b7bdfa..0000000 --- a/SOURCES/opensc-0.16.0-cardos.patch +++ /dev/null @@ -1,240 +0,0 @@ -From bc496dfa59c1cfbc5c47c76511d5c6b7eff5cc6c Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Thu, 26 Jan 2017 17:11:24 +0100 -Subject: [PATCH 1/4] Set security context for CardOS 5.3 with p1=0x41 (as - Coolkey does) - ---- - src/libopensc/card-cardos.c | 16 +++++++++++----- - src/libopensc/cards.h | 1 + - 2 files changed, 12 insertions(+), 5 deletions(-) - -diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c -index 0c14b32..008ce5c 100644 ---- a/src/libopensc/card-cardos.c -+++ b/src/libopensc/card-cardos.c -@@ -59,7 +59,7 @@ static 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:03:16", 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_3, 0, NULL}, - { NULL, NULL, NULL, 0, 0, NULL } - }; - -@@ -84,6 +84,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; -@@ -195,7 +197,8 @@ static int cardos_init(sc_card_t *card) - || 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) { -+ || card->type == SC_CARD_TYPE_CARDOS_V5_0 -+ || card->type == SC_CARD_TYPE_CARDOS_V5_3) { - rsa_2048 = 1; - card->caps |= SC_CARD_CAP_APDU_EXT; - } -@@ -230,7 +233,7 @@ static int cardos_init(sc_card_t *card) - _sc_card_add_rsa_alg(card, 2048, flags, 0); - } - -- if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { -+ 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; - } -@@ -249,7 +252,7 @@ static const struct sc_card_error cardos_errors[] = { - { 0x6f82, SC_ERROR_CARD_CMD_FAILED, "not enough memory in xram"}, - { 0x6f84, SC_ERROR_CARD_CMD_FAILED, "general protection fault"}, - --/* the card doesn't now thic combination of ins+cla+p1+p2 */ -+/* the card doesn't now this combination of ins+cla+p1+p2 */ - /* i.e. command will never work */ - { 0x6881, SC_ERROR_NO_CARD_SUPPORT, "logical channel not supported"}, - { 0x6a86, SC_ERROR_INCORRECT_PARAMETERS,"p1/p2 invalid"}, -@@ -781,6 +784,8 @@ cardos_set_security_env(sc_card_t *card, - if (card->type == SC_CARD_TYPE_CARDOS_CIE_V1) { - cardos_restore_security_env(card, 0x30); - apdu.p1 = 0xF1; -+ } else if (card->type == SC_CARD_TYPE_CARDOS_V5_3) { -+ apdu.p1 = 0x41; - } else { - apdu.p1 = 0x01; - } -@@ -1235,7 +1240,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; -diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h -index d71c02f..9f8f641 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, --- -2.9.3 - - -From 5dec534cf07e45ffb0209a53d6145022ecd9259a Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Mon, 30 Jan 2017 14:33:05 +0100 -Subject: [PATCH 2/4] Do not emulate signatures in CardOS 5.3 - -Remove the bogus SC_ALGORITHM_NEED_USAGE which prevents using the -actual implementation in cardos_compute_signature(). - -It might be bogus also in previous version, but I don't have a way -to verify against these cards. ---- - src/libopensc/card-cardos.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c -index 008ce5c..a21e67a 100644 ---- a/src/libopensc/card-cardos.c -+++ b/src/libopensc/card-cardos.c -@@ -177,11 +177,13 @@ static int cardos_init(sc_card_t *card) - card->cla = 0x00; - - /* Set up algorithm info. */ -- flags = SC_ALGORITHM_NEED_USAGE -- | SC_ALGORITHM_RSA_RAW -+ flags = SC_ALGORITHM_RSA_RAW - | SC_ALGORITHM_RSA_HASH_NONE - | SC_ALGORITHM_ONBOARD_KEY_GEN - ; -+ if (card->type != SC_CARD_TYPE_CARDOS_V5_3) -+ flags |= SC_ALGORITHM_NEED_USAGE; -+ - _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); -@@ -252,7 +254,7 @@ static const struct sc_card_error cardos_errors[] = { - { 0x6f82, SC_ERROR_CARD_CMD_FAILED, "not enough memory in xram"}, - { 0x6f84, SC_ERROR_CARD_CMD_FAILED, "general protection fault"}, - --/* the card doesn't now this combination of ins+cla+p1+p2 */ -+/* the card doesn't know this combination of ins+cla+p1+p2 */ - /* i.e. command will never work */ - { 0x6881, SC_ERROR_NO_CARD_SUPPORT, "logical channel not supported"}, - { 0x6a86, SC_ERROR_INCORRECT_PARAMETERS,"p1/p2 invalid"}, --- -2.9.3 - - -From 057197c7abf29715a2b7793045c35adf2a34dc17 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 10 Mar 2017 16:37:43 +0100 -Subject: [PATCH 3/4] Hack for returning the padding back in CardOS 5.3 - ---- - src/libopensc/card-cardos.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c -index a21e67a..39ec4ac 100644 ---- a/src/libopensc/card-cardos.c -+++ b/src/libopensc/card-cardos.c -@@ -979,6 +979,30 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, - } - - static int -+cardos_decipher(struct sc_card *card, -+ const u8 * crgram, size_t crgram_len, -+ u8 * out, size_t outlen) -+{ -+ int r; -+ u8 *tmp = NULL; -+ size_t tmp_len = crgram_len; -+ -+ assert(card != NULL && crgram != NULL && out != NULL); -+ LOG_FUNC_CALLED(card->ctx); -+ -+ tmp = malloc(tmp_len); -+ r = iso_ops->decipher(card, crgram, crgram_len, tmp, tmp_len); -+ -+ /* add bogus padding, because the card removes it */ -+ if (sc_pkcs1_encode(card->ctx, SC_ALGORITHM_RSA_HASH_NONE|SC_ALGORITHM_RSA_PAD_PKCS1, -+ tmp, r, out, &outlen, crgram_len) != SC_SUCCESS) -+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); -+ out[1] = 0x02; /* this is encryption-padding */ -+ -+ LOG_FUNC_RETURN(card->ctx, outlen); -+} -+ -+static int - cardos_lifecycle_get(sc_card_t *card, int *mode) - { - sc_apdu_t apdu; -@@ -1278,6 +1302,7 @@ static struct sc_card_driver * sc_get_driver(void) - cardos_ops.set_security_env = cardos_set_security_env; - cardos_ops.restore_security_env = cardos_restore_security_env; - cardos_ops.compute_signature = cardos_compute_signature; -+ cardos_ops.decipher = cardos_decipher; - - cardos_ops.list_files = cardos_list_files; - cardos_ops.check_sw = cardos_check_sw; --- -2.9.3 - - -From 515f761f5564e91302ce672d30a24d6e6738e349 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Mon, 13 Mar 2017 15:15:48 +0100 -Subject: [PATCH 4/4] With older cards, use iso decipher - ---- - src/libopensc/card-cardos.c | 16 ++++++++++++++-- - 1 file changed, 14 insertions(+), 2 deletions(-) - -diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c -index 39ec4ac..d479065 100644 ---- a/src/libopensc/card-cardos.c -+++ b/src/libopensc/card-cardos.c -@@ -992,10 +992,22 @@ cardos_decipher(struct sc_card *card, - - tmp = malloc(tmp_len); - r = iso_ops->decipher(card, crgram, crgram_len, tmp, tmp_len); -+ if (r < 0) -+ LOG_FUNC_RETURN(card->ctx, r); -+ -+ if (card->type != SC_CARD_TYPE_CARDOS_V5_3) { -+ /* XXX */ -+ memcpy(out, tmp, tmp_len); -+ outlen = tmp_len; -+ free(tmp); -+ LOG_FUNC_RETURN(card->ctx, r); -+ } - - /* add bogus padding, because the card removes it */ -- if (sc_pkcs1_encode(card->ctx, SC_ALGORITHM_RSA_HASH_NONE|SC_ALGORITHM_RSA_PAD_PKCS1, -- tmp, r, out, &outlen, crgram_len) != SC_SUCCESS) -+ r = sc_pkcs1_encode(card->ctx, SC_ALGORITHM_RSA_HASH_NONE|SC_ALGORITHM_RSA_PAD_PKCS1, -+ tmp, r, out, &outlen, crgram_len); -+ free(tmp); -+ if (r != SC_SUCCESS) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); - out[1] = 0x02; /* this is encryption-padding */ - --- -2.9.3 - diff --git a/SOURCES/opensc-0.16.0-cardos5.patch b/SOURCES/opensc-0.16.0-cardos5.patch deleted file mode 100644 index 648c351..0000000 --- a/SOURCES/opensc-0.16.0-cardos5.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 60dbebf511cf6112e5fc2c3549ce38881847b121 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 22 Aug 2017 10:46:26 +0200 -Subject: [PATCH] Parse the ECC parameters from TokenInfo (CHOICE in - AlgorithmInfo) - -Fixes #1134 ---- - src/libopensc/opensc.h | 1 + - src/libopensc/pkcs15.c | 40 +++++++++++++++++++++++++++++++++------- - 2 files changed, 34 insertions(+), 7 deletions(-) - -diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h -index f81f27e3a..688c14003 100644 ---- a/src/libopensc/opensc.h -+++ b/src/libopensc/opensc.h -@@ -163,6 +163,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 */ - 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 05fe03061..ba99c8af9 100644 ---- a/src/libopensc/pkcs15.c -+++ b/src/libopensc/pkcs15.c -@@ -50,13 +50,19 @@ static const struct sc_asn1_entry c_asn1_twlabel[] = { - static const struct sc_asn1_entry c_asn1_algorithm_info[7] = { - { "reference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, - { "algorithmPKCS#11", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, -- { "parameters", SC_ASN1_NULL, SC_ASN1_TAG_NULL, 0, NULL, NULL }, -+ { "parameters", SC_ASN1_CHOICE, 0, 0, NULL, NULL }, - { "supportedOperations",SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL }, - { "objId", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_OPTIONAL, NULL, NULL }, - { "algRef", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, - { NULL, 0, 0, 0, NULL, NULL } - }; - -+static const struct sc_asn1_entry c_asn1_algorithm_info_parameters[3] = { -+ { "PKCS15RSAParameters",SC_ASN1_NULL, SC_ASN1_TAG_NULL, 0, NULL, NULL }, -+ { "PKCS15ECParameters", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL }, -+ { NULL, 0, 0, 0, NULL, NULL } -+}; -+ - /* - * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 - */ -@@ -134,9 +140,11 @@ int sc_pkcs15_parse_tokeninfo(sc_context_t *ctx, - u8 preferred_language[3]; - size_t lang_length = sizeof(preferred_language); - struct sc_asn1_entry asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1], -- asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7]; -+ asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7], -+ asn1_algo_infos_parameters[SC_MAX_SUPPORTED_ALGORITHMS][3]; - size_t reference_len = sizeof(ti->supported_algos[0].reference); - size_t mechanism_len = sizeof(ti->supported_algos[0].mechanism); -+ size_t parameter_len = sizeof(ti->supported_algos[0].parameters); - size_t operations_len = sizeof(ti->supported_algos[0].operations); - size_t algo_ref_len = sizeof(ti->supported_algos[0].algo_ref); - -@@ -152,14 +160,22 @@ int sc_pkcs15_parse_tokeninfo(sc_context_t *ctx, - sc_format_asn1_entry(asn1_twlabel, label, &label_len, 0); - sc_copy_asn1_entry(c_asn1_profile_indication, asn1_profile_indication); - -- for (ii=0; iisupported_algos[ii].reference, &reference_len, 0); - sc_format_asn1_entry(asn1_algo_infos[ii] + 1, &ti->supported_algos[ii].mechanism, &mechanism_len, 0); -- sc_format_asn1_entry(asn1_algo_infos[ii] + 2, NULL, NULL, 0); -+ sc_format_asn1_entry(asn1_algo_infos[ii] + 2, -+ asn1_algo_infos_parameters[ii], NULL, 0); -+ sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0, -+ NULL, NULL, 0); -+ sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 1, -+ &ti->supported_algos[ii].parameters, ¶meter_len, 0); - sc_format_asn1_entry(asn1_algo_infos[ii] + 3, &ti->supported_algos[ii].operations, &operations_len, 0); - sc_format_asn1_entry(asn1_algo_infos[ii] + 4, &ti->supported_algos[ii].algo_id, NULL, 1); - sc_format_asn1_entry(asn1_algo_infos[ii] + 5, &ti->supported_algos[ii].algo_ref, &algo_ref_len, 0); -@@ -270,9 +286,11 @@ sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, - struct sc_asn1_entry asn1_toki_attrs[C_ASN1_TOKI_ATTRS_SIZE]; - struct sc_asn1_entry asn1_tokeninfo[2]; - struct sc_asn1_entry asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1], -- asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7]; -+ asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7], -+ asn1_algo_infos_parameters[SC_MAX_SUPPORTED_ALGORITHMS][3]; - size_t reference_len = sizeof(ti->supported_algos[0].reference); - size_t mechanism_len = sizeof(ti->supported_algos[0].mechanism); -+ size_t parameter_len = sizeof(ti->supported_algos[0].parameters); - size_t operations_len = sizeof(ti->supported_algos[0].operations); - size_t algo_ref_len = sizeof(ti->supported_algos[0].algo_ref); - struct sc_asn1_entry asn1_last_update[C_ASN1_LAST_UPDATE_SIZE]; -@@ -283,14 +301,22 @@ sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, - sc_copy_asn1_entry(c_asn1_last_update, asn1_last_update); - sc_copy_asn1_entry(c_asn1_profile_indication, asn1_profile_indication); - -- for (ii=0; iisupported_algos[ii].reference; ii++) -+ for (ii=0; iisupported_algos[ii].reference; ii++) { - sc_copy_asn1_entry(c_asn1_algorithm_info, asn1_algo_infos[ii]); -+ sc_copy_asn1_entry(c_asn1_algorithm_info_parameters, -+ asn1_algo_infos_parameters[ii]); -+ } - sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms); - - for (ii=0; iisupported_algos[ii].reference; ii++) { - sc_format_asn1_entry(asn1_algo_infos[ii] + 0, &ti->supported_algos[ii].reference, &reference_len, 1); - 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, NULL, NULL, 0); -+ sc_format_asn1_entry(asn1_algo_infos[ii] + 2, -+ asn1_algo_infos_parameters[ii], NULL, 0); -+ sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0, -+ NULL, NULL, 0); -+ sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 1, -+ &ti->supported_algos[ii].parameters, ¶meter_len, 0); - sc_format_asn1_entry(asn1_algo_infos[ii] + 3, &ti->supported_algos[ii].operations, &operations_len, 1); - sc_format_asn1_entry(asn1_algo_infos[ii] + 4, &ti->supported_algos[ii].algo_id, NULL, 1); - sc_format_asn1_entry(asn1_algo_infos[ii] + 5, &ti->supported_algos[ii].algo_ref, &algo_ref_len, 1); - diff --git a/SOURCES/opensc-0.16.0-coolkey-labels.patch b/SOURCES/opensc-0.16.0-coolkey-labels.patch deleted file mode 100644 index 81c9450..0000000 --- a/SOURCES/opensc-0.16.0-coolkey-labels.patch +++ /dev/null @@ -1,68 +0,0 @@ -From a4b6b9630eb2ee684bbf1560a93b3075c7eb58ab Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 4 Jul 2017 14:25:50 +0200 -Subject: [PATCH] [coolkey] Copy labels from certificate objects to the keys - ---- - src/libopensc/pkcs15-coolkey.c | 33 ++++++++++++++++++++++++++++++++- - 1 file changed, 32 insertions(+), 1 deletion(-) - -diff --git a/src/libopensc/pkcs15-coolkey.c b/src/libopensc/pkcs15-coolkey.c -index 5064a0f4f..a5f457acd 100644 ---- a/src/libopensc/pkcs15-coolkey.c -+++ b/src/libopensc/pkcs15-coolkey.c -@@ -484,7 +484,7 @@ static int sc_pkcs15emu_coolkey_init(sc_pkcs15_card_t *p15card) - sc_card_t *card = p15card->card; - sc_serial_number_t serial; - int count; -- -+ struct sc_pkcs15_object *obj; - - SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); - -@@ -558,6 +558,8 @@ static int sc_pkcs15emu_coolkey_init(sc_pkcs15_card_t *p15card) - - - memset(&obj_obj, 0, sizeof(obj_obj)); -+ /* coolkey applets have label only on the certificates, -+ * but we should copy it also to the keys maching the same ID */ - coolkey_get_attribute_bytes(card, &coolkey_obj, CKA_LABEL, (u8 *)obj_obj.label, &len, sizeof(obj_obj.label)); - coolkey_get_flags(card, &coolkey_obj, &obj_obj.flags); - if (obj_obj.flags & SC_PKCS15_CO_FLAG_PRIVATE) { -@@ -677,6 +679,35 @@ static int sc_pkcs15emu_coolkey_init(sc_pkcs15_card_t *p15card) - } - r = (card->ops->card_ctl)(card, SC_CARDCTL_COOLKEY_FINAL_GET_OBJECTS, &count); - -+ /* Iterate over all the created objects and fill missing labels */ -+ for (obj = p15card->obj_list; obj != NULL; obj = obj->next) { -+ struct sc_pkcs15_id *id = NULL; -+ struct sc_pkcs15_object *cert_object; -+ -+ /* label non-empty -- do not overwrite */ -+ if (obj->label[0] != '\0') -+ continue; -+ -+ switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) { -+ case SC_PKCS15_TYPE_PUBKEY: -+ id = &((struct sc_pkcs15_pubkey_info *)obj->data)->id; -+ break; -+ case SC_PKCS15_TYPE_PRKEY: -+ id = &((struct sc_pkcs15_prkey_info *)obj->data)->id; -+ break; -+ default: -+ /* We do not care about other objects */ -+ continue; -+ } -+ r = sc_pkcs15_find_cert_by_id(p15card, id, &cert_object); -+ if (r != 0) -+ continue; -+ -+ sc_log(card->ctx, "Copy label \"%s\" from cert to key object", -+ cert_object->label); -+ memcpy(obj->label, cert_object->label, SC_PKCS15_MAX_LABEL_SIZE); -+ } -+ - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); - } - - diff --git a/SOURCES/opensc-0.16.0-coverity.patch b/SOURCES/opensc-0.16.0-coverity.patch deleted file mode 100644 index dbc3c1c..0000000 --- a/SOURCES/opensc-0.16.0-coverity.patch +++ /dev/null @@ -1,643 +0,0 @@ -From 15163e6212aaf6b2dd5d7b432e5b13ca39496110 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 28 Feb 2017 16:12:31 +0100 -Subject: [PATCH 1/3] Coverity fixes for: - -card-cac.c - * CLANG_WARNING: The left operand of '<' is a garbage value -card-coolkey.c - * CLANG_WARNING: overwriting variable - * CPPCHECK_WARNING: memory leak / overwrite variable - * CLANG_WARNING: null pointer dereference - * UNUSED_VALUE: unused return value -card-gids.c - * CLANG_WARNING: Branch condition evaluates to a garbage value - * SIZEOF_MISMATCH: suspicious_sizeof -card-myeid.c - * RESOURCE_LEAK: Variable "buf" going out of scope leaks the storage it points to. - * CLANG_WARNING: overwriting variable - * (rewrite not to confuse coverity) -pkcs15-cac.c - * RESOURCE_LEAK: Variable "cert_out" going out of scope leaks the storage it points to. -pkcs15-coolkey.c - * UNUSED_VALUE: unused return value -pkcs15-piv.c - * RESOURCE_LEAK: Variable "cert_out" going out of scope leaks the storage it points to. -pkcs15-sc-hsm.c - * DEADCODE -pkcs11/framework-pkcs15.c - * RESOURCE_LEAK: Variable "p15_cert" going out of scope leaks the storage it points to. -pkcs15init/pkcs15-lib.c - * CLANG_WARNING: Assigned value is garbage or undefined -pkcs15init/pkcs15-myeid.c - * UNREACHABLE: Probably wrong placement of code block -tests/p15dump.c - * IDENTICAL_BRANCHES -pkcs15-init.c - * CLANG_WARNING: Potential leak of memory pointed to by 'args.der_encoded.value' -pkcs15-tool.c - * RESOURCE_LEAK: Variable "cert" going out of scope leaks the storage it points to. - * MISSING_BREAK: The above case falls through to this one. -sc-hsm-tool.c - * CLANG_WARNING: Potential leak of memory pointed to by 'sp' -westcos-tool.c - * FORWARD_NULL: Passing null pointer "pin" to "unlock_pin", which dereferences it. - * (rewrite not to confuse coverity) ---- - src/libopensc/card-cac.c | 2 +- - src/libopensc/card-coolkey.c | 7 +++++-- - src/libopensc/card-entersafe.c | 2 +- - src/libopensc/card-gids.c | 7 ++++++- - src/libopensc/card-myeid.c | 20 ++++++++++++-------- - src/libopensc/iso7816.c | 1 + - src/libopensc/pkcs15-cac.c | 5 ++++- - src/libopensc/pkcs15-coolkey.c | 2 ++ - src/libopensc/pkcs15-piv.c | 3 ++- - src/libopensc/pkcs15-sc-hsm.c | 6 ++---- - src/pkcs11/framework-pkcs15.c | 7 ++++++- - src/pkcs15init/pkcs15-lib.c | 2 +- - src/pkcs15init/pkcs15-myeid.c | 4 ++-- - src/tests/p15dump.c | 3 +-- - src/tools/pkcs15-init.c | 4 +++- - src/tools/pkcs15-tool.c | 11 ++++++++--- - src/tools/sc-hsm-tool.c | 2 ++ - src/tools/westcos-tool.c | 6 +++--- - 18 files changed, 62 insertions(+), 32 deletions(-) - -diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c -index d5f8585..788fb52 100644 ---- a/src/libopensc/card-cac.c -+++ b/src/libopensc/card-cac.c -@@ -467,7 +467,7 @@ static int cac_cac1_get_certificate(sc_card_t *card, u8 **out_buf, size_t *out_l - size_t left = 0; - size_t len, next_len; - sc_apdu_t apdu; -- int r; -+ int r = SC_SUCCESS; - - - /* get the size */ -diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c -index c44febe..7672028 100644 ---- a/src/libopensc/card-coolkey.c -+++ b/src/libopensc/card-coolkey.c -@@ -1369,7 +1369,7 @@ coolkey_fill_object(sc_card_t *card, sc_cardctl_coolkey_object_t *obj) - { - int r; - size_t buf_len = obj->length; -- u8 *new_obj_data = malloc(buf_len); -+ u8 *new_obj_data = NULL; - sc_cardctl_coolkey_object_t *obj_entry; - coolkey_private_data_t * priv = COOLKEY_DATA(card); - -@@ -1413,7 +1413,7 @@ coolkey_find_attribute(sc_card_t *card, sc_cardctl_coolkey_attribute_t *attribut - const u8 *obj = attribute->object->data; - const u8 *attr = NULL; - size_t buf_len = attribute->object->length; -- coolkey_object_header_t *object_head = (coolkey_object_header_t *)obj; -+ coolkey_object_header_t *object_head; - int attribute_count,i; - attribute->attribute_data_type = SC_CARDCTL_COOLKEY_ATTR_TYPE_STRING; - attribute->attribute_length = 0; -@@ -1434,6 +1434,7 @@ coolkey_find_attribute(sc_card_t *card, sc_cardctl_coolkey_attribute_t *attribut - if (buf_len <= sizeof(coolkey_v0_object_header_t)) { - return SC_ERROR_CORRUPTED_DATA; - } -+ object_head = (coolkey_object_header_t *)obj; - object_record_type = object_head->record_type; - /* make sure it's a type we recognize */ - if ((object_record_type != COOLKEY_V1_OBJECT) && (object_record_type != COOLKEY_V0_OBJECT)) { -@@ -2183,6 +2184,8 @@ static int coolkey_initialize(sc_card_t *card) - continue; - } - r = coolkey_add_object(priv, object_id, NULL, object_len, 0); -+ if (r != SC_SUCCESS) -+ sc_log(card->ctx, "coolkey_add_object() returned %d", r); - - } - if (r != SC_ERROR_FILE_END_REACHED) { -diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c -index 6e18252..1fe4102 100644 ---- a/src/libopensc/card-entersafe.c -+++ b/src/libopensc/card-entersafe.c -@@ -487,7 +487,7 @@ static int entersafe_select_fid(sc_card_t *card, - sc_file_t **file_out) - { - int r; -- sc_file_t *file=0; -+ sc_file_t *file = NULL; - sc_path_t path; - - memset(&path, 0, sizeof(sc_path_t)); -diff --git a/src/libopensc/card-gids.c b/src/libopensc/card-gids.c -index 51db9af..4db09f5 100644 ---- a/src/libopensc/card-gids.c -+++ b/src/libopensc/card-gids.c -@@ -668,6 +668,7 @@ static int gids_get_crypto_identifier_from_key_ref(sc_card_t *card, const unsign - if (index >= recordsnum) { - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS); - } -+ *cryptoidentifier = 0x00; /* initialize to zero */ - if (records[index].wKeyExchangeKeySizeBits == 1024 || records[index].wSigKeySizeBits == 1024) { - *cryptoidentifier = GIDS_RSA_1024_IDENTIFIER; - return SC_SUCCESS; -@@ -878,12 +879,16 @@ static int gids_read_public_key (struct sc_card *card , unsigned int algorithm, - if (keydata != NULL) { - rsa_key.modulus.data = (u8*) keydata; - rsa_key.modulus.len = len; -+ } else { -+ rsa_key.modulus.len = 0; - } - - keydata = sc_asn1_find_tag(card->ctx, keytemplate, tlen, GIDS_PUBKEY_TAG_EXPONENT, &len); - if (keydata != NULL) { - rsa_key.exponent.data = (u8*) keydata; - rsa_key.exponent.len = len; -+ } else { -+ rsa_key.exponent.len = 0; - } - - if (rsa_key.exponent.len && rsa_key.modulus.len) { -@@ -1453,7 +1458,7 @@ static int gids_import_key(sc_card_t *card, sc_pkcs15_object_t *object, sc_pkcs1 - SC_TEST_GOTO_ERR(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to put the private key - key greater than 2048 bits ?"); - r = SC_SUCCESS; - err: -- sc_mem_clear(buffer, sizeof(buffer)); -+ sc_mem_clear(buffer, buflen); - LOG_FUNC_RETURN(card->ctx, r); - } - -diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c -index 0e75486..65c108f 100644 ---- a/src/libopensc/card-myeid.c -+++ b/src/libopensc/card-myeid.c -@@ -846,20 +846,24 @@ myeid_convert_ec_signature(struct sc_context *ctx, size_t s_len, unsigned char * - if (sig_len != (datalen - len_size - 1)) /* validate size of the DER structure */ - return SC_ERROR_INVALID_DATA; - -- buf = calloc(1, (s_len + 7)/8*2); -+ /* test&fail early */ -+ buflen = (s_len + 7)/8*2; -+ if (buflen > datalen) -+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); -+ -+ buf = calloc(1, buflen); - if (!buf) - LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); -- buflen = (s_len + 7)/8*2; - - r = sc_asn1_sig_value_sequence_to_rs(ctx, data, datalen, buf, buflen); -- if (r < 0) -+ if (r < 0) { - free(buf); -- LOG_TEST_RET(ctx, r, "Failed to cenvert Sig-Value to the raw RS format"); -- -- if (buflen > datalen) -- LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); -+ sc_log(ctx, "Failed to convert Sig-Value to the raw RS format"); -+ return r; -+ } - - memmove(data, buf, buflen); -+ free(buf); - return buflen; - } - -@@ -868,7 +872,7 @@ static int - myeid_compute_signature(struct sc_card *card, const u8 * data, size_t datalen, - u8 * out, size_t outlen) - { -- struct sc_context *ctx = card->ctx; -+ struct sc_context *ctx; - struct sc_apdu apdu; - u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; -diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c -index 296cf69..2539d1c 100644 ---- a/src/libopensc/iso7816.c -+++ b/src/libopensc/iso7816.c -@@ -392,6 +392,7 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file, - sc_log(ctx, " type: %s", type); - sc_log(ctx, " EF structure: %d", byte & 0x07); - sc_log(ctx, " tag 0x82: 0x%02x", byte); -+ /* FIXME: check return value? */ - sc_file_set_type_attr(file, &byte, 1); - } - } -diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c -index 4894fe4..e0fa50b 100644 ---- a/src/libopensc/pkcs15-cac.c -+++ b/src/libopensc/pkcs15-cac.c -@@ -292,7 +292,7 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) - struct sc_pkcs15_object pubkey_obj; - struct sc_pkcs15_object prkey_obj; - sc_pkcs15_der_t cert_der; -- sc_pkcs15_cert_t *cert_out; -+ sc_pkcs15_cert_t *cert_out = NULL; - - r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_GET_NEXT_CERT_OBJECT, &obj_info); - -@@ -352,12 +352,14 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) - r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); - if (r < 0 || cert_out->key == NULL) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to read/parse the certificate r=%d",r); -+ sc_pkcs15_free_certificate(cert_out); - continue; - } - - r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); - if (r < 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, " Failed to add cert obj r=%d",r); -+ sc_pkcs15_free_certificate(cert_out); - continue; - } - /* set the token name to the name of the CN of the first certificate */ -@@ -393,6 +395,7 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) - usage, pubkey_info.usage, prkey_info.usage); - if (cert_out->key->algorithm != SC_ALGORITHM_RSA) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"unsupported key.algorithm %d", cert_out->key->algorithm); -+ sc_pkcs15_free_certificate(cert_out); - continue; - } else { - pubkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; -diff --git a/src/libopensc/pkcs15-coolkey.c b/src/libopensc/pkcs15-coolkey.c -index 487be19..de4920b 100644 ---- a/src/libopensc/pkcs15-coolkey.c -+++ b/src/libopensc/pkcs15-coolkey.c -@@ -667,6 +667,8 @@ static int sc_pkcs15emu_coolkey_init(sc_pkcs15_card_t *p15card) - } - - r = sc_pkcs15emu_object_add(p15card, obj_type, &obj_obj, obj_info); -+ if (r != SC_SUCCESS) -+ sc_log(card->ctx, "sc_pkcs15emu_object_add() returned %d", r); - fail: - if (key) { sc_pkcs15_free_pubkey(key); } - -diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c -index bf72df0..5bd0fdf 100644 ---- a/src/libopensc/pkcs15-piv.c -+++ b/src/libopensc/pkcs15-piv.c -@@ -710,7 +710,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) - struct sc_pkcs15_cert_info cert_info; - struct sc_pkcs15_object cert_obj; - sc_pkcs15_der_t cert_der; -- sc_pkcs15_cert_t *cert_out; -+ sc_pkcs15_cert_t *cert_out = NULL; - - ckis[i].cert_found = 0; - ckis[i].key_alg = -1; -@@ -761,6 +761,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) - r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); - if (r < 0 || cert_out->key == NULL) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to read/parse the certificate r=%d",r); -+ sc_pkcs15_free_certificate(cert_out); - continue; - } - /* -diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c -index 938ea9d..3f6b6e4 100644 ---- a/src/libopensc/pkcs15-sc-hsm.c -+++ b/src/libopensc/pkcs15-sc-hsm.c -@@ -460,6 +460,7 @@ static int sc_pkcs15emu_sc_hsm_get_ec_public_key(struct sc_context *ctx, sc_cvc_ - memcpy(pubkey->u.ec.params.der.value, ecp->der.value, ecp->der.len); - pubkey->u.ec.params.der.len = ecp->der.len; - -+ /* FIXME: check return value? */ - sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); - - return SC_SUCCESS; -@@ -627,11 +628,8 @@ static int sc_pkcs15emu_sc_hsm_add_prkd(sc_pkcs15_card_t * p15card, u8 keyid) { - - len = sizeof efbin; - r = read_file(p15card, fid, efbin, &len); -- LOG_TEST_RET(card->ctx, r, "Could not read EF"); - -- if (r < 0) { -- return SC_SUCCESS; -- } -+ LOG_TEST_RET(card->ctx, r, "Could not read EF"); - - if (efbin[0] == 0x67) { /* Decode CSR and create public key object */ - sc_pkcs15emu_sc_hsm_add_pubkey(p15card, efbin, len, key_info, prkd.label); -diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c -index 0c89d47..732e1e5 100644 ---- a/src/pkcs11/framework-pkcs15.c -+++ b/src/pkcs11/framework-pkcs15.c -@@ -571,8 +571,11 @@ __pkcs15_create_cert_object(struct pkcs15_fw_data *fw_data, struct sc_pkcs15_obj - /* Certificate object */ - rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &object, - cert, &pkcs15_cert_ops, sizeof(struct pkcs15_cert_object)); -- if (rv < 0) -+ if (rv < 0) { -+ if (p15_cert != NULL) -+ sc_pkcs15_free_certificate(p15_cert); - return rv; -+ } - - object->cert_info = p15_info; - object->cert_data = p15_cert; -@@ -643,6 +646,8 @@ __pkcs15_create_pubkey_object(struct pkcs15_fw_data *fw_data, - object->pub_data = p15_key; - if (p15_key && object->pub_info->modulus_length == 0 && p15_key->algorithm == SC_ALGORITHM_RSA) - object->pub_info->modulus_length = 8 * p15_key->u.rsa.modulus.len; -+ } else if (pubkey->emulated && (fw_data->p15_card->flags & SC_PKCS15_CARD_FLAG_EMULATED)) { -+ sc_pkcs15_free_pubkey(p15_key); - } - - if (pubkey_object != NULL) -diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c -index c2fc2df..d1558e2 100644 ---- a/src/pkcs15init/pkcs15-lib.c -+++ b/src/pkcs15init/pkcs15-lib.c -@@ -760,7 +760,7 @@ sc_pkcs15init_add_app(struct sc_card *card, struct sc_profile *profile, - struct sc_pkcs15_object *pin_obj = NULL; - struct sc_app_info *app; - struct sc_file *df = profile->df_info->file; -- int r; -+ int r = SC_SUCCESS; - - LOG_FUNC_CALLED(ctx); - p15card->card = card; -diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c -index 9ed515d..6c93545 100644 ---- a/src/pkcs15init/pkcs15-myeid.c -+++ b/src/pkcs15init/pkcs15-myeid.c -@@ -510,10 +510,10 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, - keybits = key_info->field_length; - else - key_info->field_length = keybits; -- break; -- -+ - if (sc_card_find_ec_alg(p15card->card, keybits, &prkey->u.ec.params.id) == NULL) - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported algorithm or key size"); -+ break; - default: - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store key failed: Unsupported key type"); - break; -diff --git a/src/tests/p15dump.c b/src/tests/p15dump.c -index 17ab86b..da8b4a3 100644 ---- a/src/tests/p15dump.c -+++ b/src/tests/p15dump.c -@@ -30,8 +30,7 @@ static int dump_objects(const char *what, int type) - printf("failed.\n"); - fprintf(stderr, "Error enumerating %s: %s\n", - what, sc_strerror(count)); -- if (SC_SUCCESS != sc_unlock(card)) -- return 1; -+ sc_unlock(card); - return 1; - } - if (count == 0) { -diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c -index a1b183d..a4fb1a9 100644 ---- a/src/tools/pkcs15-init.c -+++ b/src/tools/pkcs15-init.c -@@ -1318,8 +1318,10 @@ do_store_data_object(struct sc_profile *profile) - args.der_encoded.value = data; - args.der_encoded.len = datalen; - r = sc_lock(p15card->card); -- if (r < 0) -+ if (r < 0) { -+ free(data); - return r; -+ } - r = sc_pkcs15init_store_data_object(p15card, profile, &args, NULL); - sc_unlock(p15card->card); - } -diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c -index 092b9d9..e146753 100644 ---- a/src/tools/pkcs15-tool.c -+++ b/src/tools/pkcs15-tool.c -@@ -793,15 +793,18 @@ static int read_public_key(void) - - if (r == SC_ERROR_OBJECT_NOT_FOUND) { - fprintf(stderr, "Public key with ID '%s' not found.\n", opt_pubkey); -- return 2; -+ r = 2; -+ goto out; - } - if (r < 0) { - fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r)); -- return 1; -+ r = 1; -+ goto out; - } - if (!pubkey) { - fprintf(stderr, "Public key not available\n"); -- return 1; -+ r = 1; -+ goto out; - } - - r = sc_pkcs15_encode_pubkey_as_spki(ctx, pubkey, &pem_key.value, &pem_key.len); -@@ -813,6 +816,7 @@ static int read_public_key(void) - free(pem_key.value); - } - -+out: - if (cert) - sc_pkcs15_free_certificate(cert); - else if (pubkey) -@@ -2097,6 +2101,7 @@ int main(int argc, char * const argv[]) - break; - case OPT_USE_PINPAD_DEPRECATED: - fprintf(stderr, "'--no-prompt' is deprecated , use '--use-pinpad' instead.\n"); -+ /* fallthrough */ - case OPT_USE_PINPAD: - opt_use_pinpad = 1; - break; -diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c -index cce855f..029d991 100644 ---- a/src/tools/sc-hsm-tool.c -+++ b/src/tools/sc-hsm-tool.c -@@ -697,6 +697,7 @@ static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_pas - memset(inbuf, 0, sizeof(inbuf)); - if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) { - fprintf(stderr, "Input aborted\n"); -+ free(shares); - return -1; - } - p = (sp->x); -@@ -706,6 +707,7 @@ static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_pas - memset(inbuf, 0, sizeof(inbuf)); - if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) { - fprintf(stderr, "Input aborted\n"); -+ free(shares); - return -1; - } - binlen = 64; -diff --git a/src/tools/westcos-tool.c b/src/tools/westcos-tool.c -index 29b75dd..ff3d5e6 100644 ---- a/src/tools/westcos-tool.c -+++ b/src/tools/westcos-tool.c -@@ -91,8 +91,6 @@ static int finalize = 0; - static int install_pin = 0; - static int overwrite = 0; - --static const char *pin = NULL; --static const char *puk = NULL; - static char *cert = NULL; - - static int keylen = 0; -@@ -260,7 +258,7 @@ static int unlock_pin(sc_card_t *card, - } - else - { -- if(pin == NULL || puk == NULL) -+ if(pin_value == NULL || puk_value == NULL) - { - return SC_ERROR_INVALID_ARGUMENTS; - } -@@ -372,6 +370,8 @@ int main(int argc, char *argv[]) - RSA *rsa = NULL; - BIGNUM *bn = NULL; - BIO *mem = NULL; -+ static const char *pin = NULL; -+ static const char *puk = NULL; - - while (1) - { - -From e73b2ad2e01cbcc3fdee471ce9692ab95a83b8a0 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 1 Mar 2017 09:45:17 +0100 -Subject: [PATCH 2/3] Sanitize call to sc_pkcs15_free_certificate() - ---- - src/libopensc/pkcs15-cac.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c -index e0fa50b..61c6430 100644 ---- a/src/libopensc/pkcs15-cac.c -+++ b/src/libopensc/pkcs15-cac.c -@@ -352,7 +352,8 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) - r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); - if (r < 0 || cert_out->key == NULL) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to read/parse the certificate r=%d",r); -- sc_pkcs15_free_certificate(cert_out); -+ if (cert_out != NULL) -+ sc_pkcs15_free_certificate(cert_out); - continue; - } - - -From bdf452210f7fdbefe91df910025142b2e48b8ebc Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 1 Mar 2017 15:23:17 +0100 -Subject: [PATCH 3/3] Sanitize call to sc_pkcs15_free_certificate() in PIV too - ---- - src/libopensc/pkcs15-piv.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c -index 5bd0fdf..f6b6742 100644 ---- a/src/libopensc/pkcs15-piv.c -+++ b/src/libopensc/pkcs15-piv.c -@@ -761,7 +761,8 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) - r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); - if (r < 0 || cert_out->key == NULL) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to read/parse the certificate r=%d",r); -- sc_pkcs15_free_certificate(cert_out); -+ if (cert_out != NULL) -+ sc_pkcs15_free_certificate(cert_out); - continue; - } - /* -From 389ffe590986c6ed42fa810874a52a51bac3ca26 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Thu, 23 Mar 2017 12:16:46 +0100 -Subject: [PATCH 1/3] Coverity: FORWARD_NULL -- copy&paste error - ---- - src/tools/gids-tool.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/tools/gids-tool.c b/src/tools/gids-tool.c -index 029c53f..84073b6 100644 ---- a/src/tools/gids-tool.c -+++ b/src/tools/gids-tool.c -@@ -277,7 +277,7 @@ static int changeAdminKey(sc_card_t* card, const char *so_pin, const char* new_k - - if (new_key == NULL) { - printf("Enter new admin key (48 hexadecimal characters) : "); -- util_getpass(&_so_pin, NULL, stdin); -+ util_getpass(&_new_key, NULL, stdin); - printf("\n"); - } else { - _new_key = (char *)new_key; --- -2.9.3 - - -From 1133efa4fe4d9a0267486cadbd3f6d144c584645 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Thu, 23 Mar 2017 15:14:35 +0100 -Subject: [PATCH 2/3] CLANG_WARNING: Call to 'malloc' has an allocation size of - 0 bytes - ---- - src/scconf/scconf.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/scconf/scconf.c b/src/scconf/scconf.c -index 7fcc301..678df3e 100644 ---- a/src/scconf/scconf.c -+++ b/src/scconf/scconf.c -@@ -411,6 +411,8 @@ char *scconf_list_strdup(const scconf_list * list, const char *filler) - if (filler) { - len += scconf_list_array_length(list) * (strlen(filler) + 1); - } -+ if (len == 0) -+ return NULL; - buf = malloc(len); - if (!buf) { - return NULL; --- -2.9.3 - - -From f82bc2008d58348cafcbba30623fcb55dab5cb3a Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Thu, 23 Mar 2017 15:46:42 +0100 -Subject: [PATCH 3/3] Avoid malloc with 0 argument - ---- - src/libopensc/card-cac.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c -index 788fb52..6a5b5af 100644 ---- a/src/libopensc/card-cac.c -+++ b/src/libopensc/card-cac.c -@@ -670,12 +670,12 @@ static int cac_read_binary(sc_card_t *card, unsigned int idx, - r = sc_decompress_alloc(&priv->cache_buf, &priv->cache_buf_len, - cert_ptr, cert_len, COMPRESSION_AUTO); - #else -- sc_log(card->ctx, "PIV compression not supported, no zlib"); -+ sc_log(card->ctx, "CAC compression not supported, no zlib"); - r = SC_ERROR_NOT_SUPPORTED; - #endif - if (r) - goto done; -- } else { -+ } else if (cert_len > 0) { - priv->cache_buf = malloc(cert_len); - if (priv->cache_buf == NULL) { - r = SC_ERROR_OUT_OF_MEMORY; -@@ -683,6 +683,9 @@ static int cac_read_binary(sc_card_t *card, unsigned int idx, - } - priv->cache_buf_len = cert_len; - memcpy(priv->cache_buf, cert_ptr, cert_len); -+ } else { -+ sc_log(card->ctx, "Can't read zero-length certificate"); -+ goto done; - } - break; - default: --- -2.9.3 - - diff --git a/SOURCES/opensc-0.16.0-ecdsa-ec-point.patch b/SOURCES/opensc-0.16.0-ecdsa-ec-point.patch deleted file mode 100644 index 3930bb1..0000000 --- a/SOURCES/opensc-0.16.0-ecdsa-ec-point.patch +++ /dev/null @@ -1,27 +0,0 @@ -From ea4baf50d57a7a41164fedcd1b10fdb0438305c5 Mon Sep 17 00:00:00 2001 -From: AnthonyA -Date: Mon, 19 Mar 2018 15:58:21 +0800 -Subject: [PATCH] pkcs11-tool: make ECPoint behaviour standards compliant by - default - -Fixes #1286. The behaviour of pkcs11-tool will follow the standard - -send DER. If EC_POINT_NO_ASN1_OCTET_STRING is defined then it will -write plain bytes. ---- - src/tools/pkcs11-tool.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c -index 876bba2dc..63e5c5f7f 100644 ---- a/src/tools/pkcs11-tool.c -+++ b/src/tools/pkcs11-tool.c -@@ -2632,7 +2632,7 @@ parse_ec_pkey(EVP_PKEY *pkey, int private, struct gostkey_info *gost) - header_len = point-gost->public.value; - memcpy(point, buf, point_len); - gost->public.len = header_len+point_len; --#ifndef EC_POINT_NO_ASN1_OCTET_STRING // workaround for non-compliant cards not expecting DER encoding -+#ifdef EC_POINT_NO_ASN1_OCTET_STRING // workaround for non-compliant cards not expecting DER encoding - gost->public.len -= header_len; - gost->public.value += header_len; - #endif - diff --git a/SOURCES/opensc-0.16.0-hexadecimal-mechanism.patch b/SOURCES/opensc-0.16.0-hexadecimal-mechanism.patch deleted file mode 100644 index 2e30934..0000000 --- a/SOURCES/opensc-0.16.0-hexadecimal-mechanism.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 74885fb1c174468cc0a505cd7404e228d465efd8 Mon Sep 17 00:00:00 2001 -From: AnthonyA -Date: Tue, 27 Mar 2018 00:48:05 +0000 -Subject: [PATCH] pkcs11-tool: allow mechanism to be specified in hexadecimal - -To support vendor mechanisms, let -m accept hexadecimal strings, -e.g., -m 0x80001234 ---- - doc/tools/pkcs11-tool.1.xml | 3 ++- - src/tools/pkcs11-tool.c | 5 ++++- - 2 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/doc/tools/pkcs11-tool.1.xml b/doc/tools/pkcs11-tool.1.xml -index f8d638b45..e78570b10 100644 ---- a/doc/tools/pkcs11-tool.1.xml -+++ b/doc/tools/pkcs11-tool.1.xml -@@ -231,7 +231,8 @@ - - Use the specified mechanism - for token operations. See for a list -- of mechanisms supported by your token. -+ of mechanisms supported by your token. The mechanism can also be specified in -+ hexadecimal, e.g., 0x80001234. - - - -diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c -index 63e5c5f7f..484c019d8 100644 ---- a/src/tools/pkcs11-tool.c -+++ b/src/tools/pkcs11-tool.c -@@ -234,7 +234,7 @@ static const char *option_help[] = { - "Hash some data", - "Derive a secret key using another key and some data", - "Derive ECDHpass DER encoded pubkey for compatibility with some PKCS#11 implementations", -- "Specify mechanism (use -M for a list of supported mechanisms)", -+ "Specify mechanism (use -M for a list of supported mechanisms), or by hexadecimal, e.g., 0x80001234", - - "Log into the token first", - "Specify login type ('so', 'user', 'context-specific'; default:'user')", -@@ -6076,6 +6076,9 @@ static CK_MECHANISM_TYPE p11_name_to_mechanism(const char *name) - { - struct mech_info *mi; - -+ if (strncasecmp("0x", name, 2) == 0) { -+ return strtoul(name, NULL, 0); -+ } - for (mi = p11_mechanisms; mi->name; mi++) { - if (!strcasecmp(mi->name, name) - || (mi->short_name && !strcasecmp(mi->short_name, name))) - diff --git a/SOURCES/opensc-0.16.0-infinite-loop.patch b/SOURCES/opensc-0.16.0-infinite-loop.patch deleted file mode 100644 index 732314d..0000000 --- a/SOURCES/opensc-0.16.0-infinite-loop.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 645f678af24fc1e0f1559e0384f57f8fd35836b4 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 21 Jul 2017 11:30:47 +0200 -Subject: [PATCH 1/4] cac: Make the retransmitted APDU valid by restoring the - resplen - ---- - src/libopensc/card-cac.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c -index ed15ba0a8..47f9aaf0c 100644 ---- a/src/libopensc/card-cac.c -+++ b/src/libopensc/card-cac.c -@@ -1106,6 +1106,7 @@ static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc - 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); - } - -From a57407a5257b24edf313a4839c523a19cd8b0dc5 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 21 Jul 2017 13:09:14 +0200 -Subject: [PATCH 2/4] cac: Check SWs for all the APDUs and report the errors to - underlying layers - ---- - src/libopensc/card-cac.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c -index 47f9aaf0c..f3b64a33d 100644 ---- a/src/libopensc/card-cac.c -+++ b/src/libopensc/card-cac.c -@@ -390,9 +390,7 @@ static int cac_apdu_io(sc_card_t *card, int ins, int p1, int p2, - goto err; - } - -- if (apdu.sw1 == 0x61) { -- r = sc_check_sw(card, apdu.sw1, apdu.sw2); -- } -+ r = sc_check_sw(card, apdu.sw1, apdu.sw2); - - if (r < 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Card returned error "); -diff -up OpenSC-777e2a3751e3f6d53f056c98e9e20e42af674fb1/src/libopensc/card-cac.c.old OpenSC-777e2a3751e3f6d53f056c98e9e20e42af674fb1/src/libopensc/card-cac.c ---- OpenSC-777e2a3751e3f6d53f056c98e9e20e42af674fb1/src/libopensc/card-cac.c.old 2017-12-19 10:39:08.662925868 +0100 -+++ OpenSC-777e2a3751e3f6d53f056c98e9e20e42af674fb1/src/libopensc/card-cac.c 2017-12-19 10:39:58.665293224 +0100 -@@ -450,6 +450,10 @@ static int cac_read_file(sc_card_t *card - if (r < 0) { - goto fail; - } -+ if (len == 0) { -+ r = SC_ERROR_FILE_NOT_FOUND; -+ goto fail; -+ } - } - *out_len = size; - *out_buf = out; diff --git a/SOURCES/opensc-0.16.0-labels-from-dn.patch b/SOURCES/opensc-0.16.0-labels-from-dn.patch deleted file mode 100644 index e0ed69d..0000000 --- a/SOURCES/opensc-0.16.0-labels-from-dn.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 066fdce95a3a58e312f52c4e14536b4b3a4f5e26 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 9 May 2017 16:46:16 +0200 -Subject: [PATCH 1/3] If the underlying PKCS#15 structure does not provide - label for a certificate, try to use DN from the certificate. - ---- - src/libopensc/libopensc.exports | 1 + - src/pkcs11/framework-pkcs15.c | 31 +++++++++++++++++++++++++++++++ - 2 files changed, 32 insertions(+) - -diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports -index 18f80374f..36cf57023 100644 ---- a/src/libopensc/libopensc.exports -+++ b/src/libopensc/libopensc.exports -@@ -208,6 +208,7 @@ sc_pkcs15_free_prkey_info - sc_pkcs15_free_pubkey - sc_pkcs15_free_pubkey_info - sc_pkcs15_get_application_by_type -+sc_pkcs15_get_name_from_dn - sc_pkcs15_get_object_guid - sc_pkcs15_get_object_id - sc_pkcs15_get_objects -diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c -index 42c509356..f9063c8cc 100644 ---- a/src/pkcs11/framework-pkcs15.c -+++ b/src/pkcs11/framework-pkcs15.c -@@ -553,6 +553,30 @@ public_key_created(struct pkcs15_fw_data *fw_data, const struct sc_pkcs15_id *id - return SC_ERROR_OBJECT_NOT_FOUND; - } - -+static void -+pkcs15_cert_extract_label(struct pkcs15_cert_object *cert) -+{ -+ if (!cert || !cert->cert_p15obj || !cert->cert_data) -+ return; -+ -+ sc_log(context, "pkcs15_cert_extract_label() called. Current label: %s", cert->cert_p15obj->label); -+ -+ /* if we didn't get a label, set one based on the CN */ -+ if (*cert->cert_p15obj->label == '\0') { /* can't be NULL -- static array */ -+ static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }}; -+ u8 *cn_name = NULL; -+ size_t cn_len = 0; -+ int rv = sc_pkcs15_get_name_from_dn(context, -+ cert->cert_data->subject, cert->cert_data->subject_len, -+ &cn_oid, &cn_name, &cn_len); -+ sc_log(context, "pkcs15_cert_extract_label(): Name from DN is %s", cn_name); -+ if (rv == SC_SUCCESS) { -+ memcpy(cert->cert_p15obj->label, cn_name, cn_len); -+ cert->cert_p15obj->label[cn_len] = '\0'; -+ } -+ free(cn_name); -+ } -+} - - static int - __pkcs15_create_cert_object(struct pkcs15_fw_data *fw_data, struct sc_pkcs15_object *cert, -@@ -606,6 +627,9 @@ __pkcs15_create_cert_object(struct pkcs15_fw_data *fw_data, struct sc_pkcs15_obj - obj2->pub_genfrom = object; - object->cert_pubkey = obj2; - -+ /* Find missing labels for certificate */ -+ pkcs15_cert_extract_label(object); -+ - if (cert_object != NULL) - *cert_object = (struct pkcs15_any_object *) object; - -@@ -877,6 +901,9 @@ check_cert_data_read(struct pkcs15_fw_data *fw_data, struct pkcs15_cert_object * - if (!obj2->pub_data) - rv = sc_pkcs15_pubkey_from_cert(context, &cert->cert_data->data, &obj2->pub_data); - -+ /* Find missing labels for certificate */ -+ pkcs15_cert_extract_label(cert); -+ - /* now that we have the cert and pub key, lets see if we can bind anything else */ - pkcs15_bind_related_objects(fw_data); - -@@ -3165,6 +3192,10 @@ pkcs15_cert_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT - *(CK_BBOOL*)attr->pValue = FALSE; - break; - case CKA_LABEL: -+ if (check_cert_data_read(fw_data, cert) != 0) { -+ attr->ulValueLen = 0; -+ return CKR_OK; -+ } - len = strnlen(cert->cert_p15obj->label, sizeof cert->cert_p15obj->label); - check_attribute_buffer(attr, len); - memcpy(attr->pValue, cert->cert_p15obj->label, len); - -From 4d8b75c1f0a901d661ed00b29175e2fdaee940ca Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 19 May 2017 17:52:09 +0200 -Subject: [PATCH 2/3] Properly check bounds for long DNs - ---- - src/pkcs11/framework-pkcs15.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c -index f9063c8cc..863ad02a1 100644 ---- a/src/pkcs11/framework-pkcs15.c -+++ b/src/pkcs11/framework-pkcs15.c -@@ -566,8 +566,9 @@ pkcs15_cert_extract_label(struct pkcs15_cert_object *cert) - int rv = sc_pkcs15_get_name_from_dn(context, - cert->cert_data->subject, cert->cert_data->subject_len, - &cn_oid, &cn_name, &cn_len); -- sc_log(context, "pkcs15_cert_extract_label(): Name from DN is %s", cn_name); - if (rv == SC_SUCCESS) { -+ sc_log(context, "pkcs15_cert_extract_label(): Name from DN is %s", cn_name); -+ cn_len = MIN(cn_len, SC_PKCS15_MAX_LABEL_SIZE-1); - memcpy(cert->cert_p15obj->label, cn_name, cn_len); - cert->cert_p15obj->label[cn_len] = '\0'; - } - -From 4621251bbff5cc1df826aa7fdc2aa7dfbae3c8ab Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Mon, 22 May 2017 09:46:56 +0200 -Subject: [PATCH 3/3] Missing include - ---- - src/pkcs11/framework-pkcs15.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c -index 863ad02a1..ce890b7a1 100644 ---- a/src/pkcs11/framework-pkcs15.c -+++ b/src/pkcs11/framework-pkcs15.c -@@ -22,6 +22,7 @@ - #include - #include - #include "libopensc/log.h" -+#include "libopensc/internal.h" - #include "libopensc/asn1.h" - #include "libopensc/cardctl.h" - #include "common/compat_strnlen.h" - diff --git a/SOURCES/opensc-0.16.0-lock.patch b/SOURCES/opensc-0.16.0-lock.patch deleted file mode 100644 index aff8653..0000000 --- a/SOURCES/opensc-0.16.0-lock.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 6b36a341c372f3dcec13c5ddee52fdb907a255a9 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 12 Apr 2017 17:42:54 +0200 -Subject: [PATCH 1/2] Make sure the lock is released when returning - ---- - src/pkcs11/framework-pkcs15.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c -index 2f78a63..3441b99 100644 ---- a/src/pkcs11/framework-pkcs15.c -+++ b/src/pkcs11/framework-pkcs15.c -@@ -487,12 +487,16 @@ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) - goto out; - } - -- if (slot->p11card == NULL) -- return CKR_TOKEN_NOT_PRESENT; -+ if (slot->p11card == NULL) { -+ rv = CKR_TOKEN_NOT_PRESENT; -+ goto out; -+ } - - fw_data = (struct pkcs15_fw_data *) slot->p11card->fws_data[slot->fw_data_idx]; -- if (!fw_data) -- return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetTokenInfo"); -+ if (!fw_data) { -+ rv = sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetTokenInfo"); -+ goto out; -+ } - p15card = fw_data->p15_card; - - /* User PIN flags are cleared before re-calculation */ - -From 8e8f0ffdcc959f9dd7ea9036aea887917e961bd1 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 12 Apr 2017 17:43:32 +0200 -Subject: [PATCH 2/2] pkcs11-tool: Do not use unitialized data when - C_GetTokenInfo() failed - ---- - src/tools/pkcs11-tool.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c -index ef5d2a6..555029d 100644 ---- a/src/tools/pkcs11-tool.c -+++ b/src/tools/pkcs11-tool.c -@@ -1105,6 +1105,9 @@ static void show_token(CK_SLOT_ID slot) - if (rv == CKR_TOKEN_NOT_RECOGNIZED) { - printf(" (token not recognized)\n"); - return; -+ } else if (rv != CKR_OK) { -+ printf("C_GetTokenInfo() failed: rv = %s\n", CKR2Str(rv)); -+ return; - } - if (!(info.flags & CKF_TOKEN_INITIALIZED) && (!verbose)) { - printf(" token state: uninitialized\n"); diff --git a/SOURCES/opensc-0.16.0-pinpad.patch b/SOURCES/opensc-0.16.0-pinpad.patch deleted file mode 100644 index 5611c93..0000000 --- a/SOURCES/opensc-0.16.0-pinpad.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up OpenSC-777e2a3751e3f6d53f056c98e9e20e42af674fb1/etc/opensc.conf.in.pinpad OpenSC-777e2a3751e3f6d53f056c98e9e20e42af674fb1/etc/opensc.conf.in ---- OpenSC-777e2a3751e3f6d53f056c98e9e20e42af674fb1/etc/opensc.conf.in.pinpad 2018-05-28 14:30:05.605085241 +0200 -+++ OpenSC-777e2a3751e3f6d53f056c98e9e20e42af674fb1/etc/opensc.conf.in 2018-05-28 14:31:00.963495548 +0200 -@@ -101,7 +101,8 @@ app default { - # - # Enable pinpad if detected (PC/SC v2.0.2 Part 10) - # Default: true -- # enable_pinpad = false; -+ # RHEL 7.6: Disabled by default, because of many broken readers -+ enable_pinpad = false; - # - # Use specific pcsc provider. - # Default: @DEFAULT_PCSC_PROVIDER@ diff --git a/SOURCES/opensc-0.16.0-piv-cardholder-name.patch b/SOURCES/opensc-0.16.0-piv-cardholder-name.patch deleted file mode 100644 index e1c358e..0000000 --- a/SOURCES/opensc-0.16.0-piv-cardholder-name.patch +++ /dev/null @@ -1,121 +0,0 @@ -From bac1ced89dde5780ecb5014b3887e4fd81c7d81c Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 18 Aug 2017 13:49:57 +0200 -Subject: [PATCH 1/3] Use shorter PIN name for default PIN to accomodate Card - Holder name in future - ---- - src/libopensc/pkcs15-piv.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c -index d38d7ba73..7f9015dcc 100644 ---- a/src/libopensc/pkcs15-piv.c -+++ b/src/libopensc/pkcs15-piv.c -@@ -359,7 +359,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) - }; - - static const pindata pins[] = { -- { "01", "PIV Card Holder pin", "", 0x80, -+ { "01", "PIN", "", 0x80, - /* label, flag and ref will change if using global pin */ - SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, - 8, 4, 8, -@@ -932,7 +932,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) - pin_info.attrs.pin.reference = pin_ref; - pin_info.attrs.pin.flags &= ~SC_PKCS15_PIN_FLAG_LOCAL; - label = "Global PIN"; -- } -+ } - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE Adding pin %d label=%s",i, label); - strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1); - pin_obj.flags = pins[i].obj_flags; - -From 74b070128c27e24aa67db041a049a9eee5dddcd6 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 18 Aug 2017 14:18:00 +0200 -Subject: [PATCH 2/3] Get cardholder name from the first certificate - ---- - src/libopensc/pkcs15-piv.c | 24 +++++++++++++++++++++++- - 1 file changed, 23 insertions(+), 1 deletion(-) - -diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c -index 7f9015dcc..6f3c9199d 100644 ---- a/src/libopensc/pkcs15-piv.c -+++ b/src/libopensc/pkcs15-piv.c -@@ -613,7 +613,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) - char buf[SC_MAX_SERIALNR * 2 + 1]; - common_key_info ckis[PIV_NUM_CERTS_AND_KEYS]; - int follows_nist_fascn = 0; -- -+ char *token_name = NULL; - - SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); - -@@ -765,6 +765,30 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) - sc_pkcs15_free_certificate(cert_out); - continue; - } -+ -+ /* set the token name to the name of the CN of the first certificate */ -+ if (!token_name) { -+ u8 * cn_name = NULL; -+ size_t cn_len = 0; -+ static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }}; -+ r = sc_pkcs15_get_name_from_dn(card->ctx, cert_out->subject, -+ cert_out->subject_len, &cn_oid, &cn_name, &cn_len); -+ if (r == SC_SUCCESS) { -+ token_name = malloc (cn_len+1); -+ if (!token_name) { -+ sc_pkcs15_free_certificate(cert_out); -+ free(cn_name); -+ SC_FUNC_RETURN(card->ctx, -+ SC_ERROR_OUT_OF_MEMORY, r); -+ } -+ memcpy(token_name, cn_name, cn_len); -+ free(cn_name); -+ token_name[cn_len] = 0; -+ free(p15card->tokeninfo->label); -+ p15card->tokeninfo->label = token_name; -+ } -+ } -+ - /* - * get keyUsage if present save in ckis[i] - * Will only use it if this in a non FED issued card - -From 78c2b7b970a8c2d841552926a7f4c386c31abeb8 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Mon, 21 Aug 2017 13:43:08 +0200 -Subject: [PATCH 3/3] Do not add non-informative PIN to the token label - ---- - src/pkcs11/framework-pkcs15.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c -index 5b3cb32e5..8ded1125b 100644 ---- a/src/pkcs11/framework-pkcs15.c -+++ b/src/pkcs11/framework-pkcs15.c -@@ -1024,6 +1024,7 @@ pkcs15_init_slot(struct sc_pkcs15_card *p15card, struct sc_pkcs11_slot *slot, - struct sc_pkcs15_auth_info *pin_info = NULL; - char label[64]; - -+ sc_log(context, "Called"); - pkcs15_init_token_info(p15card, &slot->token_info); - slot->token_info.flags |= CKF_TOKEN_INITIALIZED; - if (auth != NULL) -@@ -1048,9 +1049,10 @@ pkcs15_init_slot(struct sc_pkcs15_card *p15card, struct sc_pkcs11_slot *slot, - pin_info = NULL; - } - else { -- if (auth->label[0]) -+ if (auth->label[0] && strncmp(auth->label, "PIN", 4) != 0) - snprintf(label, sizeof(label), "%.*s (%s)", (int) sizeof auth->label, auth->label, p15card->tokeninfo->label); - else -+ /* The PIN label is empty or says just non-useful "PIN" */ - snprintf(label, sizeof(label), "%s", p15card->tokeninfo->label); - slot->token_info.flags |= CKF_LOGIN_REQUIRED; - } - diff --git a/SOURCES/opensc-0.16.0-simpletlv.patch b/SOURCES/opensc-0.16.0-simpletlv.patch deleted file mode 100644 index 04d1e7f..0000000 --- a/SOURCES/opensc-0.16.0-simpletlv.patch +++ /dev/null @@ -1,21 +0,0 @@ -commit 602279acecb9aaff1154ac1e2993562741a57281 -Author: Jakub Jelen -Date: Tue Jan 2 11:08:31 2018 +0100 - - Skip correctly two bytes after reading 2b size - -diff --git a/src/libopensc/simpletlv.c b/src/libopensc/simpletlv.c -index f526a1cd..ab0401b5 100644 ---- a/src/libopensc/simpletlv.c -+++ b/src/libopensc/simpletlv.c -@@ -90,8 +90,9 @@ sc_simpletlv_read_tag(u8 **buf, size_t buflen, u8 *tag_out, size_t *taglen) - *taglen = 0; - return SC_ERROR_INVALID_ARGUMENTS; - } -+ /* skip two bytes (the size) */ - len = lebytes2ushort(p); -- p++; -+ p+=2; - } - *taglen = len; - *buf = p; diff --git a/SOURCES/opensc-0.19.0-cac1.patch b/SOURCES/opensc-0.19.0-cac1.patch new file mode 100644 index 0000000..a864613 --- /dev/null +++ b/SOURCES/opensc-0.19.0-cac1.patch @@ -0,0 +1,1113 @@ +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-config.patch b/SOURCES/opensc-0.19.0-config.patch new file mode 100644 index 0000000..c409557 --- /dev/null +++ b/SOURCES/opensc-0.19.0-config.patch @@ -0,0 +1,14 @@ +diff -up opensc-0.19.0/etc/opensc.conf.pinpad opensc-0.19.0/etc/opensc.conf +--- opensc-0.19.0/etc/opensc.conf.pinpad 2019-02-06 18:14:26.808343875 +0100 ++++ opensc-0.19.0/etc/opensc.conf 2019-02-06 18:17:06.747828950 +0100 +@@ -4,4 +4,10 @@ app default { + framework pkcs15 { + # use_file_caching = true; + } ++ reader_driver pcsc { ++ # RHEL 7.6: Disabled by default, because of many broken readers ++ enable_pinpad = false; ++ # RHEL 7.7: Backward compatible value with previous version ++ disconnect_action = unpower; ++ } + } diff --git a/SOURCES/opensc-0.19.0-coolkey-matching.patch b/SOURCES/opensc-0.19.0-coolkey-matching.patch new file mode 100644 index 0000000..2f00866 --- /dev/null +++ b/SOURCES/opensc-0.19.0-coolkey-matching.patch @@ -0,0 +1,112 @@ +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 new file mode 100644 index 0000000..12a6d4b --- /dev/null +++ b/SOURCES/opensc-0.19.0-coverity.patch @@ -0,0 +1,446 @@ +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 new file mode 100644 index 0000000..d11869f --- /dev/null +++ b/SOURCES/opensc-0.19.0-dual.patch @@ -0,0 +1,609 @@ +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/SPECS/opensc.spec b/SPECS/opensc.spec index e8de4b6..f3df2a2 100644 --- a/SPECS/opensc.spec +++ b/SPECS/opensc.spec @@ -1,40 +1,24 @@ -%global commit0 777e2a3751e3f6d53f056c98e9e20e42af674fb1 -%global shortcommit0 %(c=%{commit0}; echo ${c:0:7}) - Name: opensc -Version: 0.16.0 -Release: 10.20170227git%{shortcommit0}%{?dist} +Version: 0.19.0 +Release: 3%{?dist} Summary: Smart card library and applications Group: System Environment/Libraries License: LGPLv2+ URL: https://github.com/OpenSC/OpenSC/wiki -Source0: https://github.com/OpenSC/OpenSC/archive/%{commit0}.zip#/%{name}-%{version}-git%{shortcommit0}.zip +Source0: https://github.com/OpenSC/OpenSC/releases/download/%{version}/%{name}-%{version}.tar.gz Source1: opensc.module Source2: pkcs11-switch.sh -Patch0: opensc-0.16.0-coverity.patch -Patch1: opensc-0.16.0-cardos.patch -Patch2: opensc-0.16.0-lock.patch -# Use label from certificate DN if there is none (#1448555) -Patch3: opensc-0.16.0-labels-from-dn.patch -# Use Cardholder name in the token label (#1449740) -Patch4: opensc-0.16.0-piv-cardholder-name.patch -# Avoid infinite loop when reading CAC cards (#1473335) -Patch5: opensc-0.16.0-infinite-loop.patch -# Workaround for CAC Alt tokens (#1473418) -Patch6: opensc-0.16.0-cac-alt.patch -# Copy labels from certificate (#1448555) -Patch7: opensc-0.16.0-coolkey-labels.patch -# Properly parse multi-byte length (#1473418) -Patch8: opensc-0.16.0-simpletlv.patch -# Disable pinpad by default (#1547117, #1547744) -Patch9: opensc-0.16.0-pinpad.patch -# https://github.com/OpenSC/OpenSC/commit/74885fb -Patch10: opensc-0.16.0-hexadecimal-mechanism.patch -# https://github.com/OpenSC/OpenSC/commit/ea4baf5 -Patch11: opensc-0.16.0-ecdsa-ec-point.patch -# https://github.com/OpenSC/OpenSC/commit/60dbebf -Patch12: opensc-0.16.0-cardos5.patch +# Disable pinpad by default and use backward compatible configuration (#1547117, #1547744) +Patch1: opensc-0.19.0-config.patch +# https://github.com/OpenSC/OpenSC/pull/1489 +Patch2: opensc-0.19.0-coverity.patch +# https://github.com/OpenSC/OpenSC/pull/1500 +Patch3: opensc-0.19.0-coolkey-matching.patch +# https://github.com/OpenSC/OpenSC/pull/1502 +Patch4: opensc-0.19.0-cac1.patch +# https://github.com/OpenSC/OpenSC/pull/1549 +Patch5: opensc-0.19.0-dual.patch BuildRequires: pcsc-lite-devel BuildRequires: readline-devel @@ -58,34 +42,31 @@ every software/card that does so, too. %prep -%setup -q -n OpenSC-%{commit0} -%patch0 -p1 -b .coverity -%patch1 -p1 -b .cardos -%patch2 -p1 -b .lock -%patch3 -p1 -b .label -%patch4 -p1 -b .cardholder -%patch5 -p1 -b .infinite -%patch6 -p1 -b .cac-alt -%patch7 -p1 -b .coolkey-labels -%patch8 -p1 -b .simpletlv -%patch9 -p1 -b .pinpad -%patch10 -p1 -b .hex-mech -%patch11 -p1 -b .ec-point -%patch12 -p1 -b .cardos5 +%setup -q +%patch1 -p1 -b .config +%patch2 -p1 -b .coverity +%patch3 -p1 -b .coolkey-match +%patch4 -p1 -b .cac1 +%patch5 -p1 -b .dual cp -p src/pkcs15init/README ./README.pkcs15init cp -p src/scconf/README.scconf . # No {_libdir} here to avoid multilib conflicts; it's just an example -sed -i -e 's|/usr/local/towitoko/lib/|/usr/lib/ctapi/|' etc/opensc.conf.in +sed -i -e 's|/usr/local/towitoko/lib/|/usr/lib/ctapi/|' etc/opensc.conf.example.in %build autoreconf -fvi +%ifarch %{ix86} ppc s390 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-assert \ --enable-pcsc \ + --disable-tests `# Broken release tarball fails to build them` \ + --disable-notify `# This was not present in previous release` \ + --with-completiondir=no `#Bash completion is disabled` \ --enable-sm \ --with-pcsc-provider=libpcsclite.so.1 make %{?_smp_mflags} V=1 @@ -93,12 +74,23 @@ make %{?_smp_mflags} V=1 %install make install DESTDIR=$RPM_BUILD_ROOT -rm -f $RPM_BUILD_ROOT%{_sysconfdir}/opensc.conf -install -Dpm 644 etc/opensc.conf $RPM_BUILD_ROOT%{_sysconfdir}/opensc-%{_arch}.conf +rm -f $RPM_BUILD_ROOT%{_bindir}/opensc-notify install -Dpm 644 %{SOURCE1} $RPM_BUILD_ROOT%{_datadir}/p11-kit/modules/opensc.module install -Dpm 755 %{SOURCE2} $RPM_BUILD_ROOT%{_bindir}/pkcs11-switch + +%ifarch %{ix86} ppc s390 +# To avoid multilib issues, move these files on 32b intel architectures +rm -f $RPM_BUILD_ROOT%{_sysconfdir}/opensc.conf +install -Dpm 644 etc/opensc.conf $RPM_BUILD_ROOT%{_sysconfdir}/opensc-%{_arch}.conf +rm -f $RPM_BUILD_ROOT%{_mandir}/man5/opensc.conf.5 +install -Dpm 644 doc/files/opensc.conf.5 $RPM_BUILD_ROOT%{_mandir}/man5/opensc-%{_arch}.conf.5 # use NEWS file timestamp as reference for configuration file touch -r NEWS $RPM_BUILD_ROOT%{_sysconfdir}/opensc-%{_arch}.conf +touch -r NEWS $RPM_BUILD_ROOT%{_mandir}/man5/opensc-%{_arch}.conf.5 +%else +# For backward compatibility, symlink the old location to the new files +ln -s %{_sysconfdir}/opensc.conf $RPM_BUILD_ROOT%{_sysconfdir}/opensc-%{_arch}.conf +%endif find $RPM_BUILD_ROOT%{_libdir} -type f -name "*.la" | xargs rm @@ -109,10 +101,15 @@ rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/opensc # Remove the symlink as nothing is supposed to link against libopensc. rm -f $RPM_BUILD_ROOT%{_libdir}/libopensc.so rm -f $RPM_BUILD_ROOT%{_libdir}/libsmm-local.so +rm -f $RPM_BUILD_ROOT%{_mandir}/man1/opensc-notify.1* +rm -f $RPM_BUILD_ROOT%{_datadir}/applications/org.opensc.notify.desktop %if 0%{?rhel} rm -rf %{buildroot}%{_sysconfdir}/bash_completion.d/ %endif +# the npa-tool builds to nothing since we do not have OpenPACE library +rm -rf %{buildroot}%{_bindir}/npa-tool +rm -rf %{buildroot}%{_mandir}/man1/npa-tool.1* %post -p /sbin/ldconfig @@ -127,6 +124,13 @@ rm -rf %{buildroot}%{_sysconfdir}/bash_completion.d/ %{_sysconfdir}/bash_completion.d/* %endif +%ifarch %{ix86} ppc s390 +%{_mandir}/man5/opensc-%{_arch}.conf.5* +%else +%config(noreplace) %{_sysconfdir}/opensc.conf +%{_mandir}/man5/opensc.conf.5* +%endif + %config(noreplace) %{_sysconfdir}/opensc-%{_arch}.conf %{_datadir}/p11-kit/modules/opensc.module %{_bindir}/cardos-tool @@ -138,6 +142,7 @@ rm -rf %{buildroot}%{_sysconfdir}/bash_completion.d/ %{_bindir}/openpgp-tool %{_bindir}/opensc-explorer %{_bindir}/opensc-tool +%{_bindir}/opensc-asn1 %{_bindir}/piv-tool %{_bindir}/pkcs11-tool %{_bindir}/pkcs11-switch @@ -147,6 +152,7 @@ rm -rf %{buildroot}%{_sysconfdir}/bash_completion.d/ %{_bindir}/sc-hsm-tool %{_bindir}/dnie-tool %{_bindir}/westcos-tool +%{_bindir}/egk-tool %{_libdir}/lib*.so.* %{_libdir}/opensc-pkcs11.so %{_libdir}/pkcs11-spy.so @@ -166,6 +172,7 @@ rm -rf %{buildroot}%{_sysconfdir}/bash_completion.d/ %{_mandir}/man1/openpgp-tool.1* %{_mandir}/man1/opensc-explorer.* %{_mandir}/man1/opensc-tool.1* +%{_mandir}/man1/opensc-asn1.1* %{_mandir}/man1/piv-tool.1* %{_mandir}/man1/pkcs11-tool.1* %{_mandir}/man1/pkcs15-crypt.1* @@ -174,10 +181,35 @@ rm -rf %{buildroot}%{_sysconfdir}/bash_completion.d/ %{_mandir}/man1/sc-hsm-tool.1* %{_mandir}/man1/westcos-tool.1* %{_mandir}/man1/dnie-tool.1* -%{_mandir}/man5/*.5* +%{_mandir}/man1/egk-tool.1* +%{_mandir}/man5/pkcs15-profile.5* %changelog +* Wed Mar 27 2019 Jakub Jelen - 0.19.0-3 +- Make OpenSC multilib also on s390 and ppc arches + +* Wed Mar 27 2019 Jakub Jelen - 0.19.0-2 +- Make OpenSC multilib again by moving the conflicting files on ix86 arch + +* Thu Feb 07 2019 Jakub Jelen - 0.19.0-1 +- Rebase to new upstream release (#1656791) + - Add Support for HID Crescendo 144K (#1612372) + - Add Support for CAC Alt tokens (#1645581) + - Fix usage detection from certificates (#1672898) + - Fix security issues: + - CVE-2018-16391 + - CVE-2018-16392 + - CVE-2018-16393 + - CVE-2018-16418 + - CVE-2018-16419 + - CVE-2018-16420 + - CVE-2018-16421 + - CVE-2018-16422 + - CVE-2018-16423 + - CVE-2018-16426 + - CVE-2018-16427 + * Tue Jul 03 2018 Jakub Jelen - 0.16.0-10.20170227git - Improve support for ECC-enabled CardOS 5.3 card (#1562277)