From 687b17fc1e5ad0a73ecc82f770fba7dc3e37202b Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 28 2020 09:42:12 +0000 Subject: import opensc-0.19.0-7.el8 --- diff --git a/SOURCES/opensc-0.19.0-coolkey-2k.patch b/SOURCES/opensc-0.19.0-coolkey-2k.patch new file mode 100644 index 0000000..f4567cf --- /dev/null +++ b/SOURCES/opensc-0.19.0-coolkey-2k.patch @@ -0,0 +1,48 @@ +From 6c1b9094a6060d9d838bac9ea4f7c4c9e755c4ae Mon Sep 17 00:00:00 2001 +From: Steve Ross +Date: Wed, 14 Nov 2018 11:59:43 -0600 +Subject: [PATCH] Enable CoolKey driver to handle 2048-bit keys. + +For a problem description, see . +In a nutshell, for a card with the CoolKey applet and 2048-bit keys, +the command + pkcs11-tool --test --login +fails to complete all of its tests. + +This commit consists of a patch from @dengert. + +To avoid triggering an error when the data exceeds 255 bytes, this commit +limits the amount of the payload sent to the CoolKey applet on the card based +on the maximum amount of data that the card can receive, and overhead bytes +(namely, a header and nonce) that accompany the payload. + +With this change, the command + pkcs11-tool --test --login +succeeds. +--- + src/libopensc/card-coolkey.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c +index e320290dfe..11c4e92643 100644 +--- a/src/libopensc/card-coolkey.c ++++ b/src/libopensc/card-coolkey.c +@@ -1168,12 +1168,16 @@ static int coolkey_write_object(sc_card_t *card, unsigned long object_id, + size_t operation_len; + size_t left = buf_len; + int r; ++ size_t max_operation_len; ++ ++ /* set limit for the card's maximum send size and short write */ ++ max_operation_len = MIN(COOLKEY_MAX_CHUNK_SIZE, (card->max_send_size - sizeof(coolkey_read_object_param_t) - nonce_size)); + + ulong2bebytes(¶ms.head.object_id[0], object_id); + + do { + ulong2bebytes(¶ms.head.offset[0], offset); +- operation_len = MIN(left, COOLKEY_MAX_CHUNK_SIZE); ++ operation_len = MIN(left, max_operation_len); + params.head.length = operation_len; + memcpy(params.buf, buf, operation_len); + r = coolkey_apdu_io(card, COOLKEY_CLASS, COOLKEY_INS_WRITE_OBJECT, 0, 0, + diff --git a/SOURCES/opensc-0.19.0-idprime.patch b/SOURCES/opensc-0.19.0-idprime.patch new file mode 100644 index 0000000..dfc460d --- /dev/null +++ b/SOURCES/opensc-0.19.0-idprime.patch @@ -0,0 +1,1674 @@ +diff -up opensc-0.19.0/src/libopensc/card-cac1.c.idprime opensc-0.19.0/src/libopensc/card-cac1.c +--- opensc-0.19.0/src/libopensc/card-cac1.c.idprime 2019-11-14 09:42:03.557198986 +0100 ++++ opensc-0.19.0/src/libopensc/card-cac1.c 2019-11-14 09:42:03.563199045 +0100 +@@ -59,6 +59,7 @@ + #endif + #include "iso7816.h" + #include "card-cac-common.h" ++#include "pkcs15.h" + + /* + * CAC hardware and APDU constants +diff -up opensc-0.19.0/src/libopensc/card-cac.c.idprime opensc-0.19.0/src/libopensc/card-cac.c +--- opensc-0.19.0/src/libopensc/card-cac.c.idprime 2019-11-14 09:42:03.556198976 +0100 ++++ opensc-0.19.0/src/libopensc/card-cac.c 2019-11-14 09:42:03.563199045 +0100 +@@ -59,6 +59,7 @@ + #endif + #include "iso7816.h" + #include "card-cac-common.h" ++#include "pkcs15.h" + + /* + * CAC hardware and APDU constants +diff -up opensc-0.19.0/src/libopensc/cardctl.h.idprime opensc-0.19.0/src/libopensc/cardctl.h +--- opensc-0.19.0/src/libopensc/cardctl.h.idprime 2018-09-13 13:52:42.000000000 +0200 ++++ opensc-0.19.0/src/libopensc/cardctl.h 2019-11-14 09:42:03.563199045 +0100 +@@ -303,6 +303,16 @@ enum { + SC_CARDCTL_GIDS_INITIALIZE, + SC_CARDCTL_GIDS_SET_ADMIN_KEY, + SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, ++ ++ /* ++ * IDPrime specific calls ++ */ ++ SC_CARDCTL_IDPRIME_BASE = _CTL_PREFIX('I', 'D', 'P'), ++ SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS, ++ SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT, ++ SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, ++ SC_CARDCTL_IDPRIME_GET_TOKEN_NAME, ++ + }; + + enum { +diff -up opensc-0.19.0/src/libopensc/card-idprime.c.idprime opensc-0.19.0/src/libopensc/card-idprime.c +--- opensc-0.19.0/src/libopensc/card-idprime.c.idprime 2019-11-14 09:42:03.563199045 +0100 ++++ opensc-0.19.0/src/libopensc/card-idprime.c 2019-11-14 09:42:03.563199045 +0100 +@@ -0,0 +1,789 @@ ++/* ++ * 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 */ ++ 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) { ++ sc_file_free(file); ++ LOG_FUNC_RETURN(card->ctx, r); ++ } ++ r = file->size; ++ sc_file_free(file); ++ 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; ++ } ++ new_object.fd++; ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found certificate with fd=%d, key_ref=%d", ++ new_object.fd, new_object.key_reference); ++ idprime_add_object_to_list(&priv->pki_list, &new_object); ++ ++ /* 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)); ++ sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found p11/tinfo object"); ++ } ++ } ++ r = SC_SUCCESS; ++done: ++ if (buf) ++ 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; ++ ++ card->name = "Gemalto IDPrime"; ++ 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); ++ } ++ ++ 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 (memcmp(priv->tinfo_df, "\0\0", 2) == 0) { ++ 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); ++ ++ if (priv) { /* don't record anything if we haven't been initialized yet */ ++ /* forget any old cached values */ ++ if (priv->cache_buf) { ++ free(priv->cache_buf); ++ priv->cache_buf = NULL; ++ } ++ priv->cache_buf_len = 0; ++ priv->cached = 0; ++ } ++ 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[4096]; /* needs work. for 3072 keys, needs 384+10 or so */ ++ 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 -up opensc-0.19.0/src/libopensc/cards.h.idprime opensc-0.19.0/src/libopensc/cards.h +--- opensc-0.19.0/src/libopensc/cards.h.idprime 2019-11-14 09:42:03.561199025 +0100 ++++ opensc-0.19.0/src/libopensc/cards.h 2019-11-14 09:45:23.000180086 +0100 +@@ -240,6 +240,7 @@ enum { + /* JPKI cards */ + SC_CARD_TYPE_JPKI_BASE = 31000, + ++ /* Coolkey cards */ + SC_CARD_TYPE_COOLKEY_BASE = 32000, + SC_CARD_TYPE_COOLKEY_GENERIC, + +@@ -253,6 +254,12 @@ enum { + SC_CARD_TYPE_NPA = 34000, + SC_CARD_TYPE_NPA_TEST, + SC_CARD_TYPE_NPA_ONLINE, ++ ++ /* 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); +@@ -296,6 +303,7 @@ extern sc_card_driver_t *sc_get_coolkey_ + 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_idprime_driver(void); + + #ifdef __cplusplus + } +diff -up opensc-0.19.0/src/libopensc/ctx.c.idprime opensc-0.19.0/src/libopensc/ctx.c +--- opensc-0.19.0/src/libopensc/ctx.c.idprime 2019-11-14 09:42:03.564199055 +0100 ++++ opensc-0.19.0/src/libopensc/ctx.c 2019-11-14 09:46:07.142618618 +0100 +@@ -147,6 +147,7 @@ static const struct _sc_driver_entry int + { "jpki", (void *(*)(void)) sc_get_jpki_driver }, + { "npa", (void *(*)(void)) sc_get_npa_driver }, + { "cac1", (void *(*)(void)) sc_get_cac1_driver }, ++ { "idprime", (void *(*)(void)) sc_get_idprime_driver }, + /* The default driver should be last, as it handles all the + * unrecognized cards. */ + { "default", (void *(*)(void)) sc_get_default_driver }, +diff -up opensc-0.19.0/src/libopensc/Makefile.am.idprime opensc-0.19.0/src/libopensc/Makefile.am +--- opensc-0.19.0/src/libopensc/Makefile.am.idprime 2019-11-14 09:42:03.562199036 +0100 ++++ opensc-0.19.0/src/libopensc/Makefile.am 2019-11-14 09:43:42.168178253 +0100 +@@ -48,14 +48,14 @@ libopensc_la_SOURCES_BASE = \ + card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ + card-dnie.c cwa14890.c cwa-dnie.c \ + card-isoApplet.c card-masktech.c card-gids.c card-jpki.c \ +- card-npa.c \ ++ card-npa.c card-idprime.c \ + \ + pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \ + pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \ + pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \ + pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ + pkcs15-oberthur.c pkcs15-itacns.c pkcs15-gemsafeV1.c pkcs15-sc-hsm.c \ +- pkcs15-coolkey.c pkcs15-din-66291.c \ ++ pkcs15-coolkey.c pkcs15-din-66291.c pkcs15-idprime.c \ + pkcs15-dnie.c pkcs15-gids.c pkcs15-iasecc.c pkcs15-jpki.c \ + compression.c p15card-helper.c sm.c \ + aux-data.c +diff -up opensc-0.19.0/src/libopensc/Makefile.mak.idprime opensc-0.19.0/src/libopensc/Makefile.mak +--- opensc-0.19.0/src/libopensc/Makefile.mak.idprime 2019-11-14 09:42:03.563199045 +0100 ++++ opensc-0.19.0/src/libopensc/Makefile.mak 2019-11-14 09:44:42.339776109 +0100 +@@ -27,14 +27,14 @@ OBJECTS = \ + card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \ + card-sc-hsm.obj card-dnie.obj card-isoApplet.obj pkcs15-coolkey.obj \ + card-masktech.obj card-gids.obj card-jpki.obj \ +- card-npa.obj \ ++ card-npa.obj card-idprime.obj \ + \ + pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \ + pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.obj \ + pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \ + pkcs15-cac.obj pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-din-66291.obj \ + pkcs15-oberthur.obj pkcs15-itacns.obj pkcs15-gemsafeV1.obj pkcs15-sc-hsm.obj \ +- pkcs15-dnie.obj pkcs15-gids.obj pkcs15-iasecc.obj pkcs15-jpki.obj \ ++ pkcs15-dnie.obj pkcs15-gids.obj pkcs15-iasecc.obj pkcs15-jpki.obj pkcs15-idprime.obj \ + compression.obj p15card-helper.obj sm.obj \ + aux-data.obj \ + $(TOPDIR)\win32\versioninfo.res +diff -up opensc-0.19.0/src/libopensc/opensc.h.idprime opensc-0.19.0/src/libopensc/opensc.h +--- opensc-0.19.0/src/libopensc/opensc.h.idprime 2019-11-14 09:42:03.524198658 +0100 ++++ opensc-0.19.0/src/libopensc/opensc.h 2019-11-14 09:42:03.564199055 +0100 +@@ -98,12 +98,13 @@ extern "C" { + * 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 -up opensc-0.19.0/src/libopensc/padding.c.idprime opensc-0.19.0/src/libopensc/padding.c +--- opensc-0.19.0/src/libopensc/padding.c.idprime 2019-11-14 09:42:03.540198817 +0100 ++++ opensc-0.19.0/src/libopensc/padding.c 2019-11-14 09:42:03.564199055 +0100 +@@ -499,6 +499,7 @@ int sc_get_encoding_flags(sc_context_t * + /* 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 -up opensc-0.19.0/src/libopensc/pkcs15-cac.c.idprime opensc-0.19.0/src/libopensc/pkcs15-cac.c +--- opensc-0.19.0/src/libopensc/pkcs15-cac.c.idprime 2019-11-14 09:42:03.546198876 +0100 ++++ opensc-0.19.0/src/libopensc/pkcs15-cac.c 2019-11-14 09:46:46.655011155 +0100 +@@ -87,89 +87,6 @@ static const char * cac_get_name(int typ + 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[] = { +@@ -408,9 +325,9 @@ static int sc_pkcs15emu_cac_init(sc_pkcs + + 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_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n", + sc_dump_hex(cert_info.id.value, cert_info.id.len), + usage, pubkey_info.usage, prkey_info.usage); +diff -up opensc-0.19.0/src/libopensc/pkcs15-cert.c.idprime opensc-0.19.0/src/libopensc/pkcs15-cert.c +--- opensc-0.19.0/src/libopensc/pkcs15-cert.c.idprime 2018-09-13 13:52:42.000000000 +0200 ++++ opensc-0.19.0/src/libopensc/pkcs15-cert.c 2019-11-14 09:42:03.565199065 +0100 +@@ -257,6 +257,8 @@ sc_pkcs15_get_extension(struct sc_contex + { 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, +@@ -322,6 +324,8 @@ sc_pkcs15_get_bitstring_extension(struct + { 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"); + +@@ -533,6 +537,88 @@ sc_pkcs15_encode_cdf_entry(sc_context_t + 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 -up opensc-0.19.0/src/libopensc/pkcs15.h.idprime opensc-0.19.0/src/libopensc/pkcs15.h +--- opensc-0.19.0/src/libopensc/pkcs15.h.idprime 2018-09-13 13:52:42.000000000 +0200 ++++ opensc-0.19.0/src/libopensc/pkcs15.h 2019-11-14 09:42:03.565199065 +0100 +@@ -732,6 +732,9 @@ int sc_pkcs15_get_name_from_dn(struct sc + const u8 *dn, size_t dn_len, + const struct sc_object_id *type, + u8 **name, size_t *name_len); ++int sc_pkcs15_map_usage(unsigned int cert_usage, int algorithm, ++ unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, ++ int allow_nonrepudiation); + int sc_pkcs15_get_extension(struct sc_context *ctx, + struct sc_pkcs15_cert *cert, + const struct sc_object_id *type, +diff -up opensc-0.19.0/src/libopensc/pkcs15-idprime.c.idprime opensc-0.19.0/src/libopensc/pkcs15-idprime.c +--- opensc-0.19.0/src/libopensc/pkcs15-idprime.c.idprime 2019-11-14 09:42:03.565199065 +0100 ++++ opensc-0.19.0/src/libopensc/pkcs15-idprime.c 2019-11-14 09:49:19.494529520 +0100 +@@ -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" ++ ++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 = 12; ++ pin_info.attrs.pin.max_length = 12; ++ 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, CERT_LABEL_TEMPLATE, i+1); ++ snprintf(prkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, CERT_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; ++ r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); ++ sc_log(card->ctx, "adding rsa public key r=%d usage=%x",r, pubkey_info.usage); ++ if (r < 0) ++ goto fail; ++ r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); ++ sc_log(card->ctx, "adding rsa private key r=%d usage=%x",r, prkey_info.usage); ++ } ++ ++ 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_pkcs15emu_opt_t *opts) ++{ ++ sc_card_t *card = p15card->card; ++ sc_context_t *ctx = card->ctx; ++ ++ LOG_FUNC_CALLED(ctx); ++ ++ if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK) ++ return sc_pkcs15emu_idprime_init(p15card); ++ else { ++ if (idprime_detect_card(p15card)) ++ return SC_ERROR_WRONG_CARD; ++ return sc_pkcs15emu_idprime_init(p15card); ++ } ++} +diff -up opensc-0.19.0/src/libopensc/pkcs15-syn.c.idprime opensc-0.19.0/src/libopensc/pkcs15-syn.c +--- opensc-0.19.0/src/libopensc/pkcs15-syn.c.idprime 2019-11-14 09:42:03.565199065 +0100 ++++ opensc-0.19.0/src/libopensc/pkcs15-syn.c 2019-11-14 09:47:10.851251524 +0100 +@@ -45,6 +45,7 @@ struct sc_pkcs15_emulator_handler builti + { "postecert", sc_pkcs15emu_postecert_init_ex }, + { "PIV-II", sc_pkcs15emu_piv_init_ex }, + { "cac", sc_pkcs15emu_cac_init_ex }, ++ { "idprime", sc_pkcs15emu_idprime_init_ex }, + { "gemsafeGPK", sc_pkcs15emu_gemsafeGPK_init_ex }, + { "gemsafeV1", sc_pkcs15emu_gemsafeV1_init_ex }, + { "actalis", sc_pkcs15emu_actalis_init_ex }, +diff -up opensc-0.19.0/src/libopensc/pkcs15-syn.h.idprime opensc-0.19.0/src/libopensc/pkcs15-syn.h +--- opensc-0.19.0/src/libopensc/pkcs15-syn.h.idprime 2019-11-14 09:42:03.565199065 +0100 ++++ opensc-0.19.0/src/libopensc/pkcs15-syn.h 2019-11-14 09:47:34.499486456 +0100 +@@ -54,6 +54,7 @@ int sc_pkcs15emu_iasecc_init_ex(sc_pkcs1 + int sc_pkcs15emu_jpki_init_ex(sc_pkcs15_card_t *, struct sc_aid *, sc_pkcs15emu_opt_t *); + int sc_pkcs15emu_coolkey_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *, sc_pkcs15emu_opt_t *opts); + int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *, sc_pkcs15emu_opt_t *opts); ++int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *, sc_pkcs15emu_opt_t *opts); + + struct sc_pkcs15_emulator_handler { + const char *name; +diff -up opensc-0.19.0/src/libopensc/simpletlv.h.idprime opensc-0.19.0/src/libopensc/simpletlv.h +--- opensc-0.19.0/src/libopensc/simpletlv.h.idprime 2018-09-13 13:52:42.000000000 +0200 ++++ opensc-0.19.0/src/libopensc/simpletlv.h 2019-11-14 09:42:03.565199065 +0100 +@@ -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 -up opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime opensc-0.19.0/src/pkcs11/framework-pkcs15.c +--- opensc-0.19.0/src/pkcs11/framework-pkcs15.c.idprime 2019-11-14 09:42:03.537198787 +0100 ++++ opensc-0.19.0/src/pkcs11/framework-pkcs15.c 2019-11-14 09:42:03.566199075 +0100 +@@ -3796,7 +3796,7 @@ pkcs15_prkey_sign(struct sc_pkcs11_sessi + /* 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; + } +@@ -3931,6 +3931,39 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se + 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; + } +@@ -4100,6 +4133,7 @@ pkcs15_prkey_init_params(struct sc_pkcs1 + 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: +@@ -4155,6 +4189,18 @@ pkcs15_prkey_init_params(struct sc_pkcs1 + + /* 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; ++ if (oaep_params->mgf < CKG_MGF1_SHA1 || oaep_params->mgf > CKG_MGF1_SHA224) ++ return CKR_MECHANISM_PARAM_INVALID; ++ ++ /* TODO support different salt lengths */ ++ /* TODO is there something more to check */ ++ break; + } + return CKR_OK; + } +@@ -5117,6 +5163,7 @@ register_mechanisms(struct sc_pkcs11_car + 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 + } + +@@ -5197,6 +5244,7 @@ register_mechanisms(struct sc_pkcs11_car + } + + 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); +@@ -5233,6 +5281,18 @@ register_mechanisms(struct sc_pkcs11_car + 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 -up opensc-0.19.0/src/pkcs11/mechanism.c.idprime opensc-0.19.0/src/pkcs11/mechanism.c +--- opensc-0.19.0/src/pkcs11/mechanism.c.idprime 2019-11-14 09:42:03.525198668 +0100 ++++ opensc-0.19.0/src/pkcs11/mechanism.c 2019-11-14 09:42:03.566199075 +0100 +@@ -803,6 +803,15 @@ sc_pkcs11_decr_init(struct sc_pkcs11_ses + memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM)); + 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 -up opensc-0.19.0/src/tools/opensc-tool.c.idprime opensc-0.19.0/src/tools/opensc-tool.c +--- opensc-0.19.0/src/tools/opensc-tool.c.idprime 2018-09-13 13:52:42.000000000 +0200 ++++ opensc-0.19.0/src/tools/opensc-tool.c 2019-11-14 09:42:03.566199075 +0100 +@@ -593,6 +593,7 @@ static int list_algorithms(void) + { 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 -up opensc-0.19.0/src/tools/pkcs11-tool.c.idprime opensc-0.19.0/src/tools/pkcs11-tool.c +--- opensc-0.19.0/src/tools/pkcs11-tool.c.idprime 2019-11-14 09:42:03.550198916 +0100 ++++ opensc-0.19.0/src/tools/pkcs11-tool.c 2019-11-14 09:50:17.950110055 +0100 +@@ -2037,9 +2037,15 @@ static void decrypt_data(CK_SLOT_ID slot + 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; +@@ -2049,12 +2055,6 @@ static void decrypt_data(CK_SLOT_ID slot + 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_PKCS: diff --git a/SPECS/opensc.spec b/SPECS/opensc.spec index 0c709d9..50862de 100644 --- a/SPECS/opensc.spec +++ b/SPECS/opensc.spec @@ -3,7 +3,7 @@ Name: opensc Version: 0.19.0 -Release: 5%{?dist} +Release: 7%{?dist} Summary: Smart card library and applications Group: System Environment/Libraries @@ -27,6 +27,10 @@ Patch5: opensc-0.19.0-cac1.patch Patch6: opensc-0.19.0-pinpad.patch # https://github.com/OpenSC/OpenSC/pull/1549 Patch7: opensc-0.19.0-dual.patch +# https://github.com/OpenSC/OpenSC/pull/1772 +Patch8: opensc-0.19.0-idprime.patch +# https://github.com/OpenSC/OpenSC/pull/1532 +Patch9: opensc-0.19.0-coolkey-2k.patch BuildRequires: pcsc-lite-devel BuildRequires: readline-devel @@ -60,6 +64,8 @@ every software/card that does so, too. %patch5 -p1 -b .cac1 %patch6 -p1 -b .pinpad %patch7 -p1 -b .dual +%patch8 -p1 -b .idprime +%patch9 -p1 -b .coolkey-2k cp -p src/pkcs15init/README ./README.pkcs15init cp -p src/scconf/README.scconf . @@ -211,6 +217,13 @@ fi %changelog +* 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)