From 321a518128bd4d9b55c57527c540ffedc7de2c23 Mon Sep 17 00:00:00 2001 From: James Antill Date: Thu, 26 May 2022 12:28:30 -0400 Subject: [PATCH] Auto sync2gitlab import of opensc-0.20.0-4.el8.src.rpm --- .gitignore | 1 + EMPTY | 1 - opensc-0.19.0-idprime.patch | 1848 ++++++++++++++++++++++++++++ opensc-0.19.0-pinpad.patch | 13 + opensc-0.20.0-CVE-2020-26570.patch | 31 + opensc-0.20.0-CVE-2020-26571.patch | 42 + opensc-0.20.0-CVE-2020-26572.patch | 21 + opensc-0.20.0-cac-pin-change.patch | 102 ++ opensc-0.20.0-calloc0.patch | 102 ++ opensc-0.20.0-cardos.patch | 1338 ++++++++++++++++++++ opensc-0.20.0-file-cache.patch | 85 ++ opensc-0.20.0-label-padding.patch | 24 + opensc.module | 8 + opensc.spec | 716 +++++++++++ sources | 1 + 15 files changed, 4332 insertions(+), 1 deletion(-) create mode 100644 .gitignore delete mode 100644 EMPTY create mode 100644 opensc-0.19.0-idprime.patch create mode 100644 opensc-0.19.0-pinpad.patch create mode 100644 opensc-0.20.0-CVE-2020-26570.patch create mode 100644 opensc-0.20.0-CVE-2020-26571.patch create mode 100644 opensc-0.20.0-CVE-2020-26572.patch create mode 100644 opensc-0.20.0-cac-pin-change.patch create mode 100644 opensc-0.20.0-calloc0.patch create mode 100644 opensc-0.20.0-cardos.patch create mode 100644 opensc-0.20.0-file-cache.patch create mode 100644 opensc-0.20.0-label-padding.patch create mode 100644 opensc.module create mode 100644 opensc.spec create mode 100644 sources diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c729d1a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/opensc-0.20.0.tar.gz diff --git a/EMPTY b/EMPTY deleted file mode 100644 index 0519ecb..0000000 --- a/EMPTY +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/opensc-0.19.0-idprime.patch b/opensc-0.19.0-idprime.patch new file mode 100644 index 0000000..7858e19 --- /dev/null +++ b/opensc-0.19.0-idprime.patch @@ -0,0 +1,1848 @@ +diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am +index 49d122682f..a9f200c959 100644 +--- a/src/libopensc/Makefile.am ++++ b/src/libopensc/Makefile.am +@@ -48,14 +48,14 @@ libopensc_la_SOURCES_BASE = \ + card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ + card-dnie.c cwa14890.c cwa-dnie.c \ + card-isoApplet.c card-masktech.c card-gids.c card-jpki.c \ +- card-npa.c card-esteid2018.c \ ++ card-npa.c card-esteid2018.c card-idprime.c \ + \ + pkcs15-openpgp.c pkcs15-starcert.c \ + pkcs15-tcos.c pkcs15-esteid.c pkcs15-gemsafeGPK.c \ + pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \ + pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ + pkcs15-oberthur.c pkcs15-itacns.c pkcs15-gemsafeV1.c pkcs15-sc-hsm.c \ +- pkcs15-coolkey.c pkcs15-din-66291.c \ ++ pkcs15-coolkey.c pkcs15-din-66291.c pkcs15-idprime.c \ + pkcs15-dnie.c pkcs15-gids.c pkcs15-iasecc.c pkcs15-jpki.c pkcs15-esteid2018.c \ + compression.c p15card-helper.c sm.c \ + aux-data.c +@@ -131,14 +131,14 @@ TIDY_FILES = \ + card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ + cwa14890.c cwa-dnie.c \ + card-isoApplet.c card-masktech.c card-jpki.c \ +- card-npa.c card-esteid2018.c \ ++ card-npa.c card-esteid2018.c card-idprime.c \ + \ + pkcs15-openpgp.c \ + pkcs15-tcos.c pkcs15-esteid.c \ + pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c \ + pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ + pkcs15-oberthur.c pkcs15-itacns.c pkcs15-sc-hsm.c \ +- pkcs15-coolkey.c pkcs15-din-66291.c \ ++ pkcs15-coolkey.c pkcs15-din-66291.c pkcs15-idprime.c \ + pkcs15-dnie.c pkcs15-gids.c pkcs15-iasecc.c pkcs15-jpki.c pkcs15-esteid2018.c \ + compression.c p15card-helper.c sm.c \ + aux-data.c \ +diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak +index 487fbeb4a6..2e3c30c22b 100644 +--- a/src/libopensc/Makefile.mak ++++ b/src/libopensc/Makefile.mak +@@ -27,7 +27,7 @@ OBJECTS = \ + card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \ + card-sc-hsm.obj card-dnie.obj card-isoApplet.obj pkcs15-coolkey.obj \ + card-masktech.obj card-gids.obj card-jpki.obj \ +- card-npa.obj card-esteid2018.obj \ ++ card-npa.obj card-esteid2018.obj card-idprime.obj \ + \ + pkcs15-openpgp.obj pkcs15-starcert.obj \ + pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-gemsafeGPK.obj \ +@@ -35,7 +35,7 @@ OBJECTS = \ + pkcs15-cac.obj pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-din-66291.obj \ + pkcs15-oberthur.obj pkcs15-itacns.obj pkcs15-gemsafeV1.obj pkcs15-sc-hsm.obj \ + pkcs15-dnie.obj pkcs15-gids.obj pkcs15-iasecc.obj pkcs15-jpki.obj \ +- pkcs15-esteid2018.obj \ ++ pkcs15-esteid2018.obj pkcs15-idprime.obj \ + compression.obj p15card-helper.obj sm.obj \ + aux-data.obj \ + $(TOPDIR)\win32\versioninfo.res +diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c +index d59b4337c8..2c9361df88 100644 +--- a/src/libopensc/card-cac.c ++++ b/src/libopensc/card-cac.c +@@ -54,6 +54,7 @@ + #endif + #include "iso7816.h" + #include "card-cac-common.h" ++#include "pkcs15.h" + + /* + * CAC hardware and APDU constants +diff --git a/src/libopensc/card-cac1.c b/src/libopensc/card-cac1.c +index 08d62b62cc..67035d64e6 100644 +--- a/src/libopensc/card-cac1.c ++++ b/src/libopensc/card-cac1.c +@@ -54,6 +54,7 @@ + #endif + #include "iso7816.h" + #include "card-cac-common.h" ++#include "pkcs15.h" + + /* + * CAC hardware and APDU constants +diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c +new file mode 100644 +index 0000000000..7399830afd +--- /dev/null ++++ b/src/libopensc/card-idprime.c +@@ -0,0 +1,803 @@ ++/* ++ * card-idprime.c: Support for Gemalto IDPrime smart cards ++ * ++ * Copyright (c) 2019 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 "internal.h" ++#include ++#include ++#include ++#ifdef ENABLE_ZLIB ++#include "compression.h" ++#endif ++ ++#include "cardctl.h" ++#include "pkcs15.h" ++ ++static const struct sc_card_operations *iso_ops = NULL; ++ ++static struct sc_card_operations idprime_ops; ++static struct sc_card_driver idprime_drv = { ++ "Gemalto IDPrime", ++ "idprime", ++ &idprime_ops, ++ NULL, 0, NULL ++}; ++ ++/* This ATR says, there is no EF.DIR nor EF.ATR so ISO discovery mechanisms ++ * are not useful here */ ++static const struct sc_atr_table idprime_atrs[] = { ++ { "3b:7f:96:00:00:80:31:80:65:b0:84:41:3d:f6:12:0f:fe:82:90:00", ++ "ff:ff:00:ff:ff:ff:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff", ++ "Gemalto IDPrime MD 8840, 3840, 3810, 840 and 830 Cards", ++ SC_CARD_TYPE_IDPRIME_GENERIC, 0, NULL }, ++}; ++ ++static const sc_path_t idprime_path = { ++ "", 0, ++ 0, 0, SC_PATH_TYPE_DF_NAME, ++ { "\xA0\x00\x00\x00\x18\x80\x00\x00\x00\x06\x62", 11 } ++}; ++ ++/* data structures to store meta data about IDPrime objects */ ++typedef struct idprime_object { ++ int fd; ++ unsigned char key_reference; ++ u8 df[2]; ++ unsigned short length; ++} idprime_object_t; ++ ++/* ++ * IDPrime private data per card state ++ */ ++typedef struct idprime_private_data { ++ 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 */ ++ size_t file_size; /* this is real file size since IDPrime is quite strict about lengths */ ++ list_t pki_list; /* list of pki containers */ ++ idprime_object_t *pki_current; /* current pki object _ctl function */ ++ int tinfo_present; /* Token Info Label object is present*/ ++ u8 tinfo_df[2]; /* DF of object with Token Info Label */ ++} idprime_private_data_t; ++ ++/* For SimCList autocopy, we need to know the size of the data elements */ ++static size_t idprime_list_meter(const void *el) { ++ return sizeof(idprime_object_t); ++} ++ ++void idprime_free_private_data(idprime_private_data_t *priv) ++{ ++ free(priv->cache_buf); ++ list_destroy(&priv->pki_list); ++ free(priv); ++ return; ++} ++ ++idprime_private_data_t *idprime_new_private_data(void) ++{ ++ idprime_private_data_t *priv; ++ ++ priv = calloc(1, sizeof(idprime_private_data_t)); ++ if (priv == NULL) ++ return NULL; ++ ++ /* Initialize PKI Applets list */ ++ if (list_init(&priv->pki_list) != 0 || ++ list_attributes_copy(&priv->pki_list, idprime_list_meter, 1) != 0) { ++ idprime_free_private_data(priv); ++ return NULL; ++ } ++ ++ return priv; ++} ++ ++int idprime_add_object_to_list(list_t *list, const idprime_object_t *object) ++{ ++ if (list_append(list, object) < 0) ++ return SC_ERROR_INTERNAL; ++ return SC_SUCCESS; ++} ++ ++/* This selects main IDPrime AID which is used for communication with ++ * the card */ ++static int idprime_select_idprime(sc_card_t *card) ++{ ++ return iso_ops->select_file(card, &idprime_path, NULL); ++} ++ ++/* This select some index file, which is useful for enumerating other files ++ * on the card */ ++static int idprime_select_index(sc_card_t *card) ++{ ++ int r; ++ sc_file_t *file = NULL; ++ sc_path_t index_path; ++ ++ /* First, we need to make sure the IDPrime AID is selected */ ++ r = idprime_select_idprime(card); ++ if (r != SC_SUCCESS) { ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ ++ /* Returns FCI with expected length of data */ ++ sc_format_path("0101", &index_path); ++ r = iso_ops->select_file(card, &index_path, &file); ++ if (r == SC_SUCCESS) { ++ r = file->size; ++ } ++ sc_file_free(file); ++ /* Ignore too large files */ ++ if (r > MAX_FILE_SIZE) { ++ r = SC_ERROR_INVALID_DATA; ++ } ++ return r; ++} ++ ++static int idprime_process_index(sc_card_t *card, idprime_private_data_t *priv, int length) ++{ ++ u8 *buf = NULL; ++ int r = SC_ERROR_OUT_OF_MEMORY; ++ int i, num_entries; ++ idprime_object_t new_object; ++ ++ buf = malloc(length); ++ if (buf == NULL) { ++ goto done; ++ } ++ ++ r = iso_ops->read_binary(card, 0, buf, length, 0); ++ if (r < 1) { ++ r = SC_ERROR_WRONG_LENGTH; ++ goto done; ++ } ++ ++ /* First byte shows the number of entries, each of them 21 bytes long */ ++ num_entries = buf[0]; ++ if (r < num_entries*21 + 1) { ++ r = SC_ERROR_INVALID_DATA; ++ goto done; ++ } ++ new_object.fd = 0; ++ for (i = 0; i < num_entries; i++) { ++ u8 *start = &buf[i*21+1]; ++ ++ /* First two bytes specify the object DF */ ++ new_object.df[0] = start[0]; ++ new_object.df[1] = start[1]; ++ /* Second two bytes refer to the object size */ ++ new_object.length = bebytes2ushort(&start[2]); ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "df=%s, len=%u", ++ sc_dump_hex(new_object.df, sizeof(new_object.df)), new_object.length); ++ /* in minidriver, mscp/kxcNN or kscNN lists certificates */ ++ if (((memcmp(&start[4], "ksc", 3) == 0) || memcmp(&start[4], "kxc", 3) == 0) ++ && (memcmp(&start[12], "mscp", 5) == 0)) { ++ new_object.fd++; ++ if (card->type == SC_CARD_TYPE_IDPRIME_V2) { ++ /* The key reference starts from 0x11 */ ++ new_object.key_reference = 0x10 + new_object.fd; ++ } else { ++ /* The key reference is one bigger than the value found here for some reason */ ++ new_object.key_reference = start[8] + 1; ++ } ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found certificate with fd=%d, key_ref=%d", ++ new_object.fd, new_object.key_reference); ++ idprime_add_object_to_list(&priv->pki_list, &new_object); ++ ++ /* This looks like non-standard extension listing pkcs11 token info label in my card */ ++ } else if ((memcmp(&start[4], "tinfo", 6) == 0) && (memcmp(&start[12], "p11", 4) == 0)) { ++ memcpy(priv->tinfo_df, new_object.df, sizeof(priv->tinfo_df)); ++ priv->tinfo_present = 1; ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found p11/tinfo object"); ++ } ++ } ++ r = SC_SUCCESS; ++done: ++ free(buf); ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ ++/* CPLC has 42 bytes, but we get it with 3B header */ ++#define CPLC_LENGTH 45 ++static int idprime_init(sc_card_t *card) ++{ ++ int r; ++ unsigned long flags; ++ idprime_private_data_t *priv = NULL; ++ struct sc_apdu apdu; ++ u8 rbuf[CPLC_LENGTH]; ++ size_t rbuflen = sizeof(rbuf); ++ ++ /* We need to differentiate the OS version since they behave slightly differently */ ++ sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xCA, 0x9F, 0x7F); ++ apdu.resp = rbuf; ++ apdu.resplen = rbuflen; ++ apdu.le = rbuflen; ++ r = sc_transmit_apdu(card, &apdu); ++ card->type = SC_CARD_TYPE_IDPRIME_GENERIC; ++ if (r == SC_SUCCESS && apdu.resplen == CPLC_LENGTH) { ++ /* We are interested in the OS release level here */ ++ switch (rbuf[11]) { ++ case 0x01: ++ card->type = SC_CARD_TYPE_IDPRIME_V1; ++ sc_log(card->ctx, "Detected IDPrime applet version 1"); ++ break; ++ case 0x02: ++ card->type = SC_CARD_TYPE_IDPRIME_V2; ++ sc_log(card->ctx, "Detected IDPrime applet version 2"); ++ break; ++ default: ++ sc_log(card->ctx, "Unknown OS version received: %d", rbuf[11]); ++ break; ++ } ++ } else { ++ sc_log(card->ctx, "Failed to get CPLC data or invalid length returned, " ++ "err=%d, len=%"SC_FORMAT_LEN_SIZE_T"u", ++ r, apdu.resplen); ++ } ++ ++ /* Now, select and process the index file */ ++ r = idprime_select_index(card); ++ if (r <= 0) { ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Index file found"); ++ ++ priv = idprime_new_private_data(); ++ if (!priv) { ++ return SC_ERROR_OUT_OF_MEMORY; ++ } ++ ++ r = idprime_process_index(card, priv, r); ++ if (r != SC_SUCCESS) { ++ idprime_free_private_data(priv); ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ ++ card->drv_data = priv; ++ ++ switch (card->type) { ++ case SC_CARD_TYPE_IDPRIME_V1: ++ card->name = "Gemalto IDPrime (OSv1)"; ++ break; ++ case SC_CARD_TYPE_IDPRIME_V2: ++ card->name = "Gemalto IDPrime (OSv2)"; ++ break; ++ case SC_CARD_TYPE_IDPRIME_GENERIC: ++ default: ++ card->name = "Gemalto IDPrime (generic)"; ++ break; ++ } ++ card->cla = 0x00; ++ ++ /* Set up algorithm info. */ ++ flags = SC_ALGORITHM_RSA_PAD_PKCS1 ++ | SC_ALGORITHM_RSA_PAD_PSS ++ | SC_ALGORITHM_RSA_PAD_OAEP ++ /* SHA-1 mechanisms are not allowed in the card I have */ ++ | (SC_ALGORITHM_RSA_HASH_SHA256 | SC_ALGORITHM_RSA_HASH_SHA384 | SC_ALGORITHM_RSA_HASH_SHA512) ++ | (SC_ALGORITHM_MGF1_SHA256 | SC_ALGORITHM_MGF1_SHA384 | SC_ALGORITHM_MGF1_SHA512) ++ ; ++ ++ _sc_card_add_rsa_alg(card, 1024, flags, 0); ++ _sc_card_add_rsa_alg(card, 2048, flags, 0); ++ ++ card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; ++ ++ LOG_FUNC_RETURN(card->ctx, 0); ++} ++ ++static int idprime_finish(sc_card_t *card) ++{ ++ idprime_private_data_t * priv = card->drv_data; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ if (priv) { ++ idprime_free_private_data(priv); ++ } ++ return SC_SUCCESS; ++} ++ ++static int idprime_match_card(sc_card_t *card) ++{ ++ int i, r; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ i = _sc_match_atr(card, idprime_atrs, &card->type); ++ if (i < 0) ++ return 0; ++ ++ r = idprime_select_index(card); ++ return (r > 0); ++} ++ ++/* initialize getting a list and return the number of elements in the list */ ++static int idprime_get_init_and_get_count(list_t *list, idprime_object_t **entry, int *countp) ++{ ++ if (countp == NULL || entry == NULL) { ++ return SC_ERROR_INVALID_ARGUMENTS; ++ } ++ *countp = list_size(list); ++ list_iterator_start(list); ++ *entry = list_iterator_next(list); ++ return SC_SUCCESS; ++} ++ ++/* finalize the list iterator */ ++static int idprime_final_iterator(list_t *list) ++{ ++ list_iterator_stop(list); ++ return SC_SUCCESS; ++} ++ ++/* fill in the prkey_info for the current object on the list and advance to the next object */ ++static int idprime_fill_prkey_info(list_t *list, idprime_object_t **entry, sc_pkcs15_prkey_info_t *prkey_info) ++{ ++ memset(prkey_info, 0, sizeof(sc_pkcs15_prkey_info_t)); ++ if (*entry == NULL) { ++ return SC_ERROR_FILE_END_REACHED; ++ } ++ ++ prkey_info->path.len = sizeof((*entry)->df); ++ memcpy(prkey_info->path.value, (*entry)->df, sizeof((*entry)->df)); ++ prkey_info->path.type = SC_PATH_TYPE_FILE_ID; ++ /* Do not specify the length -- it will be read from the FCI */ ++ prkey_info->path.count = -1; ++ ++ /* TODO figure out the IDs as the original driver? */ ++ prkey_info->id.value[0] = ((*entry)->fd >> 8) & 0xff; ++ prkey_info->id.value[1] = (*entry)->fd & 0xff; ++ prkey_info->id.len = 2; ++ prkey_info->key_reference = (*entry)->key_reference; ++ *entry = list_iterator_next(list); ++ return SC_SUCCESS; ++} ++ ++#define IDPRIME_CARDID_LEN 16 ++ ++static int idprime_get_serial(sc_card_t* card, sc_serial_number_t* serial) ++{ ++ sc_path_t cardid_path; ++ sc_file_t *file = NULL; ++ u8 buf[IDPRIME_CARDID_LEN]; ++ int r; ++ ++ LOG_FUNC_CALLED(card->ctx); ++ ++ /* XXX this is assumed to be cardid for windows. It can be read from the index file */ ++ sc_format_path("0201", &cardid_path); ++ r = iso_ops->select_file(card, &cardid_path, &file); ++ if (r != SC_SUCCESS || file->size != IDPRIME_CARDID_LEN) { /* The cardid is always 16 B */ ++ sc_file_free(file); ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH); ++ } ++ ++ r = iso_ops->read_binary(card, 0, buf, file->size, 0); ++ sc_file_free(file); ++ if (r < 1) { ++ LOG_FUNC_RETURN(card->ctx, r); ++ } else if (r != IDPRIME_CARDID_LEN) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); ++ } ++ ++ serial->len = MIN(IDPRIME_CARDID_LEN, SC_MAX_SERIALNR); ++ memcpy(serial->value, buf, serial->len); ++ LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); ++} ++ ++static int idprime_get_token_name(sc_card_t* card, char** tname) ++{ ++ idprime_private_data_t * priv = card->drv_data; ++ sc_path_t tinfo_path = {"\x00\x00", 2, 0, 0, SC_PATH_TYPE_PATH, {"", 0}}; ++ sc_file_t *file = NULL; ++ u8 buf[2]; ++ int r; ++ ++ LOG_FUNC_CALLED(card->ctx); ++ ++ if (tname == NULL) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); ++ } ++ ++ if (!priv->tinfo_present) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); ++ } ++ ++ memcpy(tinfo_path.value, priv->tinfo_df, 2); ++ r = iso_ops->select_file(card, &tinfo_path, &file); ++ if (r != SC_SUCCESS || file->size == 0) { ++ sc_file_free(file); ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); ++ } ++ ++ /* First two bytes lists 0x01, the second indicates length */ ++ r = iso_ops->read_binary(card, 0, buf, 2, 0); ++ if (r < 2 || buf[1] > file->size) { /* make sure we do not overrun */ ++ sc_file_free(file); ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ sc_file_free(file); ++ ++ *tname = malloc(buf[1]); ++ if (*tname == NULL) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); ++ } ++ ++ r = iso_ops->read_binary(card, 2, (unsigned char *)*tname, buf[1], 0); ++ if (r < 1) { ++ free(*tname); ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ ++ if ((*tname)[r-1] != '\0') { ++ (*tname)[r-1] = '\0'; ++ } ++ LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); ++} ++ ++static int idprime_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) ++{ ++ idprime_private_data_t * priv = card->drv_data; ++ ++ LOG_FUNC_CALLED(card->ctx); ++ sc_log(card->ctx, "cmd=%ld ptr=%p", cmd, ptr); ++ ++ if (priv == NULL) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); ++ } ++ switch (cmd) { ++ case SC_CARDCTL_GET_SERIALNR: ++ return idprime_get_serial(card, (sc_serial_number_t *) ptr); ++ case SC_CARDCTL_IDPRIME_GET_TOKEN_NAME: ++ return idprime_get_token_name(card, (char **) ptr); ++ case SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS: ++ return idprime_get_init_and_get_count(&priv->pki_list, &priv->pki_current, ++ (int *)ptr); ++ case SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT: ++ return idprime_fill_prkey_info(&priv->pki_list, &priv->pki_current, ++ (sc_pkcs15_prkey_info_t *)ptr); ++ case SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS: ++ return idprime_final_iterator(&priv->pki_list); ++ } ++ ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); ++} ++ ++#define HEADER_LEN 4 ++ ++static int idprime_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out) ++{ ++ int r, len; ++ idprime_private_data_t * priv = card->drv_data; ++ u8 data[HEADER_LEN]; ++ size_t data_len = HEADER_LEN; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ /* forget any old cached values */ ++ if (priv->cache_buf) { ++ free(priv->cache_buf); ++ priv->cache_buf = NULL; ++ } ++ priv->cache_buf_len = 0; ++ priv->cached = 0; ++ ++ r = iso_ops->select_file(card, in_path, file_out); ++ if (r == SC_SUCCESS && priv && file_out != NULL) { ++ /* Try to read first bytes of the file to fix FCI in case of ++ * compressed certififcate */ ++ len = iso_ops->read_binary(card, 0, data, data_len, 0); ++ if (len == HEADER_LEN && data[0] == 0x01 && data[1] == 0x00) { ++ /* Cache the real file size for the caching read_binary() */ ++ priv->file_size = (*file_out)->size; ++ /* Fix the information in the file structure to not confuse upper layers */ ++ (*file_out)->size = (data[3]<<8) | data[2]; ++ } ++ } ++ /* Return the exit code of the select command */ ++ return r; ++} ++ ++// used to read existing certificates ++static int idprime_read_binary(sc_card_t *card, unsigned int offset, ++ unsigned char *buf, size_t count, unsigned long flags) ++{ ++ struct idprime_private_data *priv = card->drv_data; ++ int r; ++ int size; ++ ++ sc_log(card->ctx, "called; %"SC_FORMAT_LEN_SIZE_T"u bytes at offset %d", ++ count, offset); ++ ++ if (!priv->cached && offset == 0) { ++ // this function is called to read and uncompress the certificate ++ u8 buffer[SC_MAX_EXT_APDU_BUFFER_SIZE]; ++ if (sizeof(buffer) < count) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); ++ } ++ /* Read what was reported by FCI from select command */ ++ r = iso_ops->read_binary(card, 0, buffer, priv->file_size, flags); ++ if (r < 0) { ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ if (r < 4) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); ++ } ++ if (buffer[0] == 1 && buffer[1] == 0) { ++#ifdef ENABLE_ZLIB ++ size_t expectedsize = buffer[2] + buffer[3] * 0x100; ++ r = sc_decompress_alloc(&priv->cache_buf, &(priv->cache_buf_len), ++ buffer+4, priv->file_size-4, COMPRESSION_AUTO); ++ if (r != SC_SUCCESS) { ++ sc_log(card->ctx, "Zlib error: %d", r); ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ if (priv->cache_buf_len != expectedsize) { ++ sc_log(card->ctx, ++ "expected size: %"SC_FORMAT_LEN_SIZE_T"u real size: %"SC_FORMAT_LEN_SIZE_T"u", ++ expectedsize, priv->cache_buf_len); ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); ++ } ++#else ++ sc_log(card->ctx, "compression not supported, no zlib"); ++ return SC_ERROR_NOT_SUPPORTED; ++#endif /* ENABLE_ZLIB */ ++ } else { ++ /* assuming uncompressed certificate */ ++ priv->cache_buf = malloc(r); ++ if (priv->cache_buf == NULL) { ++ return SC_ERROR_OUT_OF_MEMORY; ++ } ++ memcpy(priv->cache_buf, buffer, r); ++ priv->cache_buf_len = r; ++ } ++ priv->cached = 1; ++ } ++ if (offset >= priv->cache_buf_len) { ++ return 0; ++ } ++ size = (int) MIN((priv->cache_buf_len - offset), count); ++ memcpy(buf, priv->cache_buf + offset, size); ++ return size; ++} ++ ++static int ++idprime_set_security_env(struct sc_card *card, ++ const struct sc_security_env *env, int se_num) ++{ ++ int r; ++ struct sc_security_env new_env; ++ ++ if (card == NULL || env == NULL) { ++ return SC_ERROR_INVALID_ARGUMENTS; ++ } ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ /* The card requires algorithm reference here */ ++ new_env = *env; ++ new_env.flags |= SC_SEC_ENV_ALG_REF_PRESENT; ++ /* SHA-1 mechanisms are not allowed in the card I have available */ ++ switch (env->operation) { ++ case SC_SEC_OPERATION_DECIPHER: ++ if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_OAEP) { ++ if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) { ++ new_env.algorithm_ref = 0x1D; ++ } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) { ++ new_env.algorithm_ref = 0x4D; ++ } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) { ++ new_env.algorithm_ref = 0x5D; ++ } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) { ++ new_env.algorithm_ref = 0x6D; ++ } ++ } else { /* RSA-PKCS without hashing */ ++ new_env.algorithm_ref = 0x1A; ++ } ++ break; ++ case SC_SEC_OPERATION_SIGN: ++ if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PSS) { ++ if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) { ++ new_env.algorithm_ref = 0x45; ++ } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) { ++ new_env.algorithm_ref = 0x55; ++ } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) { ++ new_env.algorithm_ref = 0x65; ++ } ++ } else { /* RSA-PKCS */ ++ if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) { ++ new_env.algorithm_ref = 0x42; ++ } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) { ++ new_env.algorithm_ref = 0x52; ++ } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) { ++ new_env.algorithm_ref = 0x62; ++ } else { /* RSA-PKCS without hashing */ ++ new_env.algorithm_ref = 0x02; ++ } ++ } ++ break; ++ default: ++ return SC_ERROR_INVALID_ARGUMENTS; ++ } ++ r = iso_ops->set_security_env(card, ++ (const struct sc_security_env *) &new_env, se_num); ++ ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ ++/* These are mostly ISO versions updated to IDPrime specifics */ ++static int ++idprime_compute_signature(struct sc_card *card, ++ const u8 * data, size_t datalen, u8 * out, size_t outlen) ++{ ++ int r; ++ struct sc_apdu apdu; ++ u8 *p; ++ u8 sbuf[128]; /* For SHA-512 we need 64 + 2 bytes */ ++ u8 rbuf[4096]; /* needs work. for 3072 keys, needs 384+2 or so */ ++ size_t rbuflen = sizeof(rbuf); ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ /* We should be signing hashes only so we should not reach this limit */ ++ if (datalen + 2 > sizeof(sbuf)) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); ++ } ++ ++ p = sbuf; ++ *(p++) = 0x90; ++ *(p++) = datalen; ++ memcpy(p, data, datalen); ++ p += datalen; ++ ++ /* INS: 0x2A PERFORM SECURITY OPERATION ++ * P1: 0x90 Hash code ++ * P2: 0xA0 Input template for the computation of a hash-code (the template is hashed) */ ++ sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x90, 0xA0); ++ apdu.resp = rbuf; ++ apdu.resplen = rbuflen; ++ apdu.le = datalen; ++ ++ apdu.data = sbuf; ++ apdu.lc = p - sbuf; ++ apdu.datalen = p - sbuf; ++ ++ r = sc_transmit_apdu(card, &apdu); ++ LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); ++ ++ /* This just returns the passed data (hash code) (for verification?) */ ++ if (apdu.resplen != datalen || memcmp(rbuf, data, datalen) != 0) { ++ sc_log(card->ctx, "The initial APDU did not return the same data"); ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); ++ } ++ /* INS: 0x2A PERFORM SECURITY OPERATION ++ * P1: 0x9E Resp: Digital Signature ++ * P2: 0x9A Cmd: Input for Digital Signature */ ++ sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x2A, 0x9E, 0x9A); ++ apdu.resp = out; ++ apdu.resplen = outlen; ++ apdu.le = outlen; ++ if (apdu.le > sc_get_max_recv_size(card)) { ++ /* The lower layers will automatically do a GET RESPONSE, if possible. ++ * All other workarounds must be carried out by the upper layers. */ ++ apdu.le = sc_get_max_recv_size(card); ++ } ++ ++ apdu.data = NULL; ++ apdu.datalen = 0; ++ apdu.lc = 0; ++ r = sc_transmit_apdu(card, &apdu); ++ LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); ++ ++ if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) ++ LOG_FUNC_RETURN(card->ctx, apdu.resplen); ++ ++ r = sc_check_sw(card, apdu.sw1, apdu.sw2); ++ LOG_TEST_RET(card->ctx, r, "Card returned error"); ++ ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ ++/* These are mostly ISO versions updated to IDPrime specifics */ ++static int ++idprime_decipher(struct sc_card *card, ++ const u8 * crgram, size_t crgram_len, ++ u8 * out, size_t outlen) ++{ ++ int r; ++ struct sc_apdu apdu; ++ u8 *sbuf = NULL; ++ ++ if (card == NULL || crgram == NULL || out == NULL) { ++ return SC_ERROR_INVALID_ARGUMENTS; ++ } ++ LOG_FUNC_CALLED(card->ctx); ++ sc_log(card->ctx, ++ "IDPrime decipher: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u", ++ crgram_len, outlen); ++ ++ sbuf = malloc(crgram_len + 1); ++ if (sbuf == NULL) ++ return SC_ERROR_OUT_OF_MEMORY; ++ ++ /* INS: 0x2A PERFORM SECURITY OPERATION ++ * P1: 0x80 Resp: Plain value ++ * P2: 0x86 Cmd: Padding indicator byte followed by cryptogram */ ++ sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86); ++ apdu.resp = out; ++ apdu.resplen = outlen; ++ apdu.le = outlen; ++ ++ sbuf[0] = 0x81; /* padding indicator byte, 0x81 = Proprietary */ ++ memcpy(sbuf + 1, crgram, crgram_len); ++ apdu.data = sbuf; ++ apdu.lc = crgram_len + 1; ++ if (apdu.lc > sc_get_max_send_size(card)) { ++ /* The lower layers will automatically do chaining */ ++ apdu.flags |= SC_APDU_FLAGS_CHAINING; ++ } ++ if (apdu.le > sc_get_max_recv_size(card)) { ++ /* The lower layers will automatically do a GET RESPONSE, if possible. ++ * All other workarounds must be carried out by the upper layers. */ ++ apdu.le = sc_get_max_recv_size(card); ++ } ++ apdu.datalen = crgram_len + 1; ++ ++ r = sc_transmit_apdu(card, &apdu); ++ sc_mem_clear(sbuf, crgram_len + 1); ++ free(sbuf); ++ LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); ++ ++ if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) ++ LOG_FUNC_RETURN(card->ctx, apdu.resplen); ++ else ++ LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); ++} ++ ++ ++static struct sc_card_driver * sc_get_driver(void) ++{ ++ if (iso_ops == NULL) { ++ iso_ops = sc_get_iso7816_driver()->ops; ++ } ++ ++ idprime_ops = *iso_ops; ++ idprime_ops.match_card = idprime_match_card; ++ idprime_ops.init = idprime_init; ++ idprime_ops.finish = idprime_finish; ++ ++ idprime_ops.read_binary = idprime_read_binary; ++ idprime_ops.select_file = idprime_select_file; ++ idprime_ops.card_ctl = idprime_card_ctl; ++ idprime_ops.set_security_env = idprime_set_security_env; ++ idprime_ops.compute_signature = idprime_compute_signature; ++ idprime_ops.decipher = idprime_decipher; ++ ++ return &idprime_drv; ++} ++ ++struct sc_card_driver * sc_get_idprime_driver(void) ++{ ++ return sc_get_driver(); ++} +diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h +index ac1969256b..7bba7e6687 100644 +--- a/src/libopensc/cardctl.h ++++ b/src/libopensc/cardctl.h +@@ -303,6 +303,16 @@ enum { + SC_CARDCTL_GIDS_INITIALIZE, + SC_CARDCTL_GIDS_SET_ADMIN_KEY, + SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, ++ ++ /* ++ * IDPrime specific calls ++ */ ++ SC_CARDCTL_IDPRIME_BASE = _CTL_PREFIX('I', 'D', 'P'), ++ SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS, ++ SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT, ++ SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, ++ SC_CARDCTL_IDPRIME_GET_TOKEN_NAME, ++ + }; + + enum { +diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h +index 24d73c094a..cb0501c3aa 100644 +--- a/src/libopensc/cards.h ++++ b/src/libopensc/cards.h +@@ -234,6 +234,7 @@ enum { + /* JPKI cards */ + SC_CARD_TYPE_JPKI_BASE = 31000, + ++ /* Coolkey cards */ + SC_CARD_TYPE_COOLKEY_BASE = 32000, + SC_CARD_TYPE_COOLKEY_GENERIC, + +@@ -258,6 +259,12 @@ enum { + SC_CARD_TYPE_RUTOKEN_ECP_SC, + SC_CARD_TYPE_RUTOKEN_LITE, + SC_CARD_TYPE_RUTOKEN_LITE_SC, ++ ++ /* IDPrime cards */ ++ SC_CARD_TYPE_IDPRIME_BASE = 37000, ++ SC_CARD_TYPE_IDPRIME_V1, ++ SC_CARD_TYPE_IDPRIME_V2, ++ SC_CARD_TYPE_IDPRIME_GENERIC, + }; + + extern sc_card_driver_t *sc_get_default_driver(void); +@@ -301,6 +308,7 @@ extern sc_card_driver_t *sc_get_cac_driver(void); + extern sc_card_driver_t *sc_get_cac1_driver(void); + extern sc_card_driver_t *sc_get_npa_driver(void); + extern sc_card_driver_t *sc_get_esteid2018_driver(void); ++extern sc_card_driver_t *sc_get_idprime_driver(void); + + #ifdef __cplusplus + } +diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c +index 40f573ed0f..4c5adc6e5f 100644 +--- a/src/libopensc/ctx.c ++++ b/src/libopensc/ctx.c +@@ -128,6 +128,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = { + { "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver }, + { "westcos", (void *(*)(void)) sc_get_westcos_driver }, + { "esteid2018", (void *(*)(void)) sc_get_esteid2018_driver }, ++ { "idprime", (void *(*)(void)) sc_get_idprime_driver }, + + /* Here should be placed drivers that need some APDU transactions in the + * driver's `match_card()` function. */ +diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h +index d8ec42174e..10bea0a013 100644 +--- a/src/libopensc/opensc.h ++++ b/src/libopensc/opensc.h +@@ -107,12 +107,13 @@ extern "C" { + * must support at least one of them, and exactly one of them must be selected + * for a given operation. */ + #define SC_ALGORITHM_RSA_RAW 0x00000001 +-#define SC_ALGORITHM_RSA_PADS 0x0000001F ++#define SC_ALGORITHM_RSA_PADS 0x0000003F + #define SC_ALGORITHM_RSA_PAD_NONE 0x00000001 + #define SC_ALGORITHM_RSA_PAD_PKCS1 0x00000002 /* PKCS#1 v1.5 padding */ + #define SC_ALGORITHM_RSA_PAD_ANSI 0x00000004 + #define SC_ALGORITHM_RSA_PAD_ISO9796 0x00000008 + #define SC_ALGORITHM_RSA_PAD_PSS 0x00000010 /* PKCS#1 v2.0 PSS */ ++#define SC_ALGORITHM_RSA_PAD_OAEP 0x00000020 /* PKCS#1 v2.0 OAEP */ + + /* If the card is willing to produce a cryptogram with the following + * hash values, set these flags accordingly. The interpretation of the hash +diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c +index 4a8fc17b9c..5bcb2bb8d9 100644 +--- a/src/libopensc/padding.c ++++ b/src/libopensc/padding.c +@@ -499,6 +499,7 @@ int sc_get_encoding_flags(sc_context_t *ctx, + /* Use the card's raw RSA capability on the padded input */ + *sflags = SC_ALGORITHM_RSA_PAD_NONE; + *pflags = iflags; ++ /* TODO emulate the OAEP decryption */ + + } else if ((caps & (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) && + (iflags & SC_ALGORITHM_RSA_PAD_PKCS1)) { +diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c +index d637dedf19..e8c13d5fea 100644 +--- a/src/libopensc/pkcs15-cac.c ++++ b/src/libopensc/pkcs15-cac.c +@@ -84,89 +84,6 @@ static const char * cac_get_name(int type) + return ("CAC"); + } + +-/* +- * These could move to a helper file for other cards that wish to use usage as a way of getting flags +- */ +- +-/* Only certain usages are valid for a given algorithm, return all the usages that the algorithm supports so we +- * can use it as a filter for all the public and private key usages */ +-static unsigned int +-cac_alg_flags_from_algorithm(int algorithm) +-{ +- switch (algorithm) { +- case SC_ALGORITHM_RSA: +- return SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP | +- SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER | +- SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP | +- SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | +- SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; +- case SC_ALGORITHM_DSA: +- return SC_PKCS15_PRKEY_USAGE_VERIFY| SC_PKCS15_PRKEY_USAGE_SIGN | +- SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; +-#ifdef SC_ALGORITHM_DH +- case SC_ALGORITHM_DH: +- return SC_PKCS15_PRKEY_USAGE_DERIVE ; +-#endif +- case SC_ALGORITHM_EC: +- return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY| +- SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; +- case SC_ALGORITHM_GOSTR3410: +- return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY| +- SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; +- } +- return 0; +-} +- +-/* These are the cert key usage bits that map to various PKCS #11 (and thus PKCS #15) flags */ +-#define CAC_X509_USAGE_SIGNATURE \ +- (SC_X509_DIGITAL_SIGNATURE | \ +- SC_X509_NON_REPUDIATION | \ +- SC_X509_KEY_CERT_SIGN | \ +- SC_X509_CRL_SIGN) +-#define CAC_X509_USAGE_DERIVE \ +- SC_X509_KEY_AGREEMENT +-#define CAC_X509_USAGE_UNWRAP \ +- (SC_X509_KEY_ENCIPHERMENT | \ +- SC_X509_KEY_AGREEMENT) +-#define CAC_X509_USAGE_DECRYPT \ +- (SC_X509_DATA_ENCIPHERMENT | \ +- SC_X509_ENCIPHER_ONLY) +-#define CAC_X509_USAGE_NONREPUDIATION \ +- SC_X509_NON_REPUDIATION +- +-/* map a cert usage and algorithm to public and private key usages */ +-static int +-cac_map_usage(unsigned int cert_usage, int algorithm, unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, int allow_nonrepudiation) +-{ +- unsigned int pub_usage = 0, pr_usage = 0; +- unsigned int alg_flags = cac_alg_flags_from_algorithm(algorithm); +- +- if (cert_usage & CAC_X509_USAGE_SIGNATURE) { +- pub_usage |= SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER; +- pr_usage |= SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER; +- } +- if (cert_usage & CAC_X509_USAGE_DERIVE) { +- pub_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; +- pr_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; +- } +- if (cert_usage & (CAC_X509_USAGE_DECRYPT|CAC_X509_USAGE_UNWRAP)) { +- pub_usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT; +- pr_usage |= SC_PKCS15_PRKEY_USAGE_DECRYPT; +- } +- if (allow_nonrepudiation && (cert_usage & CAC_X509_USAGE_NONREPUDIATION)) { +- pub_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; +- pr_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; +- } +- /* filter usages algorithm */ +- if (pub_usage_ptr) { +- *pub_usage_ptr = pub_usage & alg_flags; +- } +- if (pr_usage_ptr) { +- *pr_usage_ptr = pr_usage & alg_flags; +- } +- return SC_SUCCESS; +-} +- + static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) + { + static const pindata pins[] = { +@@ -407,9 +324,9 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) + + r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL); + if (r < 0) { +- usage = 0xd9ULL; /* basic default usage */ ++ usage = SC_X509_DATA_ENCIPHERMENT|SC_X509_DIGITAL_SIGNATURE; /* basic default usage */ + } +- cac_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); ++ sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); + sc_log(card->ctx, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n", + sc_dump_hex(cert_info.id.value, cert_info.id.len), + usage, pubkey_info.usage, prkey_info.usage); +diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c +index 8606d14af0..7850fad8d8 100644 +--- a/src/libopensc/pkcs15-cert.c ++++ b/src/libopensc/pkcs15-cert.c +@@ -257,6 +257,8 @@ sc_pkcs15_get_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert, + { NULL, 0, 0, 0, NULL, NULL } + }; + ++ LOG_FUNC_CALLED(ctx); ++ + for (next_ext = cert->extensions, next_ext_len = cert->extensions_len; next_ext_len; ) { + /* unwrap the set and point to the next ava */ + ext = sc_asn1_skip_tag(ctx, &next_ext, &next_ext_len, +@@ -324,6 +326,8 @@ sc_pkcs15_get_bitstring_extension(struct sc_context *ctx, + { NULL, 0, 0, 0, NULL, NULL } + }; + ++ LOG_FUNC_CALLED(ctx); ++ + r = sc_pkcs15_get_extension(ctx, cert, type, &bit_string, &bit_string_len, is_critical); + LOG_TEST_RET(ctx, r, "Get extension error"); + +@@ -550,6 +554,88 @@ sc_pkcs15_encode_cdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj + return r; + } + ++/* Only certain usages are valid for a given algorithm, return all the usages ++ * that the algorithm supports so we can use it as a filter for all ++ * the public and private key usages ++ */ ++static unsigned int ++sc_pkcs15_alg_flags_from_algorithm(int algorithm) ++{ ++ switch (algorithm) { ++ case SC_ALGORITHM_RSA: ++ return SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP | ++ SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER | ++ SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP | ++ SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | ++ SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; ++ case SC_ALGORITHM_DSA: ++ return SC_PKCS15_PRKEY_USAGE_VERIFY| SC_PKCS15_PRKEY_USAGE_SIGN | ++ SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; ++#ifdef SC_ALGORITHM_DH ++ case SC_ALGORITHM_DH: ++ return SC_PKCS15_PRKEY_USAGE_DERIVE ; ++#endif ++ case SC_ALGORITHM_EC: ++ return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY| ++ SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; ++ case SC_ALGORITHM_GOSTR3410: ++ return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY| ++ SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; ++ } ++ return 0; ++} ++ ++/* These are the cert key usage bits that map to various PKCS #11 (and thus PKCS #15) flags */ ++#define SC_PKCS15_X509_USAGE_SIGNATURE \ ++ (SC_X509_DIGITAL_SIGNATURE | \ ++ SC_X509_NON_REPUDIATION | \ ++ SC_X509_KEY_CERT_SIGN | \ ++ SC_X509_CRL_SIGN) ++#define SC_PKCS15_X509_USAGE_DERIVE \ ++ SC_X509_KEY_AGREEMENT ++#define SC_PKCS15_X509_USAGE_UNWRAP \ ++ (SC_X509_KEY_ENCIPHERMENT | \ ++ SC_X509_KEY_AGREEMENT) ++#define SC_PKCS15_X509_USAGE_DECRYPT \ ++ (SC_X509_DATA_ENCIPHERMENT | \ ++ SC_X509_ENCIPHER_ONLY) ++#define SC_PKCS15_X509_USAGE_NONREPUDIATION \ ++ SC_X509_NON_REPUDIATION ++ ++/* map a cert usage and algorithm to public and private key usages */ ++int ++sc_pkcs15_map_usage(unsigned int cert_usage, int algorithm, ++ unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, ++ int allow_nonrepudiation) ++{ ++ unsigned int pub_usage = 0, pr_usage = 0; ++ unsigned int alg_flags = sc_pkcs15_alg_flags_from_algorithm(algorithm); ++ ++ if (cert_usage & SC_PKCS15_X509_USAGE_SIGNATURE) { ++ pub_usage |= SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER; ++ pr_usage |= SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER; ++ } ++ if (cert_usage & SC_PKCS15_X509_USAGE_DERIVE) { ++ pub_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; ++ pr_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; ++ } ++ if (cert_usage & (SC_PKCS15_X509_USAGE_DECRYPT|SC_PKCS15_X509_USAGE_UNWRAP)) { ++ pub_usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT; ++ pr_usage |= SC_PKCS15_PRKEY_USAGE_DECRYPT; ++ } ++ if (allow_nonrepudiation && (cert_usage & SC_PKCS15_X509_USAGE_NONREPUDIATION)) { ++ pub_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; ++ pr_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; ++ } ++ /* filter usages algorithm */ ++ if (pub_usage_ptr) { ++ *pub_usage_ptr = pub_usage & alg_flags; ++ } ++ if (pr_usage_ptr) { ++ *pr_usage_ptr = pr_usage & alg_flags; ++ } ++ return SC_SUCCESS; ++} + + void + sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert) +diff --git a/src/libopensc/pkcs15-idprime.c b/src/libopensc/pkcs15-idprime.c +new file mode 100644 +index 0000000000..d882696997 +--- /dev/null ++++ b/src/libopensc/pkcs15-idprime.c +@@ -0,0 +1,286 @@ ++/* ++ * partial PKCS15 emulation for IDPrime cards. ++ * ++ * We can not use the ISO code, since the EF.DIR and EF.ATR for ++ * object discovery are missing ++ * ++ * Copyright (C) 2019, 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 "internal.h" ++#include "cardctl.h" ++#include "pkcs15.h" ++ ++#define CERT_LABEL_TEMPLATE "Certificate %d" ++#define PUBKEY_LABEL_TEMPLATE "Public key %d" ++#define PRIVKEY_LABEL_TEMPLATE "Private key %d" ++ ++static int idprime_detect_card(sc_pkcs15_card_t *p15card) ++{ ++ sc_card_t *card = p15card->card; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ if (card->type < SC_CARD_TYPE_IDPRIME_BASE ++ || card->type >= SC_CARD_TYPE_IDPRIME_BASE+1000) ++ return SC_ERROR_INVALID_CARD; ++ return SC_SUCCESS; ++} ++ ++static int sc_pkcs15emu_idprime_init(sc_pkcs15_card_t *p15card) ++{ ++ int r, i; ++ sc_card_t *card = p15card->card; ++ sc_serial_number_t serial; ++ char buf[SC_MAX_SERIALNR * 2 + 1]; ++ int count; ++ char *token_name = NULL; ++ struct sc_pkcs15_auth_info pin_info; ++ struct sc_pkcs15_object pin_obj; ++ const char pin_label[] = "PIN"; ++ const char *pin_id = "11"; ++ ++ /* oid for key usage */ ++ static const struct sc_object_id usage_type = {{ 2, 5, 29, 15, -1 }}; ++ unsigned int usage; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ /* could read this off card if needed */ ++ p15card->tokeninfo->label = strdup("IDPrime"); ++ p15card->tokeninfo->manufacturer_id = strdup("Gemalto"); ++ ++ /* ++ * get serial number ++ */ ++ memset(&serial, 0, sizeof(serial)); ++ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); ++ if (r < 0) { ++ sc_log(card->ctx, "sc_card_ctl rc=%d", r); ++ p15card->tokeninfo->serial_number = strdup("00000000"); ++ } else { ++ sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); ++ p15card->tokeninfo->serial_number = strdup(buf); ++ } ++ /* set pin */ ++ sc_log(card->ctx, "IDPrime adding pin..."); ++ memset(&pin_info, 0, sizeof(pin_info)); ++ memset(&pin_obj, 0, sizeof(pin_obj)); ++ ++ pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; ++ sc_pkcs15_format_id(pin_id, &pin_info.auth_id); ++ pin_info.attrs.pin.reference = 0x11; ++ pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_INITIALIZED; ++ pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; ++ pin_info.attrs.pin.min_length = 4; ++ pin_info.attrs.pin.stored_length = 0; ++ pin_info.attrs.pin.max_length = 16; ++ pin_info.tries_left = -1; ++ ++ sc_log(card->ctx, "IDPrime Adding pin with label=%s", pin_label); ++ strncpy(pin_obj.label, pin_label, SC_PKCS15_MAX_LABEL_SIZE - 1); ++ pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; ++ ++ r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); ++ if (r < 0) ++ LOG_FUNC_RETURN(card->ctx, r); ++ ++ /* ++ * get token name if provided ++ */ ++ r = sc_card_ctl(card, SC_CARDCTL_IDPRIME_GET_TOKEN_NAME, &token_name); ++ if (r < 0) { ++ /* On failure we will get the token name from certificates later */ ++ sc_log(card->ctx, "sc_card_ctl rc=%d", r); ++ } else { ++ free(p15card->tokeninfo->label); ++ p15card->tokeninfo->label = token_name; ++ sc_log(card->ctx, "IDPrime setting token label = %s", token_name); ++ } ++ /* ++ * certs, pubkeys and priv keys are related and we assume ++ * they are in order ++ * We need to read the cert, get modulus and keylen ++ * We use those for the pubkey, and priv key objects. ++ */ ++ sc_log(card->ctx, "IDPrime adding certs, pub and priv keys..."); ++ r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS, &count); ++ LOG_TEST_RET(card->ctx, r, "Can not initiate cert objects."); ++ ++ for (i = 0; i < count; i++) { ++ struct sc_pkcs15_prkey_info prkey_info; ++ struct sc_pkcs15_cert_info cert_info; ++ struct sc_pkcs15_pubkey_info pubkey_info; ++ struct sc_pkcs15_object cert_obj; ++ struct sc_pkcs15_object pubkey_obj; ++ struct sc_pkcs15_object prkey_obj; ++ sc_pkcs15_der_t cert_der; ++ sc_pkcs15_cert_t *cert_out = NULL; ++ ++ r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT, &prkey_info); ++ LOG_TEST_RET(card->ctx, r, "Can not get next object"); ++ ++ memset(&cert_info, 0, sizeof(cert_info)); ++ memset(&pubkey_info, 0, sizeof(pubkey_info)); ++ /* prkey_info cleaned by the card_ctl call */ ++ memset(&cert_obj, 0, sizeof(cert_obj)); ++ memset(&pubkey_obj, 0, sizeof(pubkey_obj)); ++ memset(&prkey_obj, 0, sizeof(prkey_obj)); ++ ++ cert_info.id = prkey_info.id; ++ pubkey_info.id = prkey_info.id; ++ cert_info.path = prkey_info.path; ++ /* For private keys, we no longer care for the path, just ++ * the key reference later used in the security environment */ ++ prkey_info.path.len = 0; ++ prkey_info.path.aid.len = 0; ++ pubkey_info.key_reference = prkey_info.key_reference; ++ sc_log(card->ctx, "Key ref r=%x", prkey_info.key_reference); ++ ++ pubkey_info.native = 1; ++ prkey_info.native = 1; ++ ++ snprintf(cert_obj.label, SC_PKCS15_MAX_LABEL_SIZE, CERT_LABEL_TEMPLATE, i+1); ++ snprintf(pubkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, PUBKEY_LABEL_TEMPLATE, i+1); ++ snprintf(prkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, PRIVKEY_LABEL_TEMPLATE, i+1); ++ prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; ++ sc_pkcs15_format_id(pin_id, &prkey_obj.auth_id); ++ ++ r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len); ++ ++ if (r) { ++ sc_log(card->ctx, "No cert found,i=%d", i); ++ continue; ++ } ++ cert_info.path.count = cert_der.len; ++ ++ sc_log(card->ctx, ++ "cert len=%"SC_FORMAT_LEN_SIZE_T"u, cert_info.path.count=%d r=%d\n", ++ cert_der.len, cert_info.path.count, r); ++ sc_log_hex(card->ctx, "cert", cert_der.value, cert_der.len); ++ ++ /* cache it using the PKCS15 emulation objects */ ++ /* as it does not change */ ++ if (cert_der.value) { ++ cert_info.value.value = cert_der.value; ++ cert_info.value.len = cert_der.len; ++ cert_info.path.len = 0; /* use in mem cert from now on */ ++ } ++ ++ /* following will find the cached cert in cert_info */ ++ r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); ++ if (r < 0 || cert_out->key == NULL) { ++ sc_log(card->ctx, "Failed to read/parse the certificate r=%d",r); ++ if (cert_out != NULL) ++ sc_pkcs15_free_certificate(cert_out); ++ free(cert_der.value); ++ continue; ++ } ++ ++ r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); ++ if (r < 0) { ++ sc_log(card->ctx, " Failed to add cert obj r=%d",r); ++ sc_pkcs15_free_certificate(cert_out); ++ free(cert_der.value); ++ 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) { ++ free(cn_name); ++ r = SC_ERROR_OUT_OF_MEMORY; ++ goto fail; ++ } ++ memcpy(token_name, cn_name, cn_len); ++ free(cn_name); ++ token_name[cn_len] = '\0'; ++ free(p15card->tokeninfo->label); ++ p15card->tokeninfo->label = token_name; ++ } ++ } ++ ++ ++ r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, cert_out->key, ++ &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len); ++ if (r < 0) ++ goto fail; ++ pubkey_obj.emulated = cert_out->key; ++ ++ r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL); ++ if (r < 0) { ++ usage = SC_X509_DATA_ENCIPHERMENT|SC_X509_DIGITAL_SIGNATURE; /* basic default usage */ ++ } ++ sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); ++ sc_log(card->ctx, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n", ++ sc_dump_hex(cert_info.id.value, cert_info.id.len), ++ usage, pubkey_info.usage, prkey_info.usage); ++ if (cert_out->key->algorithm != SC_ALGORITHM_RSA) { ++ sc_log(card->ctx, "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; ++ prkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; ++ sc_log(card->ctx, "adding rsa public key r=%d usage=%x",r, pubkey_info.usage); ++ r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); ++ if (r < 0) ++ goto fail; ++ sc_log(card->ctx, "adding rsa private key r=%d usage=%x",r, prkey_info.usage); ++ r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); ++ if (r < 0) ++ goto fail; ++ } ++ ++ cert_out->key = NULL; ++fail: ++ sc_pkcs15_free_certificate(cert_out); ++ if (r < 0) ++ LOG_FUNC_RETURN(card->ctx, r); /* should not fail */ ++ ++ } ++ r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, &count); ++ LOG_TEST_RET(card->ctx, r, "Can not finalize cert objects."); ++ ++ LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); ++} ++ ++int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, ++ struct sc_aid *aid) ++{ ++ sc_card_t *card = p15card->card; ++ sc_context_t *ctx = card->ctx; ++ ++ LOG_FUNC_CALLED(ctx); ++ ++ if (idprime_detect_card(p15card)) ++ return SC_ERROR_WRONG_CARD; ++ return sc_pkcs15emu_idprime_init(p15card); ++} +diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c +index facb0a607c..279a001e9d 100644 +--- a/src/libopensc/pkcs15-syn.c ++++ b/src/libopensc/pkcs15-syn.c +@@ -43,22 +43,23 @@ struct sc_pkcs15_emulator_handler builtin_emulators[] = { + { "itacns", sc_pkcs15emu_itacns_init_ex }, + { "PIV-II", sc_pkcs15emu_piv_init_ex }, + { "cac", sc_pkcs15emu_cac_init_ex }, ++ { "idprime", sc_pkcs15emu_idprime_init_ex }, + { "gemsafeGPK", sc_pkcs15emu_gemsafeGPK_init_ex }, + { "gemsafeV1", sc_pkcs15emu_gemsafeV1_init_ex }, + { "actalis", sc_pkcs15emu_actalis_init_ex }, + { "atrust-acos",sc_pkcs15emu_atrust_acos_init_ex}, + { "tccardos", sc_pkcs15emu_tccardos_init_ex }, +- { "entersafe", sc_pkcs15emu_entersafe_init_ex }, ++ { "entersafe", sc_pkcs15emu_entersafe_init_ex }, + { "pteid", sc_pkcs15emu_pteid_init_ex }, + { "oberthur", sc_pkcs15emu_oberthur_init_ex }, + { "sc-hsm", sc_pkcs15emu_sc_hsm_init_ex }, +- { "dnie", sc_pkcs15emu_dnie_init_ex }, +- { "gids", sc_pkcs15emu_gids_init_ex }, +- { "iasecc", sc_pkcs15emu_iasecc_init_ex }, +- { "jpki", sc_pkcs15emu_jpki_init_ex }, ++ { "dnie", sc_pkcs15emu_dnie_init_ex }, ++ { "gids", sc_pkcs15emu_gids_init_ex }, ++ { "iasecc", sc_pkcs15emu_iasecc_init_ex }, ++ { "jpki", sc_pkcs15emu_jpki_init_ex }, + { "coolkey", sc_pkcs15emu_coolkey_init_ex }, +- { "din66291", sc_pkcs15emu_din_66291_init_ex }, +- { "esteid2018", sc_pkcs15emu_esteid2018_init_ex }, ++ { "din66291", sc_pkcs15emu_din_66291_init_ex }, ++ { "esteid2018", sc_pkcs15emu_esteid2018_init_ex }, + + { NULL, NULL } + }; +diff --git a/src/libopensc/pkcs15-syn.h b/src/libopensc/pkcs15-syn.h +index 6811b3dab1..ccaf693ca4 100644 +--- a/src/libopensc/pkcs15-syn.h ++++ b/src/libopensc/pkcs15-syn.h +@@ -53,6 +53,7 @@ int sc_pkcs15emu_iasecc_init_ex(sc_pkcs15_card_t *, struct sc_aid *); + int sc_pkcs15emu_jpki_init_ex(sc_pkcs15_card_t *, struct sc_aid *); + int sc_pkcs15emu_coolkey_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); + int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); ++int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); + + struct sc_pkcs15_emulator_handler { + const char *name; +diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h +index f2ccc42aed..df1435ce92 100644 +--- a/src/libopensc/pkcs15.h ++++ b/src/libopensc/pkcs15.h +@@ -754,6 +754,9 @@ int sc_pkcs15_get_name_from_dn(struct sc_context *ctx, + const u8 *dn, size_t dn_len, + const struct sc_object_id *type, + u8 **name, size_t *name_len); ++int sc_pkcs15_map_usage(unsigned int cert_usage, int algorithm, ++ unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, ++ int allow_nonrepudiation); + int sc_pkcs15_get_extension(struct sc_context *ctx, + struct sc_pkcs15_cert *cert, + const struct sc_object_id *type, +diff --git a/src/libopensc/simpletlv.h b/src/libopensc/simpletlv.h +index a952779733..6bcd4f0856 100644 +--- a/src/libopensc/simpletlv.h ++++ b/src/libopensc/simpletlv.h +@@ -29,7 +29,6 @@ extern "C" { + #endif + + #include "libopensc/opensc.h" +-#include "libopensc/pkcs15.h" + + /* + * Create a tag/length file in Simple TLV based on the val_len content length +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index 22081ffef1..e94eeeffec 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -3976,7 +3976,7 @@ pkcs15_prkey_sign(struct sc_pkcs11_session *session, void *obj, + /* Check the data length matches the selected hash */ + rv = pkcs15_prkey_check_pss_param(pMechanism, (int)ulDataLen); + if (rv != CKR_OK) { +- sc_log(context, "Invalid data lenght for the selected " ++ sc_log(context, "Invalid data length for the selected " + "PSS parameters"); + return rv; + } +@@ -4179,6 +4179,39 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj, + case CKM_RSA_X_509: + flags |= SC_ALGORITHM_RSA_RAW; + break; ++ case CKM_RSA_PKCS_OAEP: ++ flags |= SC_ALGORITHM_RSA_PAD_OAEP; ++ ++ /* Omited parameter can use MGF1-SHA1 and SHA1 hash ? */ ++ if (pMechanism->pParameter == NULL) { ++ flags |= SC_ALGORITHM_RSA_HASH_SHA1; ++ flags |= SC_ALGORITHM_MGF1_SHA1; ++ break; ++ } ++ ++ switch (((CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter)->hashAlg) { ++ case CKM_SHA_1: ++ flags |= SC_ALGORITHM_RSA_HASH_SHA1; ++ break; ++ case CKM_SHA224: ++ flags |= SC_ALGORITHM_RSA_HASH_SHA224; ++ break; ++ case CKM_SHA256: ++ flags |= SC_ALGORITHM_RSA_HASH_SHA256; ++ break; ++ case CKM_SHA384: ++ flags |= SC_ALGORITHM_RSA_HASH_SHA384; ++ break; ++ case CKM_SHA512: ++ flags |= SC_ALGORITHM_RSA_HASH_SHA512; ++ break; ++ default: ++ return CKR_MECHANISM_PARAM_INVALID; ++ } ++ ++ /* The MGF parameter was already verified in SignInit() */ ++ flags |= mgf2flags(((CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter)->mgf); ++ break; + default: + return CKR_MECHANISM_INVALID; + } +@@ -4352,6 +4385,7 @@ pkcs15_prkey_init_params(struct sc_pkcs11_session *session, + const unsigned int salt_lens[5] = { 160, 256, 384, 512, 224 }; + const unsigned int hashes[5] = { CKM_SHA_1, CKM_SHA256, + CKM_SHA384, CKM_SHA512, CKM_SHA224 }; ++ const CK_RSA_PKCS_OAEP_PARAMS *oaep_params; + + switch (pMechanism->mechanism) { + case CKM_RSA_PKCS_PSS: +@@ -4407,6 +4441,26 @@ pkcs15_prkey_init_params(struct sc_pkcs11_session *session, + + /* TODO support different salt lengths */ + break; ++ case CKM_RSA_PKCS_OAEP: ++ if (!pMechanism->pParameter || ++ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) ++ return CKR_MECHANISM_PARAM_INVALID; ++ ++ oaep_params = (CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter; ++ switch (oaep_params->mgf) { ++ case CKG_MGF1_SHA1: ++ case CKG_MGF1_SHA224: ++ case CKG_MGF1_SHA256: ++ case CKG_MGF1_SHA384: ++ case CKG_MGF1_SHA512: ++ /* OK */ ++ break; ++ default: ++ return CKR_MECHANISM_PARAM_INVALID; ++ } ++ /* TODO support different salt lengths */ ++ /* TODO is there something more to check */ ++ break; + } + return CKR_OK; + } +@@ -5619,6 +5673,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) + rsa_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; + #ifdef ENABLE_OPENSSL + rsa_flags |= SC_ALGORITHM_RSA_PAD_PSS; ++ /* TODO support OAEP decryption & encryption using OpenSSL */ + #endif + } + +@@ -5699,6 +5754,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) + } + + if (rsa_flags & SC_ALGORITHM_RSA_PAD_PSS) { ++ CK_FLAGS old_flags = mech_info.flags; + mech_info.flags &= ~(CKF_DECRYPT|CKF_ENCRYPT); + mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_PSS, &mech_info, CKK_RSA, NULL, NULL); + rc = sc_pkcs11_register_mechanism(p11card, mt); +@@ -5735,6 +5791,18 @@ register_mechanisms(struct sc_pkcs11_card *p11card) + if (rc != CKR_OK) + return rc; + } ++ mech_info.flags = old_flags; ++ } ++ ++ if (rsa_flags & SC_ALGORITHM_RSA_PAD_OAEP) { ++ CK_FLAGS old_flags = mech_info.flags; ++ mech_info.flags &= ~(CKF_SIGN|CKF_VERIFY|CKF_SIGN_RECOVER|CKF_VERIFY_RECOVER); ++ mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_OAEP, &mech_info, CKK_RSA, NULL, NULL); ++ rc = sc_pkcs11_register_mechanism(p11card, mt); ++ if (rc != CKR_OK) { ++ return rc; ++ } ++ mech_info.flags = old_flags; + } + + if (rsa_flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { +diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c +index 358cad40fd..983d8dcbdf 100644 +--- a/src/pkcs11/mechanism.c ++++ b/src/pkcs11/mechanism.c +@@ -811,6 +811,15 @@ sc_pkcs11_decr_init(struct sc_pkcs11_session *session, + } + rv = mt->decrypt_init(operation, key); + ++ /* Validate the mechanism parameters */ ++ if (key->ops->init_params) { ++ rv = key->ops->init_params(operation->session, &operation->mechanism); ++ if (rv != CKR_OK) { ++ /* Probably bad arguments */ ++ LOG_FUNC_RETURN(context, (int) rv); ++ } ++ } ++ + if (rv != CKR_OK) + session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT); + +diff --git a/src/tests/p11test/p11test_case_common.c b/src/tests/p11test/p11test_case_common.c +index bd4b39af74..22e639cf49 100644 +--- a/src/tests/p11test/p11test_case_common.c ++++ b/src/tests/p11test/p11test_case_common.c +@@ -422,7 +422,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + CK_OBJECT_HANDLE object_handle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE_PTR object_handles = NULL; + unsigned long i = 0, objects_length = 0; +- int j; ++ int j, ret = -1; + + /* FindObjects first + * https://wiki.oasis-open.org/pkcs11/CommonBugs +@@ -439,16 +439,18 @@ int search_objects(test_certs_t *objects, token_info_t *info, + break; + if (rv != CKR_OK) { + fprintf(stderr, "C_FindObjects: rv = 0x%.8lX\n", rv); +- return -1; ++ goto out; + } + /* store handle */ + if (i >= objects_length) { ++ CK_OBJECT_HANDLE_PTR new_object_handles = NULL; + objects_length += 4; // do not realloc after each row +- object_handles = realloc(object_handles, objects_length * sizeof(CK_OBJECT_HANDLE)); +- if (object_handles == NULL) { ++ new_object_handles = realloc(object_handles, objects_length * sizeof(CK_OBJECT_HANDLE)); ++ if (new_object_handles == NULL) { + fail_msg("Realloc failed. Need to store object handles.\n"); +- return -1; ++ goto out; + } ++ object_handles = new_object_handles; + } + object_handles[i++] = object_handle; + } +@@ -458,8 +460,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + if (rv != CKR_OK) { + fprintf(stderr, "C_FindObjectsFinal: rv = 0x%.8lX\n", rv); + fail_msg("Could not find certificate.\n"); +- free(object_handles); +- return -1; ++ goto out; + } + + for (i = 0; i < objects_length; i++) { +@@ -476,8 +477,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + continue; + } else if (rv != CKR_OK) { + fail_msg("C_GetAttributeValue: rv = 0x%.8lX\n", rv); +- free(object_handles); +- return -1; ++ goto out; + } + + /* Allocate memory to hold the data we want */ +@@ -487,8 +487,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + template[j].pValue = malloc(template[j].ulValueLen); + if (template[j].pValue == NULL) { + fail_msg("malloc failed"); +- free(object_handles); +- return -1; ++ goto out; + } + } + /* Call again to get actual attribute */ +@@ -496,8 +495,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, + &(template[j]), 1); + if (rv != CKR_OK) { + fail_msg("C_GetAttributeValue: rv = 0x%.8lX\n", rv); +- free(object_handles); +- return -1; ++ goto out; + } + } + +@@ -506,8 +504,10 @@ int search_objects(test_certs_t *objects, token_info_t *info, + for (j = 0; j < template_size; j++) + free(template[j].pValue); + } ++ ret = 0; ++out: + free(object_handles); +- return 0; ++ return ret; + } + + void search_for_all_objects(test_certs_t *objects, token_info_t *info) +diff --git a/src/tools/opensc-tool.c b/src/tools/opensc-tool.c +index f829332fd8..52b570d9bf 100644 +--- a/src/tools/opensc-tool.c ++++ b/src/tools/opensc-tool.c +@@ -594,6 +594,7 @@ static int list_algorithms(void) + { SC_ALGORITHM_RSA_PAD_PKCS1, "pkcs1" }, + { SC_ALGORITHM_RSA_PAD_ANSI, "ansi" }, + { SC_ALGORITHM_RSA_PAD_PSS, "pss" }, ++ { SC_ALGORITHM_RSA_PAD_OAEP, "oaep" }, + { SC_ALGORITHM_RSA_PAD_ISO9796, "iso9796" }, + { SC_ALGORITHM_RSA_HASH_SHA1, "sha1" }, + { SC_ALGORITHM_RSA_HASH_MD5, "MD5" }, +diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c +index 92c8d8a506..6a8e27ee69 100644 +--- a/src/tools/pkcs11-tool.c ++++ b/src/tools/pkcs11-tool.c +@@ -2127,9 +2127,15 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, + case CKM_RSA_PKCS_OAEP: + oaep_params.hashAlg = opt_hash_alg; + switch (opt_hash_alg) { ++ case CKM_SHA_1: ++ oaep_params.mgf = CKG_MGF1_SHA1; ++ break; + case CKM_SHA224: + oaep_params.mgf = CKG_MGF1_SHA224; + break; ++ default: ++ oaep_params.hashAlg = CKM_SHA256; ++ /* fall through */ + case CKM_SHA256: + oaep_params.mgf = CKG_MGF1_SHA256; + break; +@@ -2139,12 +2145,6 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, + case CKM_SHA512: + oaep_params.mgf = CKG_MGF1_SHA512; + break; +- default: +- oaep_params.hashAlg = CKM_SHA_1; +- /* fall through */ +- case CKM_SHA_1: +- oaep_params.mgf = CKG_MGF1_SHA1; +- break; + } + break; + case CKM_RSA_X_509: diff --git a/opensc-0.19.0-pinpad.patch b/opensc-0.19.0-pinpad.patch new file mode 100644 index 0000000..f531b8b --- /dev/null +++ b/opensc-0.19.0-pinpad.patch @@ -0,0 +1,13 @@ +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 2018-10-22 14:31:12.082963540 +0200 ++++ opensc-0.19.0/etc/opensc.conf 2018-10-22 14:33:59.939410701 +0200 +@@ -4,4 +4,9 @@ app default { + framework pkcs15 { + # use_file_caching = true; + } ++ reader_driver pcsc { ++ # The pinpad is disabled by default, ++ # because of many broken readers out there ++ enable_pinpad = false; ++ } + } diff --git a/opensc-0.20.0-CVE-2020-26570.patch b/opensc-0.20.0-CVE-2020-26570.patch new file mode 100644 index 0000000..ad0320b --- /dev/null +++ b/opensc-0.20.0-CVE-2020-26570.patch @@ -0,0 +1,31 @@ +commit 6903aebfddc466d966c7b865fae34572bf3ed23e +Author: Frank Morgner +Date: Thu Jul 30 02:21:17 2020 +0200 + + Heap-buffer-overflow WRITE + + fixes https://oss-fuzz.com/testcase-detail/5088104168554496 + +diff --git a/src/libopensc/pkcs15-oberthur.c b/src/libopensc/pkcs15-oberthur.c +index a873aaa0..2fb32b8d 100644 +--- a/src/libopensc/pkcs15-oberthur.c ++++ b/src/libopensc/pkcs15-oberthur.c +@@ -271,11 +271,15 @@ sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path, + rv = sc_read_binary(card, 0, *out, sz, 0); + } + else { +- int rec; +- int offs = 0; +- int rec_len = file->record_length; ++ size_t rec; ++ size_t offs = 0; ++ size_t rec_len = file->record_length; + + for (rec = 1; ; rec++) { ++ if (rec > file->record_count) { ++ rv = 0; ++ break; ++ } + rv = sc_read_record(card, rec, *out + offs + 2, rec_len, SC_RECORD_BY_REC_NR); + if (rv == SC_ERROR_RECORD_NOT_FOUND) { + rv = 0; diff --git a/opensc-0.20.0-CVE-2020-26571.patch b/opensc-0.20.0-CVE-2020-26571.patch new file mode 100644 index 0000000..b07ac05 --- /dev/null +++ b/opensc-0.20.0-CVE-2020-26571.patch @@ -0,0 +1,42 @@ +commit ed55fcd2996930bf58b9bb57e9ba7b1f3a753c43 +Author: Frank Morgner +Date: Mon May 18 17:25:32 2020 +0200 + + fixed invalid read + + fixes https://oss-fuzz.com/testcase-detail/5765246676631552 + +diff --git a/src/libopensc/pkcs15-gemsafeGPK.c b/src/libopensc/pkcs15-gemsafeGPK.c +index e13f3b87..4b80daf2 100644 +--- a/src/libopensc/pkcs15-gemsafeGPK.c ++++ b/src/libopensc/pkcs15-gemsafeGPK.c +@@ -205,7 +205,7 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card) + + u8 sysrec[7]; + int num_keyinfo = 0; +- keyinfo kinfo[8]; /* will loook for 8 keys */ ++ keyinfo kinfo[9]; /* will look for 9 keys */ + u8 modulus_buf[ 1 + 1024 / 8]; /* tag+modulus */ + u8 *cp; + char buf[256]; +@@ -255,9 +255,9 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card) + + /* There may be more then one key in the directory. */ + /* we need to find them so we can associate them with the */ +- /* the certificate. The files are 0007 to 000f */ ++ /* the certificate. The files are 0007 to 000F */ + +- for (i = 7; i < 16; i++) { ++ for (i = 0x7; i <= 0xF; i++) { + path.value[0] = 0x00; + path.value[1] = i; + path.len = 2; +@@ -297,7 +297,7 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card) + while (j--) + *cp++ = modulus_buf[j + 1]; + num_keyinfo++; +- } ++ } + + /* Get the gemsafe data with the cert */ + sc_format_path("3F000200004", &path); diff --git a/opensc-0.20.0-CVE-2020-26572.patch b/opensc-0.20.0-CVE-2020-26572.patch new file mode 100644 index 0000000..91a1249 --- /dev/null +++ b/opensc-0.20.0-CVE-2020-26572.patch @@ -0,0 +1,21 @@ +commit 9d294de90d1cc66956389856e60b6944b27b4817 +Author: Frank Morgner +Date: Thu Jun 4 10:04:10 2020 +0200 + + prevent out of bounds write + + fixes https://oss-fuzz.com/testcase-detail/5226571123392512 + +diff --git a/src/libopensc/card-tcos.c b/src/libopensc/card-tcos.c +index 673c2493..e88c80bd 100644 +--- a/src/libopensc/card-tcos.c ++++ b/src/libopensc/card-tcos.c +@@ -623,6 +623,8 @@ static int tcos_decipher(sc_card_t *card, const u8 * crgram, size_t crgram_len, + apdu.data = sbuf; + apdu.lc = apdu.datalen = crgram_len+1; + sbuf[0] = tcos3 ? 0x00 : ((data->pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) ? 0x81 : 0x02); ++ if (sizeof sbuf - 1 < crgram_len) ++ return SC_ERROR_INVALID_ARGUMENTS; + memcpy(sbuf+1, crgram, crgram_len); + + r = sc_transmit_apdu(card, &apdu); diff --git a/opensc-0.20.0-cac-pin-change.patch b/opensc-0.20.0-cac-pin-change.patch new file mode 100644 index 0000000..3163caf --- /dev/null +++ b/opensc-0.20.0-cac-pin-change.patch @@ -0,0 +1,102 @@ +diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c +index 099923e5..61e69c88 100644 +--- a/src/libopensc/card-cac.c ++++ b/src/libopensc/card-cac.c +@@ -1793,7 +1793,7 @@ static int cac_find_and_initialize(sc_card_t *card, int initialize) + } + r = cac_process_ACA(card, priv); + if (r == SC_SUCCESS) { +- card->type = SC_CARD_TYPE_CAC_II; ++ card->type = SC_CARD_TYPE_CAC_ALT_HID; + card->drv_data = priv; + return r; + } +@@ -1869,6 +1869,8 @@ static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries + * FIPS 201 4.1.6.1 (numeric only) and * FIPS 140-2 + * (6 character minimum) requirements. + */ ++ sc_apdu_t apdu; ++ u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); + + if (data->cmd == SC_PIN_CMD_CHANGE) { +@@ -1881,6 +1883,18 @@ static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries + return SC_ERROR_INVALID_DATA; + } + } ++ ++ /* We can change the PIN of Giesecke & Devrient CAC ALT tokens ++ * with a bit non-standard APDU */ ++ if (card->type == SC_CARD_TYPE_CAC_ALT_HID) { ++ int r = 0; ++ r = iso7816_build_pin_apdu(card, &apdu, data, sbuf, sizeof(sbuf)); ++ if (r < 0) ++ return r; ++ /* it requires P1 = 0x01 completely against the ISO specs */ ++ apdu.p1 = 0x01; ++ data->apdu = &apdu; ++ } + } + + return iso_drv->ops->pin_cmd(card, data, tries_left); +diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h +index 0ec25a46..16846d15 100644 +--- a/src/libopensc/cards.h ++++ b/src/libopensc/cards.h +@@ -244,6 +244,7 @@ enum { + SC_CARD_TYPE_CAC_GENERIC, + SC_CARD_TYPE_CAC_I, + SC_CARD_TYPE_CAC_II, ++ SC_CARD_TYPE_CAC_ALT_HID, + + /* nPA cards */ + SC_CARD_TYPE_NPA = 34000, +diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c +index b1a0e88f..d41613b2 100644 +--- a/src/libopensc/iso7816.c ++++ b/src/libopensc/iso7816.c +@@ -1017,7 +1017,7 @@ iso7816_decipher(struct sc_card *card, + } + + +-static int ++int + iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, + struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len) + { +diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h +index b519c5d5..8ebf9fbd 100644 +--- a/src/libopensc/opensc.h ++++ b/src/libopensc/opensc.h +@@ -1664,6 +1664,19 @@ int iso7816_update_binary_sfid(sc_card_t *card, unsigned char sfid, + * */ + int iso7816_logout(sc_card_t *card, unsigned char pin_reference); + ++/* ++ * @brief Format PIN APDU for modifiction by card driver ++ * ++ * @param[in] card card ++ * @param[in] apdu apdu structure to update with PIN APDU ++ * @param[in] data pin command data to set into the APDU ++ * @param[in] buf buffer for APDU data field ++ * @param[in] buf_len maximum buffer length ++ */ ++int ++iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, ++ struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len); ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c +index ccb27994..05056ea9 100644 +--- a/src/libopensc/pkcs15-cac.c ++++ b/src/libopensc/pkcs15-cac.c +@@ -79,6 +79,7 @@ static const char * cac_get_name(int type) + switch (type) { + case SC_CARD_TYPE_CAC_I: return ("CAC I"); + case SC_CARD_TYPE_CAC_II: return ("CAC II"); ++ case SC_CARD_TYPE_CAC_ALT_HID: return ("CAC ALT HID"); + default: break; + } + return ("CAC"); diff --git a/opensc-0.20.0-calloc0.patch b/opensc-0.20.0-calloc0.patch new file mode 100644 index 0000000..341dc5e --- /dev/null +++ b/opensc-0.20.0-calloc0.patch @@ -0,0 +1,102 @@ +From f1bcadfbe9d156adbe509b0860511ee41add0c67 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Tue, 10 Mar 2020 12:13:29 +0100 +Subject: [PATCH] pkcs11: don't try to allocate 0 byte with calloc + +fixes #1978 +--- + src/pkcs11/pkcs11-global.c | 7 ++++++- + win32/Make.rules.mak | 4 ++-- + win32/winconfig.h.in | 2 ++ + 3 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c +index a3260314f8..671890309f 100644 +--- a/src/pkcs11/pkcs11-global.c ++++ b/src/pkcs11/pkcs11-global.c +@@ -456,6 +456,13 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese + + card_detect_all(); + ++ if (list_empty(&virtual_slots)) { ++ sc_log(context, "returned 0 slots\n"); ++ *pulCount = 0; ++ rv = CKR_OK; ++ goto out; ++ } ++ + found = calloc(list_size(&virtual_slots), sizeof(CK_SLOT_ID)); + + if (found == NULL) { +diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak +index 4f4971a72d..c6b1aac340 100644 +--- a/win32/Make.rules.mak ++++ b/win32/Make.rules.mak +@@ -1,7 +1,7 @@ + OPENSC_FEATURES = pcsc + + #Include support for minidriver +-MINIDRIVER_DEF = /DENABLE_MINIDRIVER ++#MINIDRIVER_DEF = /DENABLE_MINIDRIVER + + #Build MSI with the Windows Installer XML (WIX) toolkit, requires WIX >= 3.9 + !IF "$(WIX)" == "" +@@ -33,7 +33,7 @@ WIX_LIBS = "$(WIX)\SDK\$(WIXVSVER)\lib\$(PLATFORM)\dutil.lib" "$(WIX)\SDK\$(WIXV + SM_DEF = /DENABLE_SM + + #Build with debugging support +-#DEBUG_DEF = /DDEBUG ++DEBUG_DEF = /DDEBUG + + # If you want support for OpenSSL (needed for pkcs15-init tool, software hashing in PKCS#11 library and verification): + # - download and build OpenSSL +diff --git a/win32/winconfig.h.in b/win32/winconfig.h.in +index 94ed9b5475..fa682c5bcc 100644 +--- a/win32/winconfig.h.in ++++ b/win32/winconfig.h.in +@@ -103,6 +103,8 @@ + #define DEFAULT_ONEPIN_PKCS11_PROVIDER "@DEFAULT_ONEPIN_PKCS11_PROVIDER@" + #endif + ++#define PKCS11_THREAD_LOCKING ++ + #ifndef DEFAULT_SM_MODULE + #define DEFAULT_SM_MODULE "@DEFAULT_SM_MODULE@" + #endif + +commit 500ecd3d127975379e2310626c3ce94c3e7035ea +Author: Jakub Jelen +Date: Wed Nov 25 13:49:08 2020 +0100 + + pkcs11-tool: Avoid calloc with 0 argument + +diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c +index 4015aaf1..89244795 100644 +--- a/src/tools/pkcs11-tool.c ++++ b/src/tools/pkcs11-tool.c +@@ -1270,15 +1270,18 @@ static void list_slots(int tokens, int refresh, int print) + if (rv != CKR_OK) + p11_fatal("C_GetSlotList(NULL)", rv); + free(p11_slots); +- p11_slots = calloc(p11_num_slots, sizeof(CK_SLOT_ID)); +- if (p11_slots == NULL) { +- perror("calloc failed"); +- exit(1); ++ p11_slots = NULL; ++ if (p11_num_slots > 0) { ++ p11_slots = calloc(p11_num_slots, sizeof(CK_SLOT_ID)); ++ if (p11_slots == NULL) { ++ perror("calloc failed"); ++ exit(1); ++ } ++ rv = p11->C_GetSlotList(tokens, p11_slots, &p11_num_slots); ++ if (rv != CKR_OK) ++ p11_fatal("C_GetSlotList()", rv); + } + +- rv = p11->C_GetSlotList(tokens, p11_slots, &p11_num_slots); +- if (rv != CKR_OK) +- p11_fatal("C_GetSlotList()", rv); + } + + if (!print) diff --git a/opensc-0.20.0-cardos.patch b/opensc-0.20.0-cardos.patch new file mode 100644 index 0000000..b26b4ce --- /dev/null +++ b/opensc-0.20.0-cardos.patch @@ -0,0 +1,1338 @@ +From 592a641cb9f8eb17d4d1b1c9a96a1581f61e169b Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Sun, 29 Mar 2020 05:56:21 -0500 +Subject: [PATCH 2/6] pkcs11-tool - use valid data for decription tests + +In tests, make sute test data is either padded, or "zero" padded +so size if data <= modlen - 11. The smallest pad in 11 bytes, +00 | NN | PS | 00. PS is at least 8 bytes. +"zero" padding has N = 00, PS >= 8 byte of 00. + + On branch cardos-5.3 + Changes to be committed: + modified: tools/pkcs11-tool.c +--- + src/tools/pkcs11-tool.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c +index 3ad9289033..b1674a76cf 100644 +--- a/src/tools/pkcs11-tool.c ++++ b/src/tools/pkcs11-tool.c +@@ -5044,8 +5044,8 @@ static int test_signature(CK_SESSION_HANDLE sess) + } + + if (firstMechType == CKM_RSA_X_509) { +- /* make sure our data is smaller than the modulus */ +- data[0] = 0x00; ++ /* make sure our data is smaller than the modulus - 11 */ ++ memset(data, 0, 11); /* in effect is zero padding */ + } + + ck_mech.mechanism = firstMechType; + +From 3043f5b8a15c7cff90adcd2d31095afa734e663c Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Sun, 5 Apr 2020 11:04:42 -0500 +Subject: [PATCH 3/6] Increase SC_MAX_SUPPORTED_ALGORITHMS from 8 to 16 + +CardOS cards may have more then 8 supported_algo_info entries in tokenInfo. +We may bemissing some. We have seen 8 in some pkcs15-tool -i -v output. + +Simple fix is to incrase the limit. More appropriate fix is to remove the limit, +much like is done with sc_algorithm_info. and use realloc of the array. + + On branch cardos-5.3 + Changes to be committed: + modified: src/libopensc/pkcs15-prkey.c + modified: src/libopensc/pkcs15-skey.c + modified: src/libopensc/pkcs15.c + modified: src/libopensc/types.h +--- + src/libopensc/pkcs15-prkey.c | 10 +++++++++- + src/libopensc/pkcs15-skey.c | 10 +++++++++- + src/libopensc/pkcs15.c | 10 +++++++++- + src/libopensc/types.h | 6 ++++-- + 4 files changed, 31 insertions(+), 5 deletions(-) + +diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c +index ed008ede14..a6c05415ec 100644 +--- a/src/libopensc/pkcs15-prkey.c ++++ b/src/libopensc/pkcs15-prkey.c +@@ -48,10 +48,18 @@ + #include "aux-data.h" + + /* +- * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 ++ * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 + */ + #define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1) + static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = { ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, +diff --git a/src/libopensc/pkcs15-skey.c b/src/libopensc/pkcs15-skey.c +index b22e619723..4e58355ad7 100644 +--- a/src/libopensc/pkcs15-skey.c ++++ b/src/libopensc/pkcs15-skey.c +@@ -28,10 +28,18 @@ + #include + + /* +- * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 ++ * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 + */ + #define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1) + static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = { ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, +diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c +index ba04f531ef..d4a4496980 100644 +--- a/src/libopensc/pkcs15.c ++++ b/src/libopensc/pkcs15.c +@@ -64,9 +64,17 @@ static const struct sc_asn1_entry c_asn1_algorithm_info_parameters[3] = { + }; + + /* +- * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 ++ * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 + */ + static const struct sc_asn1_entry c_asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1] = { ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, ++ { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, +diff --git a/src/libopensc/types.h b/src/libopensc/types.h +index 76cf4c1a71..17035b5505 100644 +--- a/src/libopensc/types.h ++++ b/src/libopensc/types.h +@@ -52,9 +52,11 @@ typedef unsigned char u8; + + /* When changing this value, pay attention to the initialization of the ASN1 + * static variables that use this macro, like, for example, +- * 'c_asn1_supported_algorithms' in src/libopensc/pkcs15.c ++ * 'c_asn1_supported_algorithms' in src/libopensc/pkcs15.c, ++ * src/libopensc/pkcs15-prkey.c and src/libopensc/pkcs15-skey.c ++ * `grep "src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as"' + */ +-#define SC_MAX_SUPPORTED_ALGORITHMS 8 ++#define SC_MAX_SUPPORTED_ALGORITHMS 16 + + struct sc_lv_data { + unsigned char *value; + +From 8292ff57ad581995eca8209764813725594dd34f Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Fri, 17 Apr 2020 12:26:14 -0500 +Subject: [PATCH 4/6] sc_supported_algo_info - Put ECDSA OID as inline + + Mismatch of ASN1 parsing of tokeninfo.supported_algos[n].paramters + in one place parameter was treated as a pointer to sc_object_id + and in another as inline structure. This caused segfaults + in pkcs15-tool when it tried to print the OID. + + Changes to be committed: + modified: src/libopensc/opensc.h + modified: src/libopensc/pkcs15.c +--- + src/libopensc/opensc.h | 2 +- + src/libopensc/pkcs15.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h +index 9e764665b2..0c3c73e229 100644 +--- a/src/libopensc/opensc.h ++++ b/src/libopensc/opensc.h +@@ -223,7 +223,7 @@ extern "C" { + struct sc_supported_algo_info { + unsigned int reference; + unsigned int mechanism; +- struct sc_object_id *parameters; /* OID for ECC, NULL for RSA */ ++ struct sc_object_id parameters; /* OID for ECC */ + unsigned int operations; + struct sc_object_id algo_id; + unsigned int algo_ref; +diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c +index d4a4496980..c58c34fd13 100644 +--- a/src/libopensc/pkcs15.c ++++ b/src/libopensc/pkcs15.c +@@ -318,7 +318,7 @@ sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, + sc_format_asn1_entry(asn1_algo_infos[ii] + 1, &ti->supported_algos[ii].mechanism, &mechanism_len, 1); + sc_format_asn1_entry(asn1_algo_infos[ii] + 2, + asn1_algo_infos_parameters[ii], NULL, 1); +- if (!ti->supported_algos[ii].parameters) { ++ if (!sc_valid_oid(&ti->supported_algos[ii].parameters)) { + sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0, + NULL, NULL, 1); + } + +From f9665e4d46ed278b6cf1188e0e7adb5b6e119ac9 Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Thu, 26 Mar 2020 13:51:33 -0500 +Subject: [PATCH 5/6] pkcs15-tool.c - print Supported_algorithms from tokenInfo + +Some cards can provide supported algorithms in tokenInfo +which contain ECDSA OID, and PKCS11 mechanism + +Don't know how many Algo_refs were actually read, +and a ref of 0 may be valid. print at least one Algo_refs. + +Print the mechanism from PKCS11, and print operations +Use the $(top_srcdir)/src/pkcs11/pkcs11-display.c on Unix +Use the $(TOPDIR)\src\pkcs11\pkcs11-display.obj on Windows + +pkcs15.tool.c treat ECDSA OID as inline + +pkcs15-tool prints PKCS11 mechanisms using pkcs11-display.c +Automake now warns that the default will change, in the future +so "[subdir-objects]" is added to configure.ac + + Changes to be committed: + modified: configure.ac + modified: src/tools/Makefile.am + modified: src/tools/Makefile.mak + modified: src/tools/pkcs15-tool.c +--- + configure.ac | 2 +- + src/tools/Makefile.am | 2 +- + src/tools/Makefile.mak | 5 ++++ + src/tools/pkcs15-tool.c | 57 +++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 64 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 705bc027f1..f54093b0aa 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -27,7 +27,7 @@ AC_INIT([PRODUCT_NAME],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERS + AC_CONFIG_AUX_DIR([.]) + AC_CONFIG_HEADERS([config.h]) + AC_CONFIG_MACRO_DIR([m4]) +-AM_INIT_AUTOMAKE(foreign 1.10) ++AM_INIT_AUTOMAKE(foreign 1.10 [subdir-objects]) + + OPENSC_VERSION_MAJOR="PACKAGE_VERSION_MAJOR" + OPENSC_VERSION_MINOR="PACKAGE_VERSION_MINOR" +diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am +index 5ee5edfb29..55beb631d5 100644 +--- a/src/tools/Makefile.am ++++ b/src/tools/Makefile.am +@@ -52,7 +52,7 @@ piv_tool_SOURCES = piv-tool.c util.c + piv_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) + opensc_explorer_SOURCES = opensc-explorer.c util.c + opensc_explorer_LDADD = $(OPTIONAL_READLINE_LIBS) +-pkcs15_tool_SOURCES = pkcs15-tool.c util.c ++pkcs15_tool_SOURCES = pkcs15-tool.c util.c ../pkcs11/pkcs11-display.c ../pkcs11/pkcs11-display.h + pkcs15_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) + pkcs11_tool_SOURCES = pkcs11-tool.c util.c + pkcs11_tool_LDADD = \ +diff --git a/src/tools/Makefile.mak b/src/tools/Makefile.mak +index 4637a44dc6..38e5ba4e7e 100644 +--- a/src/tools/Makefile.mak ++++ b/src/tools/Makefile.mak +@@ -52,6 +52,11 @@ pkcs11-register.exe: pkcs11-register-cmdline.obj fread_to_eof.obj $(LIBS) + link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj pkcs11-register-cmdline.obj fread_to_eof.obj versioninfo-tools.res $(LIBS) gdi32.lib shell32.lib User32.lib ws2_32.lib + mt -manifest exe.manifest -outputresource:$@;1 + ++pkcs15-tool.exe: pkcs15-tool.obj $(TOPDIR)\src\pkcs11\pkcs11-display.obj ++ cl $(COPTS) /c $*.c ++ link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj $(TOPDIR)\src\pkcs11\pkcs11-display.obj $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib ++ mt -manifest exe.manifest -outputresource:$@;1 ++ + .c.exe: + cl $(COPTS) /c $< + link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib +diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c +index e901e17d0d..363bfb8272 100644 +--- a/src/tools/pkcs15-tool.c ++++ b/src/tools/pkcs15-tool.c +@@ -57,6 +57,7 @@ typedef unsigned __int32 uint32_t; + #include "libopensc/pkcs15.h" + #include "libopensc/asn1.h" + #include "util.h" ++#include "pkcs11/pkcs11-display.h" + + static const char *app_name = "pkcs15-tool"; + +@@ -607,6 +608,8 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj) + struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; + unsigned char guid[40]; + size_t guid_len; ++ int i; ++ int last_algo_refs = 0; + + if (compact) { + printf("\t%-3s", key_types[7 & obj->type]); +@@ -635,6 +638,16 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj) + printf("\tAccess Flags : [0x%02X]", prkey->access_flags); + print_key_access_flags(prkey->access_flags); + printf("\n"); ++ printf("\tAlgo_refs : "); ++ /* zero may be valid and don't know how many were read print at least 1*/ ++ for (i = 0; i< SC_MAX_SUPPORTED_ALGORITHMS; i++) { ++ if (prkey->algo_refs[i] != 0) ++ last_algo_refs = i; ++ } ++ for (i = 0; i< last_algo_refs + 1; i++) { ++ printf("%s%u", (i == 0) ? "" : ", ", prkey->algo_refs[i]); ++ } ++ printf("\n"); + + print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); + +@@ -1645,6 +1658,21 @@ static int list_apps(FILE *fout) + return 0; + } + ++ ++static void print_supported_algo_info_operations(unsigned int operation) ++ ++{ ++ size_t i; ++ const char *operations[] = { ++ "compute_checksum", "compute_signature", "verify_checksum", "verify_signature", ++ "encipher", "decipher", "hash", "generate/derive_key" ++ }; ++ const size_t operations_count = NELEMENTS(operations); ++ for (i = 0; i < operations_count; i++) ++ if (operation & (1 << i)) ++ printf(", %s", operations[i]); ++} ++ + static void list_info(void) + { + const char *flags[] = { +@@ -1655,6 +1683,7 @@ static void list_info(void) + }; + char *last_update = sc_pkcs15_get_lastupdate(p15card); + int i, count = 0; ++ int idx; + + printf("PKCS#15 Card [%s]:\n", p15card->tokeninfo->label); + printf("\tVersion : %d\n", p15card->tokeninfo->version); +@@ -1675,6 +1704,34 @@ static void list_info(void) + count++; + } + } ++ printf("\n"); ++ for (i = 0; i < SC_MAX_SUPPORTED_ALGORITHMS; i++) { ++ struct sc_supported_algo_info * sa = &p15card->tokeninfo->supported_algos[i]; ++ ++ if (sa->reference == 0 && sa->reference == 0 && sa->mechanism == 0 ++ && sa->operations == 0 && sa->algo_ref == 0) ++ break; ++ printf("\t\t sc_supported_algo_info[%d]:\n", i); ++ printf("\t\t\t reference : %u (0x%02x)\n", sa->reference, sa->reference); ++ printf("\t\t\t mechanism : [0x%02x] %s\n", sa->mechanism, lookup_enum(MEC_T, sa->mechanism)); ++ if (sc_valid_oid(&sa->parameters)) { ++ printf("\t\t\t parameters: %i", sa->parameters.value[0]); ++ for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && sa->parameters.value[idx] != -1 ; idx++) ++ printf(".%i", sa->parameters.value[idx]); ++ printf("\n"); ++ } ++ printf("\t\t\t operations : [0x%2.2x]",sa->operations); ++ print_supported_algo_info_operations(sa->operations); ++ printf("\n"); ++ if (sc_valid_oid((const struct sc_object_id*)&sa->algo_id)) { ++ printf("\t\t\t algo_id : %i", sa->algo_id.value[0]); ++ for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && sa->algo_id.value[idx] != -1 ; idx++) ++ printf(".%i", sa->algo_id.value[idx]); ++ printf("\n"); ++ } ++ printf("\t\t\t algo_ref : [0x%02x]\n",sa->algo_ref); ++ } ++ + printf((compact) ? "\n" : "\n\n"); + } + + +From f472f0ec213adc096508997bf7e1786ffb557d52 Mon Sep 17 00:00:00 2001 +From: Doug Engert +Date: Fri, 17 Apr 2020 11:36:48 -0500 +Subject: [PATCH 6/6] Various CardOS V5_* improvements +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Treat CardOS V5_0 and V5_3 cards differently then older versions: + +Use card->dvr_data as a pointer to cardos_data_t to store private driver +data to pass internally, especially between set security environment +and the crypto operations. Sc_get_encoding_flags sets sec_flags from +algo_info->flags in pkcs15-sec.c and it passed to decipher. + +Some cards when doing a decipher may drop leading 00 byte when +returning data from RSA_RAW decipher. Add leading byte(s) as needed. + +Get Cryptographic Mechanism Reference from Key Reference: + +Key reference byte appears to be a 4 bit Cryptographic Mechanism Reference +and a 4 bit key reference. + +This is only done if key reference & 0xF0 != 0 i.e. default Cryptographic +mechanism reference is 0. which appears to be the case for RSA RAW. +PKCS1 appears to be 0x10 and ECDSA 0x30 + + See iso 7816-4 table 55 for DST: + 84 Reference of a private key + 95 Usage qualifier byte - Table 57 - 40 looks OK + 80 Cryptographic mechanism reference and referes to section 9.2 + +The 4 bit key reference limits card to 16 keys. In future this may not work, +but we can derive a Cryptographic Mechanism Reference from what OpenSC +thinks the card needs to do. Only know RSA RAW, PKCS1 and ECDSA. + +ECDSA code has not been tested, but expected to work. + +Allow setting CardOS type and flags from opensc.conf using card_atr stanza +This is a fallback if newer cards are added or older cards have problems +giving us time to make need changes in next release. + +It will help in identifying what flags are needed for each card. +As user can report what combination of flags work for them. They do this by +adding to opensc.conf with something like this. (Change the ATR to your card's ATR): + + card_atr 3b:d2:18:00:81:31:fe:58:c9:03:16 { + driver = "cardos"; + # type is decimal from cards.h: + # SC_CARD_TYPE_CARDOS_V5_0 is 1009 + # SC_CARD_TYPE_CARDOS_V5_3 is 1010 + type = 1010; + + # flags is hex from opensc.h: + #define SC_ALGORITHM_ONBOARD_KEY_GEN 0x80000000 + #define SC_ALGORITHM_NEED_USAGE 0x40000000 + + #define SC_ALGORITHM_RSA_RAW 0x00000001 /* RSA_RAW is PAD_NONE */ + #define SC_ALGORITHM_RSA_PAD_NONE 0x00000001 + #define SC_ALGORITHM_RSA_PAD_PKCS1 0x00000002 /* PKCS#1 v1.5 padding */ + #define SC_ALGORITHM_RSA_PAD_ANSI 0x00000004 + #define SC_ALGORITHM_RSA_PAD_ISO9796 0x00000008 + #define SC_ALGORITHM_RSA_PAD_PSS 0x00000010 /* PKCS#1 v2.0 PSS */ + #define SC_ALGORITHM_RSA_PAD_OAEP 0x00000020 /* PKCS#1 v2.0 OAEP */ + #define SC_ALGORITHM_RSA_HASH_NONE 0x00000100 /* only applies to PKCS1 padding */ + # example: SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_RAW + flags = 80000101; + #example: SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_PAD_PKCS1 + flags = 80000002; + } + +For V5_0 and v5_3 cards, use sc_get_max_send_size and sc_get_max_recv_size +which takes care or reader sizes even on Windows where SCardControl can not get PART_10 sizes. + +(commit eddea6f3c2d3dafc2c09eba6695c745a61b5186f on Windows forces reader sizes to 255, 256 +in reader-pcsc.c if not already set. It should not do this, but leave that up to card drivers.) + +pkcs15-cardos.c added: + +New file, pkcs15-cardos.c, added as emulation only for CardOS +V5_0 and V5_3 cards. + +sc_pkcs15_bind_internal is called to get tokenInfo as CardOS +cards are substantially PKCS15 cards. But some V5_* cards have +errors in the tokenInfo, Which are corrected. + +For older CardOS cards, card-cardos.c will create all the +card->algorithms. + +Pkcs15-cardos.c will check for card->algorithms and if there +are none, it will do the following: + +SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS is called twice. First to get +the flags as set by user via opensc.conf card_atr or default +flags set by the card driver. Then after determining from the +tokenInfo what algorithms the card can support, the new flags +are passed to card_cardos.c to create card->algorithms. + +https://atos.net/wp-content/uploads/2018/11/CT_181026_LPM_CardOS_V5-3_Multifunctionality_FS_en3_web.pdf +says card supports: "“Command chaining” in accordance with ISO/IEC 7816-4" + +To take advantage of this with older readers, max_send_size and max_recv_size +is now based on minimum of reader limits and "data_field_length" from card. +This should allow card to work in older readers not capable of extended APDU. +So far current cards we have seen do no appear to support “Command chaining”. + + Changes to be committed: + modified: src/libopensc/Makefile.am + modified: src/libopensc/Makefile.mak + modified: src/libopensc/card-cardos.c + modified: src/libopensc/cardctl.h + modified: src/libopensc/cards.h + new file: src/libopensc/pkcs15-cardos.c + modified: src/libopensc/pkcs15-syn.c + modified: src/libopensc/pkcs15-syn.h +--- + src/libopensc/Makefile.am | 4 +- + src/libopensc/Makefile.mak | 2 +- + src/libopensc/card-cardos.c | 336 +++++++++++++++++++++++++++++----- + src/libopensc/cardctl.h | 18 ++ + src/libopensc/cards.h | 1 + + src/libopensc/pkcs15-cardos.c | 177 ++++++++++++++++++ + src/libopensc/pkcs15-syn.c | 3 + + src/libopensc/pkcs15-syn.h | 1 + + 8 files changed, 492 insertions(+), 50 deletions(-) + create mode 100644 src/libopensc/pkcs15-cardos.c + +diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am +index 140665c8a6..9f0dda5ecb 100644 +--- a/src/libopensc/Makefile.am ++++ b/src/libopensc/Makefile.am +@@ -51,7 +51,7 @@ libopensc_la_SOURCES_BASE = \ + ctbcs.c reader-ctapi.c reader-pcsc.c reader-openct.c reader-tr03119.c \ + \ + card-setcos.c card-miocos.c card-flex.c card-gpk.c \ +- card-cardos.c card-tcos.c card-default.c \ ++ card-cardos.c card-tcos.c pkcs15-cardos.c card-default.c \ + card-mcrd.c card-starcos.c card-openpgp.c card-jcop.c \ + card-oberthur.c card-belpic.c card-atrust-acos.c \ + card-entersafe.c card-epass2003.c card-coolkey.c card-incrypto34.c \ +@@ -134,7 +134,7 @@ TIDY_FILES = \ + card-npa.c card-esteid2018.c card-idprime.c \ + \ + pkcs15-openpgp.c \ +- pkcs15-tcos.c pkcs15-esteid.c \ ++ pkcs15-tcos.c pkcs15-esteid.c pkcs15-cardos.c \ + pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c \ + pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ + pkcs15-oberthur.c pkcs15-itacns.c pkcs15-sc-hsm.c \ +diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak +index 2e3c30c22b..1b0ff45c9b 100644 +--- a/src/libopensc/Makefile.mak ++++ b/src/libopensc/Makefile.mak +@@ -29,7 +29,7 @@ OBJECTS = \ + card-masktech.obj card-gids.obj card-jpki.obj \ + card-npa.obj card-esteid2018.obj card-idprime.obj \ + \ +- pkcs15-openpgp.obj pkcs15-starcert.obj \ ++ pkcs15-openpgp.obj pkcs15-starcert.obj pkcs15-cardos.obj \ + pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-gemsafeGPK.obj \ + pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \ + pkcs15-cac.obj pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-din-66291.obj \ +diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c +index 306822b974..4ef6ead0d2 100644 +--- a/src/libopensc/card-cardos.c ++++ b/src/libopensc/card-cardos.c +@@ -53,13 +53,42 @@ static const struct sc_atr_table cardos_atrs[] = { + /* CardOS v5.0 */ + { "3b:d2:18:00:81:31:fe:58:c9:01:14", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL}, + /* CardOS v5.3 */ +- { "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL}, +- { "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL}, ++ { "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL}, ++ { "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL}, + { NULL, NULL, NULL, 0, 0, NULL } + }; + +-static unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS]; +-static unsigned int algorithm_ids_in_tokeninfo_count=0; ++/* private data for cardos driver */ ++typedef struct cardos_data { ++ /* constructed internally */ ++ unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS]; ++ unsigned int algorithm_ids_in_tokeninfo_count; ++ unsigned long flags; /* flags used by init to create sc_algorithms */ ++ unsigned long ec_flags; ++ unsigned long ext_flags; ++ int rsa_2048; ++ const sc_security_env_t * sec_env; ++} cardos_data_t; ++ ++/* copied from iso7816.c */ ++static void fixup_transceive_length(const struct sc_card *card, ++ struct sc_apdu *apdu) ++{ ++ if (card == NULL || apdu == NULL) { ++ return; ++ } ++ ++ if (apdu->lc > sc_get_max_send_size(card)) { ++ /* The lower layers will automatically do chaining */ ++ apdu->flags |= SC_APDU_FLAGS_CHAINING; ++ } ++ ++ if (apdu->le > sc_get_max_recv_size(card)) { ++ /* The lower layers will automatically do a GET RESPONSE, if possible. ++ * All other workarounds must be carried out by the upper layers. */ ++ apdu->le = sc_get_max_recv_size(card); ++ } ++} + + static int cardos_match_card(sc_card_t *card) + { +@@ -79,6 +108,8 @@ static int cardos_match_card(sc_card_t *card) + return 1; + if (card->type == SC_CARD_TYPE_CARDOS_V5_0) + return 1; ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_3) ++ return 1; + if (card->type == SC_CARD_TYPE_CARDOS_M4_2) { + int rv; + sc_apdu_t apdu; +@@ -159,42 +190,102 @@ static int cardos_have_2048bit_package(sc_card_t *card) + return 0; + } + ++ ++/* Called from cardos_init for old cards, from cardos_cardctl_parsed_token_info for new cards */ ++/* TODO see if works from old cards too */ ++static int cardos_add_algs(sc_card_t *card, unsigned long flags, unsigned long ec_flags, unsigned long ext_flags) ++{ ++ ++ cardos_data_t * priv = (cardos_data_t *)card->drv_data; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ _sc_card_add_rsa_alg(card, 512, flags, 0); ++ _sc_card_add_rsa_alg(card, 768, flags, 0); ++ _sc_card_add_rsa_alg(card, 1024, flags, 0); ++ if (priv->rsa_2048 == 1) { ++ _sc_card_add_rsa_alg(card, 1280, flags, 0); ++ _sc_card_add_rsa_alg(card, 1536, flags, 0); ++ _sc_card_add_rsa_alg(card, 1792, flags, 0); ++ _sc_card_add_rsa_alg(card, 2048, flags, 0); ++ } ++ ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ /* Starting with CardOS 5, the card supports PIN query commands */ ++ card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; ++ _sc_card_add_rsa_alg(card, 3072, flags, 0); ++ _sc_card_add_rsa_alg(card, 4096, flags, 0); ++ } ++ ++ /* TODO need to get sizes from supported_algos too */ ++ if (ec_flags != 0) { ++ _sc_card_add_ec_alg(card, 256, ec_flags, priv->ext_flags, NULL); ++ _sc_card_add_ec_alg(card, 384, ec_flags, priv->ext_flags, NULL); ++ } ++ ++ return 0; ++} ++ + static int cardos_init(sc_card_t *card) + { +- unsigned long flags = 0, rsa_2048 = 0; ++ cardos_data_t * priv = NULL; ++ unsigned long flags = 0; + size_t data_field_length; + sc_apdu_t apdu; + u8 rbuf[2]; + int r; + ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ priv = calloc(1, sizeof(cardos_data_t)); ++ if (!priv) ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); ++ card->drv_data = priv; ++ + card->name = "Atos CardOS"; + card->cla = 0x00; + +- /* Set up algorithm info. */ +- flags = 0; +- if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { +- flags |= SC_ALGORITHM_RSA_PAD_PKCS1; ++ /* let user override flags and type from opensc.conf */ ++ /* user can override card->type too.*/ ++ if (card->flags) { ++ flags = card->flags; + } else { +- flags |= SC_ALGORITHM_RSA_RAW +- | SC_ALGORITHM_RSA_HASH_NONE +- | SC_ALGORITHM_NEED_USAGE +- | SC_ALGORITHM_ONBOARD_KEY_GEN; ++ ++ /* Set up algorithm info. */ ++ flags = 0; ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { ++ flags |= SC_ALGORITHM_RSA_PAD_PKCS1; ++ } else if(card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ flags |= SC_ALGORITHM_RSA_RAW ++ | SC_ALGORITHM_RSA_HASH_NONE ++ | SC_ALGORITHM_ONBOARD_KEY_GEN; ++ } else { ++ flags |= SC_ALGORITHM_RSA_RAW ++ | SC_ALGORITHM_RSA_HASH_NONE ++ | SC_ALGORITHM_NEED_USAGE ++ | SC_ALGORITHM_ONBOARD_KEY_GEN; ++ } + } + ++ priv->flags = flags; ++ + if (card->type == SC_CARD_TYPE_CARDOS_M4_2) { + r = cardos_have_2048bit_package(card); + if (r < 0) + return SC_ERROR_INVALID_CARD; + if (r == 1) +- rsa_2048 = 1; ++ priv->rsa_2048 = 1; + card->caps |= SC_CARD_CAP_APDU_EXT; +- } else if (card->type == SC_CARD_TYPE_CARDOS_M4_3 ++ } else if (card->type == SC_CARD_TYPE_CARDOS_M4_3 + || card->type == SC_CARD_TYPE_CARDOS_M4_2B + || card->type == SC_CARD_TYPE_CARDOS_M4_2C + || card->type == SC_CARD_TYPE_CARDOS_M4_4 +- || card->type == SC_CARD_TYPE_CARDOS_V5_0) { +- rsa_2048 = 1; ++ || card->type == SC_CARD_TYPE_CARDOS_V5_0 ++ || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ priv->rsa_2048 = 1; + card->caps |= SC_CARD_CAP_APDU_EXT; ++ /* TODO check this. EC only if in supported_algo */ ++ priv->ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; + } + + /* probe DATA FIELD LENGTH with GET DATA */ +@@ -202,6 +293,7 @@ static int cardos_init(sc_card_t *card) + apdu.le = sizeof rbuf; + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); ++ + r = sc_transmit_apdu(card, &apdu); + if (r < 0) + LOG_TEST_RET(card->ctx, +@@ -216,34 +308,99 @@ static int cardos_init(sc_card_t *card) + return SC_ERROR_INVALID_CARD; + data_field_length = ((rbuf[0] << 8) | rbuf[1]); + +- /* strip the length of possible Lc and Le bytes */ +- if (card->caps & SC_CARD_CAP_APDU_EXT) +- card->max_send_size = data_field_length - 6; +- else +- card->max_send_size = data_field_length - 3; +- /* strip the length of SW bytes */ +- card->max_recv_size = data_field_length - 2; ++ /* TODO is this really needed? strip the length of possible Lc and Le bytes */ ++ ++ /* Use Min card sizes and reader too. for V5_3 at least*/ ++ ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "data_field_length:%"SC_FORMAT_LEN_SIZE_T"u " ++ "card->reader->max_send_size:%"SC_FORMAT_LEN_SIZE_T"u " ++ "card->reader->max_recv_size:%"SC_FORMAT_LEN_SIZE_T"u %s", ++ data_field_length, card->reader->max_send_size, card->reader->max_recv_size, ++ (card->caps & SC_CARD_CAP_APDU_EXT) ? "SC_CARD_CAP_APDU_EXT" : " "); ++ ++ if (card->caps & SC_CARD_CAP_APDU_EXT) { ++ card->max_send_size = data_field_length - 6; ++#ifdef _WIN32 ++ /* Windows does not support PCSC PART_10 and may have forced reader to 255/256 ++ * https://github.com/OpenSC/OpenSC/commit/eddea6f3c2d3dafc2c09eba6695c745a61b5186f ++ * may have reset this. if so, will override and force extended ++ * Most, if not all, cardos cards do extended, but not chaining ++ */ ++ if (card->reader->max_send_size == 255 && card->reader->max_recv_size == 256) { ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "reseting reader to use data_field_length"); ++ card->reader->max_send_size = data_field_length - 6; ++ card->reader->max_recv_size = data_field_length - 3; ++ } ++#endif ++ } else ++ card->max_send_size = data_field_length - 3; + +- _sc_card_add_rsa_alg(card, 512, flags, 0); +- _sc_card_add_rsa_alg(card, 768, flags, 0); +- _sc_card_add_rsa_alg(card, 1024, flags, 0); +- if (rsa_2048 == 1) { +- _sc_card_add_rsa_alg(card, 1280, flags, 0); +- _sc_card_add_rsa_alg(card, 1536, flags, 0); +- _sc_card_add_rsa_alg(card, 1792, flags, 0); +- _sc_card_add_rsa_alg(card, 2048, flags, 0); ++ card->max_send_size = sc_get_max_send_size(card); /* include reader sizes and protocol */ ++ card->max_recv_size = data_field_length - 2; ++ card->max_recv_size = sc_get_max_recv_size(card); ++ } else { ++ /* old way, disregards reader capabilities */ ++ if (card->caps & SC_CARD_CAP_APDU_EXT) ++ card->max_send_size = data_field_length - 6; ++ else ++ card->max_send_size = data_field_length - 3; ++ /* strip the length of SW bytes */ ++ card->max_recv_size = data_field_length - 2; + } + +- if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { +- /* Starting with CardOS 5, the card supports PIN query commands */ +- card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; +- _sc_card_add_rsa_alg(card, 3072, flags, 0); +- _sc_card_add_rsa_alg(card, 4096, flags, 0); ++ /*for new cards, wait till after sc_pkcs15_bind_internal reads tokeninfo */ ++ if (card->type != SC_CARD_TYPE_CARDOS_V5_0 && card->type != SC_CARD_TYPE_CARDOS_V5_3) { ++ r = cardos_add_algs(card, flags, 0, 0); + } + + return 0; + } + ++static int cardos_pass_algo_flags(sc_card_t *card, struct sc_cardctl_cardos_pass_algo_flags * ptr) ++{ ++ cardos_data_t * priv = (cardos_data_t *)card->drv_data; ++ int r = 0; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ switch (ptr->pass) { ++ case 1: ++ ptr->card_flags = card->flags; ++ ptr->used_flags = priv->flags; ++ ptr->ec_flags = priv->ec_flags; ++ ptr->ext_flags = priv->ext_flags; ++ break; ++ case 2: ++ r = cardos_add_algs(card,ptr->new_flags, ptr->ec_flags, ptr->ext_flags); ++ break; ++ default: ++ sc_log(card->ctx, "ptr->pass: %ul invalid", ptr->pass); ++ r = SC_ERROR_INTERNAL; ++ } ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ ++ ++static int cardos_finish(sc_card_t *card) ++{ ++ int r = 0; ++ ++ if (card) ++ return 0; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ /* free priv data */ ++ if (card->drv_data) { /* priv */ ++ free(card->drv_data); ++ card->drv_data = NULL; ++ } ++ ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); ++} ++ ++ ++ + static const struct sc_card_error cardos_errors[] = { + /* some error inside the card */ + /* i.e. nothing you can do */ +@@ -772,8 +929,9 @@ cardos_set_security_env(sc_card_t *card, + const sc_security_env_t *env, + int se_num) + { ++ cardos_data_t* priv = (cardos_data_t*)card->drv_data; + sc_apdu_t apdu; +- u8 data[6]; ++ u8 data[9]; + int key_id, r; + + assert(card != NULL && env != NULL); +@@ -782,6 +940,15 @@ cardos_set_security_env(sc_card_t *card, + sc_log(card->ctx, "No or invalid key reference\n"); + return SC_ERROR_INVALID_ARGUMENTS; + } ++ priv->sec_env = env; /* pass on to crypto routines */ ++ ++ /* key_ref includes card mechanism and key number ++ * But newer cards appear to get this some other way, ++ * We can use flags passed to know what OpenSC expects from the card ++ * and have derived what these machanisums are. ++ * Newer cards may change how this is done ++ */ ++ + key_id = env->key_ref[0]; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); +@@ -802,16 +969,39 @@ cardos_set_security_env(sc_card_t *card, + return SC_ERROR_INVALID_ARGUMENTS; + } + +- if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ /* some cards appear to have key_id be both Cryptographic mechanism reference 4 bits ++ * and key_ref 4 bits. But this limits card to 16 keys. ++ * TODO may need to be looked at at a later time ++ */ + /* Private key reference */ + data[0] = 0x84; + data[1] = 0x01; +- data[2] = key_id; ++ data[2] = key_id & 0x0F; + /* Usage qualifier byte */ + data[3] = 0x95; + data[4] = 0x01; + data[5] = 0x40; + apdu.lc = apdu.datalen = 6; ++ if (key_id & 0xF0) { ++ /* Cryptographic mechanism reference */ ++ data[6] = 0x80; ++ data[7] = 0x01; ++ data[8] = key_id & 0xF0; ++ apdu.lc = apdu.datalen = 9; ++ } else if (priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { ++ /* TODO this may only apply to c903 cards */ ++ /* TODO or only for cards without any supported_algos or EIDComplient only */ ++ data[6] = 0x80; ++ data[7] = 0x01; ++ data[8] = 0x10; ++ apdu.lc = apdu.datalen = 9; ++ } else if (priv->sec_env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW) { ++ data[6] = 0x80; ++ data[7] = 0x01; ++ data[8] = 0x30; ++ apdu.lc = apdu.datalen = 9; ++ } + } else { + data[0] = 0x83; + data[1] = 0x01; +@@ -839,12 +1029,12 @@ cardos_set_security_env(sc_card_t *card, + + sc_log(card->ctx, "is signature"); + sc_log(card->ctx, "Adding ID %d at index %d", algorithm_id, algorithm_id_count); +- algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id; ++ priv->algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id; + } + sc_log(card->ctx, "reference=%d, mechanism=%d, operations=%d, algo_ref=%d", + alg.reference, alg.mechanism, alg.operations, alg.algo_ref); + } +- algorithm_ids_in_tokeninfo_count = algorithm_id_count; ++ priv -> algorithm_ids_in_tokeninfo_count = algorithm_id_count; + } while (0); + + LOG_FUNC_RETURN(card->ctx, r); +@@ -859,6 +1049,7 @@ static int + do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + u8 *out, size_t outlen) + { ++ /* cardos_data_t* priv = (cardos_data_t*)card->drv_dataa */; + int r; + sc_apdu_t apdu; + +@@ -873,6 +1064,7 @@ do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + apdu.data = data; + apdu.lc = datalen; + apdu.datalen = datalen; ++ fixup_transceive_length(card, &apdu); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + +@@ -886,6 +1078,7 @@ static int + cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + u8 *out, size_t outlen) + { ++ cardos_data_t* priv; + int r; + sc_context_t *ctx; + int do_rsa_pure_sig = 0; +@@ -895,8 +1088,21 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + + assert(card != NULL && data != NULL && out != NULL); + ctx = card->ctx; ++ priv = (cardos_data_t*)card->drv_data; + SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); + ++ /* sec_env has algorithm_flags set from sc_get_encoding_flags sec_flags ++ * If flags are set correctly we don't need to test anything ++ * TODO this assumes RSA is PSS, PKCS1 or RAW and we are passing ++ * the correct data. Should work for ECDSA too. ++ * use for V5 cards and TODO should for older cards too ++ */ ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ ++ r = do_compute_signature(card, data, datalen, out, outlen); ++ LOG_FUNC_RETURN(ctx, r); ++ } ++ + /* There are two ways to create a signature, depending on the way, + * the key was created: RSA_SIG and RSA_PURE_SIG. + * We can use the following reasoning, to determine the correct operation: +@@ -913,8 +1119,8 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, + */ + + /* check the the algorithmIDs from the AlgorithmInfo */ +- for (i = 0; i < algorithm_ids_in_tokeninfo_count; ++i) { +- unsigned int id = algorithm_ids_in_tokeninfo[i]; ++ for (i = 0; i < priv->algorithm_ids_in_tokeninfo_count; ++i) { ++ unsigned int id = priv->algorithm_ids_in_tokeninfo[i]; + if (id == 0x86 || id == 0x88) { + do_rsa_sig = 1; + } else if (id == 0x8C || id == 0x8A) { +@@ -985,10 +1191,41 @@ cardos_decipher(struct sc_card *card, + const u8 * crgram, size_t crgram_len, + u8 * out, size_t outlen) + { ++ cardos_data_t* priv = (cardos_data_t*)card->drv_data; + int r; + size_t card_max_send_size = card->max_send_size; + size_t reader_max_send_size = card->reader->max_send_size; + ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ /* 5.3 supports command chaining. Others may also ++ * card_max_send_size for 5.3 is already based on reader max_send_size */ ++ ++ if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { ++ ++ r = iso_ops->decipher(card, crgram, crgram_len, out, outlen); ++ /* ++ * 5.3 supports RAW as well as PKCS1 and PSS ++ * decription may strip padding if card supports it ++ * with cards that support RAW, it always appears to ++ * drop first 00 that is start of padding. ++ */ ++ ++ if (r > 0 && priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_RAW) { ++ size_t rsize = r; ++ /* RSA RAW crgram_len == modlen */ ++ /* removed padding is always > 1 byte */ ++ /* add back missing leading zero if card dropped it */ ++ if (rsize == crgram_len - 1 && rsize < outlen) { ++ memmove(out+1, out, rsize); ++ out[0] =0x00; ++ r++; ++ } ++ } ++ ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); ++ } ++ + if (sc_get_max_send_size(card) < crgram_len + 1) { + /* CardOS doesn't support chaining for PSO:DEC, so we just _hope_ + * that both, the reader and the card are able to send enough data. +@@ -1003,7 +1240,7 @@ cardos_decipher(struct sc_card *card, + card->max_send_size = card_max_send_size; + card->reader->max_send_size = reader_max_send_size; + +- return r; ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); + } + + static int +@@ -1188,7 +1425,7 @@ static int cardos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) + return SC_ERROR_INTERNAL; +- if ((apdu.resplen == 8) && (card->type == SC_CARD_TYPE_CARDOS_V5_0)) { ++ if ((apdu.resplen == 8) && (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3)) { + /* cache serial number */ + memcpy(card->serialnr.value, rbuf, 8); + card->serialnr.len = 8; +@@ -1223,6 +1460,9 @@ cardos_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) + case SC_CARDCTL_CARDOS_GENERATE_KEY: + return cardos_generate_key(card, + (struct sc_cardctl_cardos_genkey_info *) ptr); ++ case SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS: ++ return cardos_pass_algo_flags(card, ++ (struct sc_cardctl_cardos_pass_algo_flags *) ptr); + case SC_CARDCTL_LIFECYCLE_GET: + return cardos_lifecycle_get(card, (int *) ptr); + case SC_CARDCTL_LIFECYCLE_SET: +@@ -1279,7 +1519,8 @@ cardos_logout(sc_card_t *card) + || card->type == SC_CARD_TYPE_CARDOS_M4_2C + || card->type == SC_CARD_TYPE_CARDOS_M4_3 + || card->type == SC_CARD_TYPE_CARDOS_M4_4 +- || card->type == SC_CARD_TYPE_CARDOS_V5_0) { ++ || card->type == SC_CARD_TYPE_CARDOS_V5_0 ++ || card->type == SC_CARD_TYPE_CARDOS_V5_3) { + sc_apdu_t apdu; + int r; + sc_path_t path; +@@ -1309,6 +1550,7 @@ static struct sc_card_driver * sc_get_driver(void) + cardos_ops = *iso_ops; + cardos_ops.match_card = cardos_match_card; + cardos_ops.init = cardos_init; ++ cardos_ops.finish = cardos_finish; + cardos_ops.select_file = cardos_select_file; + cardos_ops.create_file = cardos_create_file; + cardos_ops.set_security_env = cardos_set_security_env; +diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h +index 0c68c4c625..10ddfa0545 100644 +--- a/src/libopensc/cardctl.h ++++ b/src/libopensc/cardctl.h +@@ -83,6 +83,7 @@ enum { + SC_CARDCTL_CARDOS_PUT_DATA_OCI, + SC_CARDCTL_CARDOS_PUT_DATA_SECI, + SC_CARDCTL_CARDOS_GENERATE_KEY, ++ SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, + + /* + * Starcos SPK 2.3 specific calls +@@ -350,6 +351,14 @@ typedef struct sc_cardctl_pkcs11_init_pin { + size_t pin_len; + } sc_cardctl_pkcs11_init_pin_t; + ++/* ++ * Generic cardctl - card driver can examine token info ++ */ ++struct sc_cardctl_parsed_token_info { ++ unsigned int flags; ++ struct sc_pkcs15_tokeninfo * tokeninfo; ++}; ++ + /* + * GPK lock file. + * Parent DF of file must be selected. +@@ -419,6 +428,15 @@ struct sc_cardctl_cardos_genkey_info { + unsigned short fid; + }; + ++struct sc_cardctl_cardos_pass_algo_flags { ++ unsigned int pass; ++ unsigned long card_flags; /* from card->flags i.e. user set */ ++ unsigned long used_flags; /* as set by default */ ++ unsigned long new_flags; /* set in pkcs15-cardos.c */ ++ unsigned long ec_flags; /* for EC keys */ ++ unsigned long ext_flags; /* for EC keys */ ++}; ++ + /* + * Incrypto34 PIN info + */ +diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h +index cb0501c3aa..8d58fb9368 100644 +--- a/src/libopensc/cards.h ++++ b/src/libopensc/cards.h +@@ -47,6 +47,7 @@ enum { + SC_CARD_TYPE_CARDOS_CIE_V1, /* Italian CIE (eID) v1 */ + SC_CARD_TYPE_CARDOS_M4_4, + SC_CARD_TYPE_CARDOS_V5_0, ++ SC_CARD_TYPE_CARDOS_V5_3, + + /* flex/cyberflex drivers */ + SC_CARD_TYPE_FLEX_BASE = 2000, +diff --git a/src/libopensc/pkcs15-cardos.c b/src/libopensc/pkcs15-cardos.c +new file mode 100644 +index 0000000000..752631ce88 +--- /dev/null ++++ b/src/libopensc/pkcs15-cardos.c +@@ -0,0 +1,177 @@ ++/* ++ * PKCS15 emulation layer for CardOS cards ++ * Adapted from PKCS15 emulation layer for IAS/ECC card. ++ * ++ * Copyright (C) 2020, Douglas E. Engert ++ * Copyright (C) 2016, Viktor Tarasov ++ * Copyright (C) 2004, Bud P. Bruegger ++ * Copyright (C) 2004, Antonino Iacono ++ * Copyright (C) 2003, Olaf Kirch ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#if HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include ++#include ++#include ++ ++#include "internal.h" ++#include "pkcs15.h" ++ ++ ++/* ++ * Called after sc_pkcs15_bind_internal ++ * Create new flags based on supported_algos. ++ */ ++static int cardos_fix_token_info(sc_pkcs15_card_t *p15card) ++{ ++ sc_card_t *card; ++ struct sc_supported_algo_info (*saa)[SC_MAX_SUPPORTED_ALGORITHMS]; ++ struct sc_supported_algo_info *sa; ++ struct sc_cardctl_cardos_pass_algo_flags *passed = NULL; ++ int r = 0; ++ int i; ++ ++ card = p15card->card; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ passed = calloc(1, sizeof(struct sc_cardctl_cardos_pass_algo_flags)); ++ if (!passed) ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); ++ ++ passed->pass = 1; /* get used_flags and card_flags from card */ ++ r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed); ++ if (r < 0) { ++ free(passed); ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ ++ saa = &(p15card->tokeninfo->supported_algos); ++ ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Original Flags: 0x%8.8lx card->flags:0x%8.8lx", passed->used_flags, passed->card_flags); ++ ++ if (passed->card_flags) { /* user forced the flags, use them */ ++ passed->new_flags = passed->card_flags; /* from card_atr flags */ ++ } else { ++ ++ for (i = 0, sa = saa[0]; i < SC_MAX_SUPPORTED_ALGORITHMS; i++, sa++) { ++ ++ if (sa->reference == 0 && sa->reference == 0 && sa->mechanism == 0 ++ && sa->operations == 0 && sa->algo_ref == 0) ++ break; ++ ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "supported_algos[%d] mechamism:0x%8.8x", i, sa->mechanism); ++ switch(sa->mechanism) { ++ case 0x01 : ++ /* ++ * Card appears to use lower 4 bits of reference as key, and upper ++ * 4 bits as mech for card. ++ * Also has a bug if mechanism = 1 (CKM_RSA_PKCS1) and reference 0x10 ++ * bit is set mechanism should be 3 (CKM_RSA_X_509) ++ * correct the mechanism in tokenInfo ++ */ ++ if (sa->reference & 0x10) { ++ sc_log(card->ctx, "Changeing mechanism to CKM_RSA_X_509 based on reference"); ++ passed->new_flags |= SC_ALGORITHM_RSA_RAW ++ | SC_ALGORITHM_RSA_PAD_NONE; ++ sa->mechanism = 0x03; ++ } else ++ passed->new_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; ++ break; ++ case 0x03 : ++ passed->new_flags |= SC_ALGORITHM_RSA_RAW ++ | SC_ALGORITHM_RSA_PAD_NONE; ++ break; ++ case 0x06 : ++ passed->new_flags |= SC_ALGORITHM_RSA_HASH_SHA1; ++ break; ++ case 0x1041: ++ passed->ec_flags |= SC_ALGORITHM_ECDSA_RAW; ++ /* no old_ec_flags */ ++ /* TODO turn on sizes from ec curves OIDS */ ++ break; ++ default: ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "UNKNOWN MECH: 0x%8.8x", sa->mechanism); ++ } ++ ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", ++ passed->new_flags, passed->ec_flags); ++ } ++ ++ if (passed->new_flags == 0) { ++ if (p15card->tokeninfo && p15card->tokeninfo->flags & SC_PKCS15_TOKEN_EID_COMPLIANT) { ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EID_COMPLIANT flag found"); ++ passed->new_flags = (passed->used_flags & ~SC_ALGORITHM_SPECIFIC_FLAGS) | SC_ALGORITHM_RSA_PAD_PKCS1; ++ } else ++ passed->new_flags = passed->used_flags; /* from default cardos_init */ ++ } ++ } ++ ++ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Final New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", passed->new_flags, passed->ec_flags); ++ ++ passed->pass = 2; /* tell card driver to use the new flags */ ++ r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed); ++ ++ free(passed); ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ ++static int ++cardos_pkcs15emu_detect_card(sc_pkcs15_card_t *p15card) ++{ ++ if (p15card->card->type < SC_CARD_TYPE_CARDOS_BASE) ++ return SC_ERROR_WRONG_CARD; ++ ++ if (p15card->card->type >= SC_CARD_TYPE_CARDOS_BASE + 1000) ++ return SC_ERROR_WRONG_CARD; ++ ++ return SC_SUCCESS; ++} ++ ++ ++static int ++sc_pkcs15emu_cardos_init(struct sc_pkcs15_card *p15card, struct sc_aid *aid) ++{ ++ sc_card_t *card = p15card->card; ++ int r; ++ ++ LOG_FUNC_CALLED(card->ctx); ++ ++ r = sc_pkcs15_bind_internal(p15card, aid); ++ LOG_TEST_RET(card->ctx, r, "sc_pkcs15_bind_internal failed"); ++ ++ /* If card has created algorithms, return */ ++ sc_log(card->ctx, " card->algorithms:%p card->algorithm_count:%d", card->algorithms, card->algorithm_count); ++ if (!card->algorithms && card->algorithm_count == 0) { ++ r = cardos_fix_token_info(p15card); ++ } ++ ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ ++ ++int ++sc_pkcs15emu_cardos_init_ex(struct sc_pkcs15_card *p15card, struct sc_aid *aid) ++{ ++ if (cardos_pkcs15emu_detect_card(p15card)) ++ return SC_ERROR_WRONG_CARD; ++ ++ return sc_pkcs15emu_cardos_init(p15card, aid); ++} +diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c +index aba6f52c0e..ecd06b13c6 100644 +--- a/src/libopensc/pkcs15-syn.c ++++ b/src/libopensc/pkcs15-syn.c +@@ -60,6 +60,7 @@ struct sc_pkcs15_emulator_handler builtin_emulators[] = { + { "coolkey", sc_pkcs15emu_coolkey_init_ex }, + { "din66291", sc_pkcs15emu_din_66291_init_ex }, + { "esteid2018", sc_pkcs15emu_esteid2018_init_ex }, ++ { "cardos", sc_pkcs15emu_cardos_init_ex }, + + { NULL, NULL } + }; +@@ -95,6 +96,8 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card) + case SC_CARD_TYPE_PIV_II_NEO: + case SC_CARD_TYPE_PIV_II_YUBIKEY4: + case SC_CARD_TYPE_ESTEID_2018: ++ case SC_CARD_TYPE_CARDOS_V5_0: ++ case SC_CARD_TYPE_CARDOS_V5_3: + + return 1; + default: +diff --git a/src/libopensc/pkcs15-syn.h b/src/libopensc/pkcs15-syn.h +index ccaf693ca4..a15e0d95cf 100644 +--- a/src/libopensc/pkcs15-syn.h ++++ b/src/libopensc/pkcs15-syn.h +@@ -54,6 +54,7 @@ int sc_pkcs15emu_jpki_init_ex(sc_pkcs15_card_t *, struct sc_aid *); + int sc_pkcs15emu_coolkey_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); + int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); + int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); ++int sc_pkcs15emu_cardos_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); + + struct sc_pkcs15_emulator_handler { + const char *name; + diff --git a/opensc-0.20.0-file-cache.patch b/opensc-0.20.0-file-cache.patch new file mode 100644 index 0000000..9dfce70 --- /dev/null +++ b/opensc-0.20.0-file-cache.patch @@ -0,0 +1,85 @@ +From 2a28dcd3f6e4af7a5b2d7d7810b26b6321dd1bf1 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 10 Nov 2020 14:44:43 +0100 +Subject: [PATCH 1/3] ctx: Use more standard cache directory + +https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html +--- + src/libopensc/ctx.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c +index 6b57170f01..d6058c070e 100644 +--- a/src/libopensc/ctx.c ++++ b/src/libopensc/ctx.c +@@ -1008,7 +1008,12 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize) + } + + #ifndef _WIN32 +- cache_dir = ".eid/cache"; ++ cache_dir = getenv("XDG_CACHE_HOME"); ++ if (cache_dir != NULL && cache_dir[0] != '\0') { ++ snprintf(buf, bufsize, "%s/%s", cache_dir, "opensc"); ++ return SC_SUCCESS; ++ } ++ cache_dir = ".cache/opensc"; + homedir = getenv("HOME"); + #else + cache_dir = "eid-cache"; +@@ -1020,7 +1025,7 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize) + homedir = temp_path; + } + #endif +- if (homedir == NULL) ++ if (homedir == NULL || homedir[0] == '\0') + return SC_ERROR_INTERNAL; + if (snprintf(buf, bufsize, "%s/%s", homedir, cache_dir) < 0) + return SC_ERROR_BUFFER_TOO_SMALL; + +From 7c1c6f6be47f55693647827259edcacc98761371 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 10 Nov 2020 15:07:42 +0100 +Subject: [PATCH 3/3] doc: Update documentation about the cache location + +--- + doc/files/opensc.conf.5.xml.in | 9 +++++++-- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/doc/files/opensc.conf.5.xml.in b/doc/files/opensc.conf.5.xml.in +index 118922a877..791f11669a 100644 +--- a/doc/files/opensc.conf.5.xml.in ++++ b/doc/files/opensc.conf.5.xml.in +@@ -1116,12 +1116,17 @@ app application { + + + +- HOME/.eid/cache/ (Unix) ++ $XDG_CACHE_HOME/opensc/ (If $XDG_CACHE_HOME is defined) + + + + +- USERPROFILE\.eid-cache\ (Windows) ++ $HOME/.cache/opensc/ (Unix) ++ ++ ++ ++ ++ $USERPROFILE\.eid-cache\ (Windows) + + + + +diff -up opensc-0.20.0/etc/opensc.conf.file-cache opensc-0.20.0/etc/opensc.conf +--- opensc-0.20.0/etc/opensc.conf.file-cache 2020-11-20 16:49:30.995526825 +0100 ++++ opensc-0.20.0/etc/opensc.conf 2020-11-20 16:50:07.665053280 +0100 +@@ -2,7 +2,7 @@ app default { + # debug = 3; + # debug_file = opensc-debug.txt; + framework pkcs15 { +- # use_file_caching = true; ++ use_file_caching = true; + } + reader_driver pcsc { + # The pinpad is disabled by default, + diff --git a/opensc-0.20.0-label-padding.patch b/opensc-0.20.0-label-padding.patch new file mode 100644 index 0000000..4cf26b8 --- /dev/null +++ b/opensc-0.20.0-label-padding.patch @@ -0,0 +1,24 @@ +commit 8d4af9eb0b799f22b25783e8e1b7af329b5a917b +Author: Frank Morgner +Date: Fri Jan 31 12:15:53 2020 +0100 + + pkcs11: fixed right padding of token label with ' ' + + fixes https://github.com/OpenSC/OpenSC/issues/1922 + +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index e94eeeff..a1951c2e 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -1122,9 +1122,10 @@ pkcs15_init_slot(struct sc_pkcs15_card *p15card, struct sc_pkcs11_slot *slot, + max_tokeninfo_len); + slot->token_info.label[max_tokeninfo_len] = ' '; + slot->token_info.label[max_tokeninfo_len+1] = '('; +- slot->token_info.label[max_tokeninfo_len+2+pin_len] = ')'; + strcpy_bp(slot->token_info.label+max_tokeninfo_len+2, + auth->label, pin_len); ++ strcpy_bp(slot->token_info.label+max_tokeninfo_len+2+pin_len, ++ ")", 32 - max_tokeninfo_len-2-pin_len); + } + } else { + /* PIN label is empty or just says non-useful "PIN", diff --git a/opensc.module b/opensc.module new file mode 100644 index 0000000..2071097 --- /dev/null +++ b/opensc.module @@ -0,0 +1,8 @@ +# This file describes how to load the opensc module +# See: http://p11-glue.freedesktop.org/doc/p11-kit/config.html + +# This is a relative path, which means it will be loaded from +# the p11-kit default path which is usually $(libdir)/pkcs11. +# Doing it this way allows for packagers to package opensc for +# 32-bit and 64-bit and make them parallel installable +module: opensc-pkcs11.so diff --git a/opensc.spec b/opensc.spec new file mode 100644 index 0000000..e7a2759 --- /dev/null +++ b/opensc.spec @@ -0,0 +1,716 @@ +%define opensc_module "OpenSC PKCS #11 Module" +%define nssdb %{_sysconfdir}/pki/nssdb + +Name: opensc +Version: 0.20.0 +Release: 4%{?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/releases/download/%{version}/%{name}-%{version}.tar.gz +Source1: opensc.module +Patch6: opensc-0.19.0-pinpad.patch +# https://github.com/OpenSC/OpenSC/pull/1772 +Patch8: opensc-0.19.0-idprime.patch +# https://github.com/OpenSC/OpenSC/pull/1987 +Patch9: opensc-0.20.0-cardos.patch +# https://github.com/OpenSC/OpenSC/pull/2129 +Patch10: opensc-0.20.0-cac-pin-change.patch +# https://github.com/OpenSC/OpenSC/commit/6903aebf +Patch11: opensc-0.20.0-CVE-2020-26570.patch +# https://github.com/OpenSC/OpenSC/commit/ed55fcd2 +Patch12: opensc-0.20.0-CVE-2020-26571.patch +# https://github.com/OpenSC/OpenSC/commit/9d294de9 +Patch13: opensc-0.20.0-CVE-2020-26572.patch +# https://github.com/OpenSC/OpenSC/commit/8d4af9eb +Patch14: opensc-0.20.0-label-padding.patch +# https://github.com/OpenSC/OpenSC/commit/f1bcadfb +# https://github.com/OpenSC/OpenSC/pull/2166 +Patch15: opensc-0.20.0-calloc0.patch +# https://github.com/OpenSC/OpenSC/pull/2148 +# + configuration change by default +Patch16: opensc-0.20.0-file-cache.patch + + +BuildRequires: pcsc-lite-devel +BuildRequires: readline-devel +BuildRequires: openssl-devel +BuildRequires: /usr/bin/xsltproc +BuildRequires: docbook-style-xsl +BuildRequires: autoconf automake libtool gcc +BuildRequires: desktop-file-utils +BuildRequires: bash-completion +BuildRequires: zlib-devel +Requires: pcsc-lite-libs%{?_isa} +Requires: pcsc-lite +Obsoletes: mozilla-opensc-signer < 0.12.0 +Obsoletes: opensc-devel < 0.12.0 +Obsoletes: coolkey <= 1.1.0-36 + +%description +OpenSC provides a set of libraries and utilities to work with smart cards. Its +main focus is on cards that support cryptographic operations, and facilitate +their use in security applications such as authentication, mail encryption and +digital signatures. OpenSC implements the PKCS#11 API so applications +supporting this API (such as Mozilla Firefox and Thunderbird) can use it. On +the card OpenSC implements the PKCS#15 standard and aims to be compatible with +every software/card that does so, too. + + +%prep +%setup -q +%patch6 -p1 -b .pinpad +%patch8 -p1 -b .idprime +%patch9 -p1 -b .cardos +%patch10 -p1 -b .cac-pin-change +%patch11 -p1 -b .CVE-2020-26570 +%patch12 -p1 -b .CVE-2020-26571 +%patch13 -p1 -b .CVE-2020-26572 +%patch14 -p1 -b .padding +%patch15 -p1 -b .calloc0 +%patch16 -p1 -b .file-cache + +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.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-autostart-items \ + --disable-assert \ + --enable-pcsc \ + --disable-tests \ + --enable-sm \ + --with-pcsc-provider=libpcsclite.so.1 +make %{?_smp_mflags} V=1 + + +%install +make install DESTDIR=$RPM_BUILD_ROOT +install -Dpm 644 %{SOURCE1} $RPM_BUILD_ROOT%{_datadir}/p11-kit/modules/opensc.module + +%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 + +rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/opensc + +# Upstream considers libopensc API internal and no longer ships +# public headers and pkgconfig files. +# 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 +%if 0%{?rhel} && 0%{?rhel} < 7 +rm -rf %{buildroot}%{_datadir}/bash-completion/ +%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* + +# We use p11-kit for pkcs11 modules registration +rm -rf %{buildroot}%{_bindir}/pkcs11-register +# It is even missing the manual page +#rm -rf %{buildroot}%{_mandir}/man1/pkcs11-register.1* + +desktop-file-validate %{buildroot}/%{_datadir}/applications/org.opensc.notify.desktop + +%post +/sbin/ldconfig +# Remove our PKCS#11 module from NSS DB, if there is NSS installed, because +# it is already loaded by p11-kit-proxy. Using both of them can cause +# race conditions and hard-to-debug problems +# TODO Remove with F30 or so +if [ -x /usr/bin/modutil ]; then + isThere=`modutil -rawlist -dbdir %{nssdb} | grep %{opensc_module} || echo NO` + if [ ! "$isThere" == "NO" ]; then + modutil -delete %{opensc_module} -dbdir %{nssdb} -force || : + + fi + isThere=`modutil -rawlist -dbdir sql:%{nssdb} | grep %{opensc_module} || echo NO` + if [ ! "$isThere" == "NO" ]; then + modutil -delete %{opensc_module} -dbdir sql:%{nssdb} -force || : + fi +fi + +%postun +/sbin/ldconfig + +%files +%doc COPYING NEWS README* + +%if ! 0%{?rhel} || 0%{?rhel} >= 7 +%{_datadir}/bash-completion/* +%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 +%{_bindir}/cryptoflex-tool +%{_bindir}/eidenv +%{_bindir}/iasecc-tool +%{_bindir}/gids-tool +%{_bindir}/netkey-tool +%{_bindir}/openpgp-tool +%{_bindir}/opensc-explorer +%{_bindir}/opensc-tool +%{_bindir}/opensc-asn1 +%{_bindir}/opensc-notify +%{_bindir}/piv-tool +%{_bindir}/pkcs11-tool +%{_bindir}/pkcs15-crypt +%{_bindir}/pkcs15-init +%{_bindir}/pkcs15-tool +%{_bindir}/sc-hsm-tool +%{_bindir}/dnie-tool +%{_bindir}/westcos-tool +%{_bindir}/egk-tool +%{_datadir}/applications/org.opensc.notify.desktop +%{_bindir}/goid-tool +%{_libdir}/lib*.so.* +%{_libdir}/opensc-pkcs11.so +%{_libdir}/pkcs11-spy.so +%{_libdir}/onepin-opensc-pkcs11.so +%{_libdir}/pkgconfig/*.pc +%%dir %{_libdir}/pkcs11 +%{_libdir}/pkcs11/opensc-pkcs11.so +%{_libdir}/pkcs11/onepin-opensc-pkcs11.so +%{_libdir}/pkcs11/pkcs11-spy.so +%{_datadir}/opensc/ +%{_mandir}/man1/cardos-tool.1* +%{_mandir}/man1/cryptoflex-tool.1* +%{_mandir}/man1/eidenv.1* +%{_mandir}/man1/gids-tool.1* +%{_mandir}/man1/iasecc-tool.1* +%{_mandir}/man1/netkey-tool.1* +%{_mandir}/man1/openpgp-tool.1* +%{_mandir}/man1/opensc-explorer.* +%{_mandir}/man1/opensc-tool.1* +%{_mandir}/man1/opensc-asn1.1* +%{_mandir}/man1/opensc-notify.1* +%{_mandir}/man1/piv-tool.1* +%{_mandir}/man1/pkcs11-tool.1* +%{_mandir}/man1/pkcs15-crypt.1* +%{_mandir}/man1/pkcs15-init.1* +%{_mandir}/man1/pkcs15-tool.1* +%{_mandir}/man1/sc-hsm-tool.1* +%{_mandir}/man1/westcos-tool.1* +%{_mandir}/man1/dnie-tool.1* +%{_mandir}/man1/egk-tool.1* +%{_mandir}/man5/pkcs15-profile.5* + + +%changelog +* Fri Nov 20 2020 Jakub Jelen - 0.20.0-4 +- Use file cache by default (#1892810) +- Avoid calloc with 0 argument (#1895401) + +* Tue Oct 20 2020 Jakub Jelen - 0.20.0-3 +- Support PIN change for HID Alt tokens (#1830901) +- Fix CVE-2020-26570, CVE-2020-26571 and CVE-2020-26572 +- Fix right padding of token labels of some cards (#1877973) + +* Wed May 27 2020 Jakub Jelen - 0.20.0-2 +- Unbreak different CardOS 5 configurations supporting raw RSA (#1830856) + +* Wed Apr 22 2020 Jakub Jelen - 0.20.0-1 +- Rebase to current upstream release (#1810660) + +* Mon Nov 25 2019 Jakub Jelen - 0.19.0-7 +- Unbreak RSA-PSS mechanisms in -6 release (#1775673) + +* Thu Nov 14 2019 Jakub Jelen - 0.19.0-6 +- Add support for Gemalto IDPrime smart cards (#1657970) +- Fix 2k RSA key operations with Coolkey (#1766712) + +* Thu Apr 18 2019 Jakub Jelen - 0.19.0-5 +- Avoid multilib issues (#1693380) + +* Wed Dec 12 2018 Jakub Jelen - 0.19.0-4 +- Unbreak the Dual CAC cards in PIV driver (#1651748) +- Fix few more corner cases for handling different types of padding (#1595626) +- Unbreak signature verification in pkcs11-tool (#1651748) + +* Wed Oct 31 2018 Jakub Jelen - 0.19.0-3 +- Unbreak the RSA-PSS mechanisms (#1595626) +- Unbreak the signing using hashed mechanisms in CardOS and others (#1644338) + +* Mon Oct 22 2018 Jakub Jelen - 0.19.0-2 +- Avoid mismatching coolkey cards for muscle ones (#1588722) +- Implement legacy CAC1 driver (#1638052) +- Disable pinpad +- Fixup verification after RSA-PSS implementation + +* Tue Sep 25 2018 Jakub Jelen - 0.19.0-1 +- New upstream release fixing various CVE-2018-16418 - 16421, 16423 - 16427 +- Add support for RSA-PSS signatures + +* Fri Jul 13 2018 Fedora Release Engineering - 0.18.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Thu Jul 12 2018 Jakub Jelen - 0.18.0-3 +- Do not add pkcs11 module to NSS after installation + (NSS is loading p11-kit modules by default) +- Remove pkcs11-switch since there is nothing to switch to + +* Mon May 21 2018 Jakub Jelen - 0.18.0-2 +- Backport a fix for C_WaitForSlotEvent crash (#1579933) + +* Thu May 17 2018 Jakub Jelen - 0.18.0-1 +- New upstream release (#1567503) + +* Wed Apr 04 2018 Jakub Jelen - 0.17.0-10 +- Install the PKCS#11 modules also to the new NSS DB +- Drop the pkcs11-switch as the coolkey is gone + +* Tue Apr 03 2018 Jakub Jelen - 0.17.0-9 +- Improved support for CloudHSM (#1562572) + +* Mon Mar 19 2018 Jakub Jelen - 0.17.0-8 +- Build requires gcc +- Backport a fix for feitian tokens (#1558099) + +* Fri Mar 02 2018 Jakub Jelen - 0.17.0-7 +- Obsolete coolkey +- Do not report bogus errors from pkcs11-switch +- Do not delete nonexisting modules during uninstall (#1526670) + +* Wed Feb 21 2018 Jakub Jelen - 0.17.0-6 +- PIV: Use Cardholder name in the token label +- Avoid infinite loop when reading CAC cards +- Properly parse multi-byte length in SimpleTLV +- Support CAC Alt tokens + +* Thu Feb 08 2018 Fedora Release Engineering - 0.17.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Mon Dec 04 2017 Jakub Jelen - 0.17.0-4 +- Allow functionality of a new Estonia ID cards (#1519751) + +* Thu Aug 03 2017 Fedora Release Engineering - 0.17.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 0.17.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Jul 19 2017 Jakub Jelen - 0.17.0-1 +- New upstream release including support for Coolkey and CAC cards + +* Tue Feb 28 2017 Jakub Jelen - 0.16.0-5.20161016git0362439 +- Add PKCS#11 library to the NSS DB (#1421692) + +* Sat Feb 11 2017 Fedora Release Engineering - 0.16.0-4.20161016git0362439 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Jan 12 2017 Igor Gnatenko - 0.16.0-3.20161016git0362439 +- Rebuild for readline 7.x + +* Mon Oct 31 2016 Jakub Jelen - 0.16.0-2.20161016git0362439 +- Updated to latest git to address openssl 1.1.0 compilation issues (#1388895) +- Do not own /etc/bash_completion.d directory (#1303441) + +* Tue Aug 02 2016 Jakub Jelen - 0.16.0-1 +- New upstream release 0.16.0 (#1306071) + +* Tue Jul 12 2016 Jakub Jelen - 0.15.0-6 +- Add support for 2048 key length (#1350588) +- Explicitly set CKA_PRIVATE to false when writing certificates (#1272127) + +* Thu Feb 04 2016 Fedora Release Engineering - 0.15.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Mon Jan 18 2016 Nikos Mavrogiannopoulos - 0.15.0-4 +- Fix a crash in accessing public key (#1298669) + +* Thu Nov 19 2015 Nikos Mavrogiannopoulos - 0.15.0-3 +- Export PKCS#11 symbols from spy library (#1283306) + +* Tue Aug 4 2015 Nikos Mavrogiannopoulos - 0.15.0-2 +- Updated fix for issue with C_Initialize after fork() (#1218797) + +* Tue Jul 14 2015 Nikos Mavrogiannopoulos - 0.15.0-1 +- Update to 0.15.0 (#1209682) +- Solve issue with C_Initialize after fork() (#1218797) + +* Thu Jun 18 2015 Fedora Release Engineering - 0.14.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Sun Aug 17 2014 Fedora Release Engineering - 0.14.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Tue Jul 01 2014 Nikos Mavrogiannopoulos - 0.14.0-1 +- new upstream version + +* Sat Jun 07 2014 Fedora Release Engineering - 0.13.0-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Fri Feb 28 2014 Nikos Mavrogiannopoulos - 0.13.0-12 +- Added fix for crash when calling pkcs11-tool with an invalid module (#1071368) +- Added fix for invalid parameters passed to module by pkcs11-tool + when importing a private key (#1071369) +- Configuration file opensc.conf was renamed to opensc-arch.conf to + avoid multi-arch issues. + +* Fri Jan 31 2014 Nikos Mavrogiannopoulos - 0.13.0-11 +- Corrected installation path of opensc.module (#1060053) + +* Mon Jan 06 2014 Nikos Mavrogiannopoulos - 0.13.0-10 +- Applied myeid related patch (#1048576) + +* Thu Jan 02 2014 Nikos Mavrogiannopoulos - 0.13.0-9 +- Applied epass2003 related patch (#981462) + +* Mon Dec 23 2013 Nikos Mavrogiannopoulos - 0.13.0-8 +- Compile using the --enable-sm option (related but does not fix #981462) + +* Wed Dec 18 2013 Nikos Mavrogiannopoulos - 0.13.0-7 +- Ensure that pcsc-lite is depended on (#1029133) + +* Mon Sep 23 2013 Stef Walter - 0.13.0-6 +- Install p11-kit config file to the right place (#999190) + +* Sat Aug 03 2013 Fedora Release Engineering - 0.13.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Fri Mar 08 2013 Stef Walter - 0.13.0-4 +- Use the standard name format for p11-kit module configs +- Put the p11-kit module config is the system location + +* Thu Feb 14 2013 Fedora Release Engineering - 0.13.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Sun Jan 13 2013 Kalev Lember - 0.13.0-2 +- Backport an upstream patch for fixing pkcs15 cert length calculation + +* Thu Jan 03 2013 Milan Broz - 0.13.0-1 +- Update to 0.13.0 (#890770) +- Remove no longer provided onepin-opensc-pkcs11.so. +- Add iasecc-tool, openpgp-tool and sc-hsm-tool. + +* Fri Jul 27 2012 Tomas Mraz - 0.12.2-6 +- Add a configuration file for p11-kit (#840504) + +* Fri Jul 20 2012 Fedora Release Engineering - 0.12.2-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Sun Mar 4 2012 Peter Robinson - 0.12.2-4 +- Add patch for dso + +* Fri Jan 13 2012 Fedora Release Engineering - 0.12.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Aug 17 2011 Tomas Mraz - 0.12.2-2 +- Rebuilt to fix trailing slashes in filelist from rpmbuild bug + +* Tue Jul 19 2011 Kalev Lember - 0.12.2-1 +- Update to 0.12.2 (#722659) + +* Wed May 18 2011 Kalev Lember - 0.12.1-1 +- Update to 0.12.1 (#705743) +- Removed BR libtool-ltdl-devel to build with glibc's libdl instead + +* Tue Apr 12 2011 Tomas Mraz - 0.12.0-4 +- drop multilib conflicting and duplicated doc file (#695368) + +* Tue Feb 08 2011 Fedora Release Engineering - 0.12.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Jan 03 2011 Kalev Lember - 0.12.0-2 +- Disabled asserts + +* Mon Jan 03 2011 Kalev Lember - 0.12.0-1 +- Update to 0.12.0 +- Removed and obsoleted mozilla-opensc-signer and opensc-devel subpackages +- Dropped patches which are now upstreamed +- It is no longer possible to build in both pcsc-lite and openct support, + so opensc now gets built exclusively with pcsc-lite. + +* Tue Dec 21 2010 Tomas Mraz - 0.11.13-6 +- fix buffer overflow on rogue card serial numbers + +* Tue Oct 19 2010 Tomas Mraz - 0.11.13-5 +- own the _libdir/pkcs11 subdirectory (#644527) + +* Tue Sep 7 2010 Tomas Mraz - 0.11.13-4 +- fix build with new pcsc-lite + +* Wed Aug 11 2010 Rex Dieter - 0.11.13-3 +- build against libassuan1 (f14+) + +* Wed Jun 9 2010 Tomas Mraz - 0.11.13-2 +- replace file dependency (#601943) + +* Tue Feb 16 2010 Kalev Lember - 0.11.13-1 +- new upstream version + +* Sun Feb 14 2010 Kalev Lember - 0.11.12-2 +- Added patch to fix linking with the new --no-add-needed default (#564758) + +* Mon Dec 21 2009 Kalev Lember - 0.11.12-1 +- new upstream version +- replaced %%define with %%global +- BR clean up from items not applicable to current Fedora releases + +* Tue Dec 8 2009 Michael Schwendt - 0.11.11-2 +- Explicitly BR libassuan-static in accordance with the Packaging + Guidelines (libassuan-devel is still static-only). + +* Thu Nov 19 2009 Tomas Mraz - 0.11.11-1 +- new upstream version + +* Tue Sep 29 2009 Tomas Mraz - 0.11.9-2 +- fix multilib conflict in the configuration file (#526269) + +* Wed Sep 09 2009 Tomas Mraz - 0.11.9-1 +- new upstream version + +* Fri Aug 21 2009 Tomas Mraz - 0.11.8-5 +- rebuilt with new openssl + +* Mon Jul 27 2009 Tomas Mraz - 0.11.8-4 +- Depend on specific arch of pcsc-lite-libs (reported by Kalev Lember) + +* Sat Jul 25 2009 Fedora Release Engineering - 0.11.8-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Mon Jun 15 2009 Tomas Mraz - 0.11.8-2 +- Rebuilt with new openct + +* Mon May 11 2009 Tomas Mraz - 0.11.8-1 +- new upstream version - fixes security issue + +* Fri Feb 27 2009 Tomas Mraz - 0.11.7-1 +- new upstream version - fixes CVE-2009-0368 + +* Thu Feb 26 2009 Fedora Release Engineering - 0.11.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Thu Jan 15 2009 Tomas Mraz - 0.11.6-2 +- Add explicit requires for pcsc-lite-libs. Dlopen libpcsclite with the full + soname. + +* Tue Sep 2 2008 Tomas Mraz - 0.11.6-1 +- Update to latest upstream, fixes CVE-2008-2235 + +* Thu Apr 10 2008 Hans de Goede - 0.11.4-5 +- BuildRequire libassuan-devel instead of libassuan-static (bz 441812) + +* Tue Feb 19 2008 Fedora Release Engineering - 0.11.4-4 +- Autorebuild for GCC 4.3 + +* Wed Dec 05 2007 Release Engineering - 0.11.4-3 + - Rebuild for deps + +* Wed Dec 5 2007 Ville Skyttä - 0.11.4-2 +- Rebuild. + +* Mon Sep 10 2007 Ville Skyttä - 0.11.4-1 +- 0.11.4. + +* Mon Aug 20 2007 Ville Skyttä - 0.11.4-0.1.rc1 +- 0.11.4-rc1, pkcs11-tool usage message fix applied upstream. +- License: LGPLv2+ + +* Thu Jul 26 2007 Ville Skyttä - 0.11.3-2 +- Fix pkcs11-tool usage message crash (#249702). + +* Tue Jul 17 2007 Ville Skyttä - 0.11.3-1 +- 0.11.3. + +* Sat Jun 30 2007 Ville Skyttä - 0.11.3-0.1.pre2 +- 0.11.3-pre2. + +* Thu Jun 21 2007 Ville Skyttä - 0.11.3-0.1.pre1 +- 0.11.3-pre1. + +* Sun May 6 2007 Ville Skyttä - 0.11.2-2 +- Add explicit build dependency on ncurses-devel. + +* Sat May 5 2007 Ville Skyttä - 0.11.2-1 +- 0.11.2. + +* Tue Apr 24 2007 Ville Skyttä - 0.11.2-0.3.rc2 +- 0.11.2-rc2. + +* Fri Mar 23 2007 Ville Skyttä - 0.11.2-0.3.rc1 +- 0.11.2-rc1. + +* Thu Mar 15 2007 Ville Skyttä - 0.11.2-0.2.pre6 +- 0.11.2-pre6. + +* Tue Mar 6 2007 Ville Skyttä - 0.11.2-0.2.pre4 +- 0.11.2-pre4. +- Require pinentry-gui instead of the pinentry executable in signer. + +* Sun Dec 3 2006 Ville Skyttä - 0.11.2-0.1.pre3 +- 0.11.2-pre3. +- Build with new libassuan. +- Don't run autotools during build. +- Adjust to readline/termcap/ncurses changes. + +* Sat Oct 14 2006 Ville Skyttä - 0.11.1-6 +- Rebuild with new libassuan. + +* Sun Oct 8 2006 Ville Skyttä - 0.11.1-5 +- Rebuild with new libassuan. + +* Mon Oct 2 2006 Ville Skyttä - 0.11.1-4 +- Rebuild. + +* Tue Sep 26 2006 Ville Skyttä - 0.11.1-3 +- Rebuild with new libassuan. + +* Sat Sep 2 2006 Ville Skyttä - 0.11.1-2 +- Rebuild. + +* Wed May 31 2006 Ville Skyttä - 0.11.1-1 +- 0.11.1. +- Avoid some multilib conflicts. + +* Sun May 7 2006 Ville Skyttä - 0.11.0-2 +- Sync example paths in openct.conf with ctapi-common. +- Update URL. + +* Thu May 4 2006 Ville Skyttä - 0.11.0-1 +- 0.11.0. + +* Thu Apr 27 2006 Ville Skyttä - 0.11.0-0.1.rc2 +- 0.11.0-rc2. + +* Sat Apr 22 2006 Ville Skyttä - 0.11.0-0.1.rc1 +- 0.11.0-rc1. + +* Mon Mar 6 2006 Ville Skyttä - 0.10.1-3 +- Rebuild. + +* Wed Feb 15 2006 Ville Skyttä - 0.10.1-2 +- Avoid standard rpaths on lib64 archs. + +* Sun Jan 8 2006 Ville Skyttä - 0.10.1-1 +- 0.10.1. + +* Wed Nov 9 2005 Ville Skyttä - 0.10.0-1 +- 0.10.0. +- Adapt to modularized X.Org. + +* Wed Oct 26 2005 Ville Skyttä - 0.10.0-0.1.rc2 +- 0.10.0-rc2. +- Install signer plugin only to plugin dir. + +* Sat Oct 22 2005 Ville Skyttä - 0.10.0-0.1.rc1 +- 0.10.0-rc1. + +* Wed Oct 19 2005 Ville Skyttä - 0.10.0-0.1.beta2.rc1 +- 0.10.0-beta2-rc1. +- Specfile cleanups. + +* Tue Apr 26 2005 Ville Skyttä - 0.9.6-2 +- 0.9.6, build patch applied upstream. +- Package summary and description improvements. +- Drop explicit openct dependency. + +* Fri Mar 18 2005 Ville Skyttä - 0.9.4-3 +- Fix FC4 build. +- Rename opensc-pam to pam_opensc per package naming guidelines. + +* Wed Feb 9 2005 Michael Schwendt - 0.9.4-2 +- Substitute hardcoded 'lib' in OpenSSL checks for multi-lib platforms. +- Use --with-plugin-dir instead of --with-plugin-path (fixes x86_64). + +* Thu Feb 3 2005 Ville Skyttä - 0.9.4-1 +- Drop unnecessary Epochs, pre-FC1 compat cruft, and no longer relevant + --with(out) rpmbuild options. +- Exclude *.la. + +* Wed Nov 3 2004 Ville Skyttä - 0:0.9.4-0.fdr.1 +- Update to 0.9.4, parallel build patch applied upstream. +- Patch to fix library paths and LDFLAGS. +- Don't require mozilla, but the plugin dir in signer. +- Build with dependency tracking disabled. + +* Tue Jul 27 2004 Ville Skyttä - 0:0.9.2-0.fdr.2 +- Building the signer plugin can be disabled with "--without signer". + Thanks to Fritz Elfert for the idea. +- Update description. + +* Sun Jul 25 2004 Ville Skyttä - 0:0.9.2-0.fdr.1 +- Update to 0.9.2, old patches applied upstream. +- Add patch to fix parallel builds. +- Convert man pages to UTF-8. + +* Thu Jul 22 2004 Ville Skyttä - 0:0.9.1-0.fdr.1 +- Update to 0.9.1 (preview). + +* Thu Jul 1 2004 Ville Skyttä - 0:0.9.0-0.fdr.0.1.alpha +- Update to 0.9.0-alpha. + +* Sat May 1 2004 Ville Skyttä - 0:0.8.1-0.fdr.8 +- Rebuild with libassuan 0.6.5. + +* Sat Jan 31 2004 Ville Skyttä - 0:0.8.1-0.fdr.7 +- Rebuild with libassuan 0.6.3. +- Add gdm example to PAM quickstart. + +* Mon Jan 19 2004 Ville Skyttä - 0:0.8.1-0.fdr.6 +- Use /%%{_lib} instead of hardcoding /lib. + +* Sat Dec 20 2003 Ville Skyttä - 0:0.8.1-0.fdr.5 +- Split PAM support into a subpackage. +- Rebuild with libassuan 0.6.2. + +* Sun Nov 23 2003 Ville Skyttä - 0:0.8.1-0.fdr.4 +- Rebuild with libassuan 0.6.1. +- Include PAM quickstart doc snippet. + +* Fri Nov 14 2003 Ville Skyttä - 0:0.8.1-0.fdr.3 +- Require OpenCT. + +* Fri Oct 17 2003 Ville Skyttä - 0:0.8.1-0.fdr.2 +- Install example config files as documentation. + +* Tue Oct 14 2003 Ville Skyttä - 0:0.8.1-0.fdr.1 +- Update to 0.8.1. + +* Wed Aug 27 2003 Ville Skyttä - 0:0.8.0-0.fdr.2 +- Signer can be built with oldssl too. + +* Wed Aug 27 2003 Ville Skyttä - 0:0.8.0-0.fdr.1 +- Update to 0.8.0. + +* Wed Jul 30 2003 Ville Skyttä - 0:0.8.0-0.fdr.0.2.cvs20030730 +- Update to 20030730. +- Clean up %%docs. +- Include *.la (uses ltdl). +- Own the %%{_libdir}/pkcs11 directory. +- Disable signer; assuan has disappeared from the tarball :( + +* Fri May 23 2003 Ville Skyttä - 0:0.8.0-0.fdr.0.1.rc1 +- First build. diff --git a/sources b/sources new file mode 100644 index 0000000..ac12c19 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (opensc-0.20.0.tar.gz) = 71f71fa6062410e63c6c60f5b2d10d1d855cc6cc815ef0e42e42a1ddd25bbd52fc396c1e495ef54610f3243996dec84dacc8007b186deb670ed645b04ee6eda5