2010-08-16 00:56:27 +00:00
|
|
|
/*
|
|
|
|
* PKCS15 emulation layer for Italian CNS.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008, Emanuele Pucciarelli <ep@acm.org>
|
|
|
|
* Many snippets have been taken out from other PKCS15 emulation layer
|
|
|
|
* modules in this directory; their copyright is their authors'.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Specifications for the development of this driver come from:
|
|
|
|
* http://www.servizidemografici.interno.it/sitoCNSD/documentazioneRicerca.do?metodo=contenutoDocumento&servizio=documentazione&ID_DOCUMENTO=1043
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2016-01-06 14:40:59 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
#include <openssl/x509.h>
|
|
|
|
#include <openssl/x509v3.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "internal.h"
|
2010-08-16 00:56:27 +00:00
|
|
|
#include "pkcs15.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "cards.h"
|
|
|
|
#include "itacns.h"
|
|
|
|
#include "common/compat_strlcpy.h"
|
2010-08-18 13:42:30 +00:00
|
|
|
#include "common/compat_strlcat.h"
|
2010-08-16 00:56:27 +00:00
|
|
|
|
|
|
|
#ifdef ENABLE_OPENSSL
|
2016-01-06 14:40:59 +00:00
|
|
|
#include <openssl/x509.h>
|
2010-08-16 00:56:27 +00:00
|
|
|
#include <openssl/x509v3.h>
|
|
|
|
#endif
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
int sc_pkcs15emu_itacns_init_ex(sc_pkcs15_card_t *, struct sc_aid *, sc_pkcs15emu_opt_t *);
|
2010-08-16 00:56:27 +00:00
|
|
|
|
|
|
|
static const char path_serial[] = "10001003";
|
|
|
|
|
|
|
|
/* Manufacturers */
|
|
|
|
|
2010-11-06 18:07:04 +00:00
|
|
|
const char * itacns_mask_manufacturers[] = {
|
2010-08-16 00:56:27 +00:00
|
|
|
"Unknown",
|
|
|
|
"Kaitech",
|
|
|
|
"Gemplus",
|
|
|
|
"Ghirlanda",
|
|
|
|
"Giesecke & Devrient",
|
|
|
|
"Oberthur Card Systems",
|
|
|
|
"Orga",
|
|
|
|
"Axalto",
|
|
|
|
"Siemens",
|
|
|
|
"STIncard",
|
|
|
|
"GEP",
|
|
|
|
"EPS Corp",
|
|
|
|
"Athena"
|
|
|
|
};
|
|
|
|
|
2010-11-06 18:07:04 +00:00
|
|
|
const char * iso7816_ic_manufacturers[] = {
|
2010-08-16 00:56:27 +00:00
|
|
|
"Unknown",
|
|
|
|
"Motorola",
|
|
|
|
"STMicroelectronics",
|
|
|
|
"Hitachi",
|
2011-01-27 08:43:32 +00:00
|
|
|
"NXP Semiconductors",
|
|
|
|
"Infineon",
|
2010-08-16 00:56:27 +00:00
|
|
|
"Cylinc",
|
|
|
|
"Texas Instruments",
|
|
|
|
"Fujitsu",
|
|
|
|
"Matsushita",
|
|
|
|
"NEC",
|
|
|
|
"Oki",
|
|
|
|
"Toshiba",
|
|
|
|
"Mitsubishi",
|
|
|
|
"Samsung",
|
2011-01-27 08:43:32 +00:00
|
|
|
"Hynix",
|
|
|
|
"LG",
|
|
|
|
"Emosyn-EM",
|
|
|
|
"INSIDE",
|
|
|
|
"ORGA",
|
|
|
|
"SHARP",
|
|
|
|
"ATMEL",
|
|
|
|
"EM Microelectronic-Marin",
|
|
|
|
"KSW Microtec",
|
|
|
|
"ZMD",
|
|
|
|
"XICOR",
|
|
|
|
"Sony",
|
|
|
|
"Malaysia Microelectronic Solutions",
|
|
|
|
"Emosyn",
|
|
|
|
"Shanghai Fudan",
|
|
|
|
"Magellan",
|
|
|
|
"Melexis",
|
|
|
|
"Renesas",
|
|
|
|
"TAGSYS",
|
|
|
|
"Transcore",
|
|
|
|
"Shanghai belling",
|
|
|
|
"Masktech",
|
|
|
|
"Innovision",
|
|
|
|
"Hitachi",
|
|
|
|
"Cypak",
|
|
|
|
"Ricoh",
|
|
|
|
"ASK",
|
|
|
|
"Unicore",
|
|
|
|
"Dallas",
|
|
|
|
"Impinj",
|
|
|
|
"RightPlug Alliance",
|
|
|
|
"Broadcom",
|
|
|
|
"MStar",
|
|
|
|
"BeeDar",
|
|
|
|
"RFIDsec",
|
|
|
|
"Schweizer Electronic",
|
|
|
|
"AMIC Technology",
|
|
|
|
"Mikron",
|
|
|
|
"Fraunhofer",
|
|
|
|
"IDS Microchip",
|
|
|
|
"Kovio",
|
|
|
|
"HMT Microelectronic",
|
|
|
|
"Silicon Craft",
|
|
|
|
"Advanced Film Device",
|
|
|
|
"Nitecrest",
|
|
|
|
"Verayo",
|
|
|
|
"HID Gloval",
|
|
|
|
"Productivity Engineering",
|
|
|
|
"Austriamicrosystems",
|
|
|
|
"Gemalto"
|
2010-08-16 00:56:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Data files */
|
|
|
|
|
|
|
|
static const struct {
|
2010-11-06 18:07:04 +00:00
|
|
|
const char *label;
|
|
|
|
const char *path;
|
2010-08-16 00:56:27 +00:00
|
|
|
int cie_only;
|
|
|
|
} itacns_data_files[] = {
|
|
|
|
{ "EF_DatiProcessore", "3F0010001002", 0 },
|
|
|
|
{ "EF_IDCarta", "3F0010001003", 0 },
|
|
|
|
{ "EF_DatiSistema", "3F0010001004", 1 },
|
|
|
|
{ "EF_DatiPersonali", "3F0011001102", 0 },
|
|
|
|
{ "EF_DatiPersonali_Annotazioni", "3F0011001103", 1 },
|
|
|
|
{ "EF_Impronte", "3F0011001104", 1 },
|
|
|
|
{ "EF_Foto", "3F0011001104", 1 },
|
|
|
|
{ "EF_DatiPersonaliAggiuntivi", "3F0012001201", 0 },
|
|
|
|
{ "EF_MemoriaResidua", "3F0012001202", 0 },
|
|
|
|
{ "EF_ServiziInstallati", "3F0012001203", 0 },
|
|
|
|
{ "EF_INST_FILE", "3F0012004142", 0 },
|
|
|
|
{ "EF_CardStatus", "3F003F02", 0 },
|
|
|
|
{ "EF_GDO", "3F002F02", 0 },
|
|
|
|
{ "EF_RootInstFile", "3F000405", 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Utility functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void set_string(char **strp, const char *value)
|
|
|
|
{
|
|
|
|
if (*strp)
|
|
|
|
free(*strp);
|
|
|
|
*strp = value ? strdup(value) : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int loadFile(const sc_pkcs15_card_t *p15card, const sc_path_t *path,
|
|
|
|
u8 *buf, const size_t buflen)
|
|
|
|
{
|
2010-09-08 21:23:49 +00:00
|
|
|
int sc_res;
|
2010-08-16 00:56:27 +00:00
|
|
|
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
|
|
|
|
|
|
|
sc_res = sc_select_file(p15card->card, path, NULL);
|
|
|
|
if(sc_res != SC_SUCCESS)
|
|
|
|
return sc_res;
|
|
|
|
|
|
|
|
sc_res = sc_read_binary(p15card->card, 0, buf, buflen, 0);
|
|
|
|
return sc_res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The following functions add objects to the card emulator.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int itacns_add_cert(sc_pkcs15_card_t *p15card,
|
|
|
|
int type, int authority, const sc_path_t *path,
|
|
|
|
const sc_pkcs15_id_t *id, const char *label, int obj_flags,
|
|
|
|
int *ext_info_ok, int *key_usage, int *x_key_usage)
|
|
|
|
{
|
2010-09-08 21:23:49 +00:00
|
|
|
int r;
|
|
|
|
/* const char *label = "Certificate"; */
|
|
|
|
sc_pkcs15_cert_info_t info;
|
|
|
|
sc_pkcs15_object_t obj;
|
2010-09-22 20:57:07 +00:00
|
|
|
#ifdef ENABLE_OPENSSL
|
2010-09-08 21:23:49 +00:00
|
|
|
X509 *x509;
|
|
|
|
sc_pkcs15_cert_t *cert;
|
2015-09-17 19:50:19 +00:00
|
|
|
#endif
|
2010-09-08 21:23:49 +00:00
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
2010-09-02 22:58:45 +00:00
|
|
|
|
|
|
|
if(type != SC_PKCS15_TYPE_CERT_X509) {
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
"Cannot add a certificate of a type other than X.509");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
*ext_info_ok = 0;
|
2010-09-02 22:58:45 +00:00
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
memset(&obj, 0, sizeof(obj));
|
|
|
|
|
|
|
|
info.id = *id;
|
|
|
|
info.authority = authority;
|
|
|
|
if (path)
|
|
|
|
info.path = *path;
|
|
|
|
|
|
|
|
strlcpy(obj.label, label, sizeof(obj.label));
|
|
|
|
obj.flags = obj_flags;
|
|
|
|
|
|
|
|
r = sc_pkcs15emu_add_x509_cert(p15card, &obj, &info);
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add X.509 certificate");
|
|
|
|
|
|
|
|
/* If we have OpenSSL, read keyUsage */
|
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
|
|
|
|
r = sc_pkcs15_read_certificate(p15card, &info, &cert);
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not read X.509 certificate");
|
|
|
|
|
2010-09-08 21:23:49 +00:00
|
|
|
{
|
2012-09-30 20:38:27 +00:00
|
|
|
const u8 *throwaway = cert->data.value;
|
|
|
|
x509 = d2i_X509(NULL, &throwaway, cert->data.len);
|
2010-09-08 21:23:49 +00:00
|
|
|
}
|
2010-08-16 00:56:27 +00:00
|
|
|
sc_pkcs15_free_certificate(cert);
|
|
|
|
if (!x509) return SC_SUCCESS;
|
|
|
|
X509_check_purpose(x509, -1, 0);
|
2016-01-06 14:40:59 +00:00
|
|
|
|
|
|
|
if(X509_get_extension_flags(x509) & EXFLAG_KUSAGE) {
|
2010-08-16 00:56:27 +00:00
|
|
|
*ext_info_ok = 1;
|
2016-01-06 14:40:59 +00:00
|
|
|
*key_usage = X509_get_key_usage(x509);
|
|
|
|
*x_key_usage = X509_get_extended_key_usage(x509);
|
2010-08-16 00:56:27 +00:00
|
|
|
}
|
|
|
|
OPENSSL_free(x509);
|
|
|
|
|
|
|
|
return SC_SUCCESS;
|
|
|
|
|
|
|
|
#else /* ENABLE_OPENSSL */
|
|
|
|
|
|
|
|
return SC_SUCCESS;
|
|
|
|
|
|
|
|
#endif /* ENABLE_OPENSSL */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int itacns_add_pubkey(sc_pkcs15_card_t *p15card,
|
|
|
|
const sc_path_t *path, const sc_pkcs15_id_t *id, const char *label,
|
|
|
|
int usage, int ref, int obj_flags, int *modulus_len_out)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
sc_pkcs15_pubkey_info_t info;
|
|
|
|
sc_pkcs15_object_t obj;
|
|
|
|
|
2010-09-08 21:23:49 +00:00
|
|
|
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
memset(&obj, 0, sizeof(obj));
|
|
|
|
|
|
|
|
info.id = *id;
|
|
|
|
if (path)
|
|
|
|
info.path = *path;
|
|
|
|
info.usage = usage;
|
|
|
|
info.key_reference = ref;
|
|
|
|
strlcpy(obj.label, label, sizeof(obj.label));
|
|
|
|
obj.flags = obj_flags;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is hard-coded, unless unforeseen versions of the CNS
|
|
|
|
* turn up sometime.
|
|
|
|
*/
|
|
|
|
info.modulus_length = 1024;
|
|
|
|
|
|
|
|
*modulus_len_out = info.modulus_length;
|
|
|
|
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &obj, &info);
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add pub key");
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int itacns_add_prkey(sc_pkcs15_card_t *p15card,
|
|
|
|
const sc_pkcs15_id_t *id,
|
|
|
|
const char *label,
|
|
|
|
int type, unsigned int modulus_length, int usage,
|
2010-09-02 22:58:45 +00:00
|
|
|
const sc_path_t *path, int ref,
|
2010-08-16 00:56:27 +00:00
|
|
|
const sc_pkcs15_id_t *auth_id, int obj_flags)
|
|
|
|
{
|
2010-09-08 21:23:49 +00:00
|
|
|
sc_pkcs15_prkey_info_t info;
|
|
|
|
sc_pkcs15_object_t obj;
|
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
|
|
|
|
2010-09-02 22:58:45 +00:00
|
|
|
if(type != SC_PKCS15_TYPE_PRKEY_RSA) {
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
"Cannot add a private key of a type other than RSA");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
memset(&obj, 0, sizeof(obj));
|
|
|
|
|
|
|
|
info.id = *id;
|
|
|
|
info.modulus_length = modulus_length;
|
|
|
|
info.usage = usage;
|
|
|
|
info.native = 1;
|
|
|
|
info.key_reference = ref;
|
|
|
|
|
|
|
|
if (path)
|
|
|
|
info.path = *path;
|
|
|
|
|
|
|
|
obj.flags = obj_flags;
|
|
|
|
strlcpy(obj.label, label, sizeof(obj.label));
|
|
|
|
if (auth_id != NULL)
|
|
|
|
obj.auth_id = *auth_id;
|
|
|
|
|
|
|
|
return sc_pkcs15emu_add_rsa_prkey(p15card, &obj, &info);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int itacns_add_pin(sc_pkcs15_card_t *p15card,
|
|
|
|
char *label,
|
|
|
|
int id,
|
|
|
|
int auth_id,
|
|
|
|
int reference,
|
|
|
|
sc_path_t *path,
|
|
|
|
int flags)
|
|
|
|
{
|
2011-06-05 15:46:25 +00:00
|
|
|
struct sc_pkcs15_auth_info pin_info;
|
2010-08-16 00:56:27 +00:00
|
|
|
struct sc_pkcs15_object pin_obj;
|
|
|
|
|
2010-09-08 21:23:49 +00:00
|
|
|
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
memset(&pin_info, 0, sizeof(pin_info));
|
2011-06-05 15:46:25 +00:00
|
|
|
pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
|
2010-08-16 00:56:27 +00:00
|
|
|
pin_info.auth_id.len = 1;
|
|
|
|
pin_info.auth_id.value[0] = id;
|
2011-06-05 15:46:25 +00:00
|
|
|
pin_info.attrs.pin.reference = reference;
|
|
|
|
pin_info.attrs.pin.flags = flags;
|
|
|
|
pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
|
|
|
|
pin_info.attrs.pin.min_length = 5;
|
|
|
|
pin_info.attrs.pin.stored_length = 8;
|
|
|
|
pin_info.attrs.pin.max_length = 8;
|
|
|
|
pin_info.attrs.pin.pad_char = 0xff;
|
2016-08-11 16:26:01 +00:00
|
|
|
pin_info.logged_in = SC_PIN_STATE_UNKNOWN;
|
2010-08-16 00:56:27 +00:00
|
|
|
if(path)
|
|
|
|
pin_info.path = *path;
|
|
|
|
|
|
|
|
memset(&pin_obj, 0, sizeof(pin_obj));
|
|
|
|
strlcpy(pin_obj.label, label, sizeof(pin_obj.label));
|
|
|
|
pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE |
|
|
|
|
(auth_id ? SC_PKCS15_CO_FLAG_MODIFIABLE : 0);
|
|
|
|
if (auth_id) {
|
|
|
|
pin_obj.auth_id.len = 1;
|
|
|
|
pin_obj.auth_id.value[0] = auth_id;
|
|
|
|
} else
|
|
|
|
pin_obj.auth_id.len = 0;
|
|
|
|
|
|
|
|
return sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
|
|
|
|
}
|
|
|
|
|
2010-09-02 22:58:47 +00:00
|
|
|
static int hextoint(char *src, unsigned int len)
|
2010-08-16 00:56:27 +00:00
|
|
|
{
|
|
|
|
char hex[16];
|
2010-09-08 21:23:49 +00:00
|
|
|
char *end;
|
|
|
|
int res;
|
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
if(len >= sizeof(hex))
|
|
|
|
return -1;
|
|
|
|
strncpy(hex, src, len+1);
|
|
|
|
hex[len] = '\0';
|
2010-09-08 21:23:49 +00:00
|
|
|
res = strtol(hex, &end, 0x10);
|
2010-08-16 00:56:27 +00:00
|
|
|
if(end != (char*)&hex[len])
|
|
|
|
return -1;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int get_name_from_EF_DatiPersonali(unsigned char *EFdata,
|
|
|
|
char name[], int name_len)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Bytes 0-5 contain the ASCII encoding of the following TLV
|
2018-04-14 17:38:34 +00:00
|
|
|
* structure's total size, in base 16.
|
2010-08-16 00:56:27 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
const unsigned int EF_personaldata_maxlen = 400;
|
2010-09-02 22:58:47 +00:00
|
|
|
const unsigned int tlv_length_size = 6;
|
|
|
|
char *file = (char*)&EFdata[tlv_length_size];
|
|
|
|
int file_size = hextoint((char*)EFdata, tlv_length_size);
|
2010-08-16 00:56:27 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
f_issuer_code = 0,
|
|
|
|
f_issuing_date,
|
|
|
|
f_expiry_date,
|
|
|
|
f_last_name,
|
|
|
|
f_first_name,
|
|
|
|
f_birth_date,
|
|
|
|
f_sex,
|
|
|
|
f_height,
|
|
|
|
f_codice_fiscale,
|
|
|
|
f_citizenship_code,
|
|
|
|
f_birth_township_code,
|
|
|
|
f_birth_country,
|
|
|
|
f_birth_certificate,
|
|
|
|
f_residence_township_code,
|
|
|
|
f_residence_address,
|
|
|
|
f_expat_notes
|
|
|
|
};
|
|
|
|
|
2010-09-08 21:23:49 +00:00
|
|
|
/* Read the fields up to f_first_name */
|
2010-08-16 00:56:27 +00:00
|
|
|
struct {
|
|
|
|
int len;
|
|
|
|
char value[256];
|
|
|
|
} fields[f_first_name+1];
|
|
|
|
int i=0; /* offset inside the file */
|
|
|
|
int f; /* field number */
|
|
|
|
|
2010-09-08 21:23:49 +00:00
|
|
|
if(file_size < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This shouldn't happen, but let us be protected against wrong
|
|
|
|
* or malicious cards
|
|
|
|
*/
|
|
|
|
if(file_size > (int)EF_personaldata_maxlen - (int)tlv_length_size)
|
|
|
|
file_size = EF_personaldata_maxlen - tlv_length_size;
|
|
|
|
|
|
|
|
|
|
|
|
memset(fields, 0, sizeof(fields));
|
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
for(f=0; f<f_first_name+1; f++) {
|
2010-09-08 21:23:49 +00:00
|
|
|
int field_size;
|
2010-09-02 13:39:01 +00:00
|
|
|
/* Don't read beyond the allocated buffer */
|
2010-08-16 00:56:27 +00:00
|
|
|
if(i > file_size)
|
|
|
|
return -1;
|
|
|
|
|
2010-09-08 21:23:49 +00:00
|
|
|
field_size = hextoint((char*) &file[i], 2);
|
2010-08-16 00:56:27 +00:00
|
|
|
if((field_size < 0) || (field_size+i > file_size))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
i += 2;
|
|
|
|
|
2010-09-02 22:58:47 +00:00
|
|
|
if(field_size >= (int)sizeof(fields[f].value))
|
2010-08-16 00:56:27 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
fields[f].len = field_size;
|
|
|
|
strncpy(fields[f].value, &file[i], field_size);
|
|
|
|
fields[f].value[field_size] = '\0';
|
|
|
|
i += field_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fields[f_first_name].len + fields[f_last_name].len + 1 >= name_len)
|
|
|
|
return -1;
|
|
|
|
|
2017-11-17 09:47:53 +00:00
|
|
|
/* the lengths are already checked that they will fit in buffer */
|
|
|
|
snprintf(name, name_len, "%.*s %.*s",
|
|
|
|
fields[f_first_name].len, fields[f_first_name].value,
|
|
|
|
fields[f_last_name].len, fields[f_last_name].value);
|
2010-08-16 00:56:27 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int itacns_add_data_files(sc_pkcs15_card_t *p15card)
|
|
|
|
{
|
2011-03-23 16:05:24 +00:00
|
|
|
const size_t array_size =
|
2010-08-16 00:56:27 +00:00
|
|
|
sizeof(itacns_data_files)/sizeof(itacns_data_files[0]);
|
2010-09-02 22:58:47 +00:00
|
|
|
unsigned int i;
|
2010-09-08 21:23:49 +00:00
|
|
|
int rv;
|
|
|
|
sc_pkcs15_data_t *p15_personaldata = NULL;
|
|
|
|
sc_pkcs15_data_info_t dinfo;
|
|
|
|
struct sc_pkcs15_object *objs[32];
|
|
|
|
struct sc_pkcs15_data_info *cinfo;
|
|
|
|
|
2011-03-23 16:05:24 +00:00
|
|
|
for(i=0; i < array_size; i++) {
|
2010-09-08 21:23:49 +00:00
|
|
|
sc_path_t path;
|
|
|
|
sc_pkcs15_data_info_t data;
|
|
|
|
sc_pkcs15_object_t obj;
|
|
|
|
|
|
|
|
if (itacns_data_files[i].cie_only &&
|
2010-08-16 00:56:27 +00:00
|
|
|
p15card->card->type != SC_CARD_TYPE_ITACNS_CIE_V2)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
sc_format_path(itacns_data_files[i].path, &path);
|
|
|
|
|
|
|
|
memset(&data, 0, sizeof(data));
|
|
|
|
memset(&obj, 0, sizeof(obj));
|
|
|
|
strlcpy(data.app_label, itacns_data_files[i].label,
|
|
|
|
sizeof(data.app_label));
|
|
|
|
strlcpy(obj.label, itacns_data_files[i].label,
|
|
|
|
sizeof(obj.label));
|
|
|
|
data.path = path;
|
2010-09-08 21:23:49 +00:00
|
|
|
rv = sc_pkcs15emu_add_data_object(p15card, &obj, &data);
|
2015-01-28 04:47:20 +00:00
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, rv,
|
|
|
|
"Could not add data file");
|
2010-08-16 00:56:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we got this far, we can read the Personal Data file and glean
|
|
|
|
* the user's full name. Thus we can use it to put together a
|
|
|
|
* user-friendlier card name.
|
|
|
|
*/
|
|
|
|
memset(&dinfo, 0, sizeof(dinfo));
|
|
|
|
strcpy(dinfo.app_label, "EF_DatiPersonali");
|
|
|
|
|
2010-09-02 13:39:01 +00:00
|
|
|
/* Find EF_DatiPersonali */
|
2010-08-16 00:56:27 +00:00
|
|
|
|
2010-09-08 21:23:49 +00:00
|
|
|
rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT,
|
2010-08-16 00:56:27 +00:00
|
|
|
objs, 32);
|
|
|
|
if(rv < 0) {
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
"Data enumeration failed");
|
|
|
|
return SC_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<32; i++) {
|
|
|
|
cinfo = (struct sc_pkcs15_data_info *) objs[i]->data;
|
|
|
|
if(!strcmp("EF_DatiPersonali", objs[i]->label))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(i>=32) {
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
"Could not find EF_DatiPersonali: "
|
|
|
|
"keeping generic card name");
|
|
|
|
return SC_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = sc_pkcs15_read_data_object(p15card, cinfo, &p15_personaldata);
|
|
|
|
if (rv) {
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
"Could not read EF_DatiPersonali: "
|
|
|
|
"keeping generic card name");
|
|
|
|
}
|
|
|
|
|
2010-09-08 21:23:49 +00:00
|
|
|
{
|
|
|
|
char fullname[160];
|
|
|
|
if(get_name_from_EF_DatiPersonali(p15_personaldata->data,
|
|
|
|
fullname, sizeof(fullname))) {
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
"Could not parse EF_DatiPersonali: "
|
|
|
|
"keeping generic card name");
|
|
|
|
sc_pkcs15_free_data_object(p15_personaldata);
|
|
|
|
return SC_SUCCESS;
|
|
|
|
}
|
2010-10-05 15:44:58 +00:00
|
|
|
set_string(&p15card->tokeninfo->label, fullname);
|
2010-08-16 00:56:27 +00:00
|
|
|
}
|
|
|
|
sc_pkcs15_free_data_object(p15_personaldata);
|
|
|
|
return SC_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int itacns_add_keyset(sc_pkcs15_card_t *p15card,
|
|
|
|
const char *label, int sec_env, sc_pkcs15_id_t *cert_id,
|
|
|
|
const char *pubkey_path, const char *prkey_path,
|
|
|
|
unsigned int pubkey_usage_flags, unsigned int prkey_usage_flags,
|
2010-09-02 22:58:45 +00:00
|
|
|
u8 pin_ref)
|
2010-08-16 00:56:27 +00:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
sc_path_t path;
|
2010-09-08 21:23:49 +00:00
|
|
|
sc_path_t *private_path = NULL;
|
|
|
|
char pinlabel[16];
|
|
|
|
int fake_puk_authid, pin_flags;
|
2010-08-16 00:56:27 +00:00
|
|
|
|
|
|
|
/* This is hard-coded, for the time being. */
|
|
|
|
int modulus_length = 1024;
|
|
|
|
|
|
|
|
/* Public key; not really needed */
|
|
|
|
/* FIXME: set usage according to the certificate. */
|
|
|
|
if (pubkey_path) {
|
|
|
|
sc_format_path(pubkey_path, &path);
|
|
|
|
r = itacns_add_pubkey(p15card, &path, cert_id, label,
|
|
|
|
pubkey_usage_flags, sec_env, 0, &modulus_length);
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add public key");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: usage should be inferred from the X.509 certificate, and not
|
|
|
|
* from whether the key needs Secure Messaging.
|
|
|
|
*/
|
|
|
|
if (prkey_path) {
|
|
|
|
sc_format_path(prkey_path, &path);
|
|
|
|
private_path = &path;
|
|
|
|
}
|
|
|
|
r = itacns_add_prkey(p15card, cert_id, label, SC_PKCS15_TYPE_PRKEY_RSA,
|
|
|
|
modulus_length,
|
|
|
|
prkey_usage_flags,
|
|
|
|
private_path, sec_env, cert_id, SC_PKCS15_CO_FLAG_PRIVATE);
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add private key");
|
|
|
|
|
|
|
|
/* PIN and PUK */
|
2010-08-18 13:42:30 +00:00
|
|
|
strlcpy(pinlabel, "PIN ", sizeof(pinlabel));
|
|
|
|
strlcat(pinlabel, label, sizeof(pinlabel));
|
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
/* We are making up ID 0x90+ to link the PIN and the PUK. */
|
2010-09-08 21:23:49 +00:00
|
|
|
fake_puk_authid = 0x90 + pin_ref;
|
|
|
|
pin_flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE
|
2010-08-16 00:56:27 +00:00
|
|
|
| SC_PKCS15_PIN_FLAG_INITIALIZED;
|
|
|
|
r = itacns_add_pin(p15card, pinlabel, sec_env, fake_puk_authid, pin_ref,
|
|
|
|
private_path, pin_flags);
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add PIN");
|
2010-08-18 13:42:30 +00:00
|
|
|
|
|
|
|
strlcpy(pinlabel, "PUK ", sizeof(pinlabel));
|
|
|
|
strlcat(pinlabel, label, sizeof(pinlabel));
|
2010-08-16 00:56:27 +00:00
|
|
|
/*
|
|
|
|
* Looking at pkcs15-tcos.c and pkcs15-framework.c, it seems that the
|
|
|
|
* right thing to do here is to define a PUK as a SO PIN. Can anybody
|
|
|
|
* comment on this?
|
|
|
|
*/
|
|
|
|
pin_flags |= SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN
|
|
|
|
| SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED;
|
|
|
|
r = itacns_add_pin(p15card, pinlabel, fake_puk_authid, 0, pin_ref+1,
|
|
|
|
private_path, pin_flags);
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add PUK");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* itacns_check_and_add_keyset() checks for the existence and correctness
|
|
|
|
* of an X.509 certificate. If it is all right, it adds the related keys;
|
|
|
|
* otherwise it aborts.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int itacns_check_and_add_keyset(sc_pkcs15_card_t *p15card,
|
|
|
|
const char *label, int sec_env, size_t cert_offset,
|
|
|
|
const char *cert_path, const char *pubkey_path, const char *prkey_path,
|
2010-09-02 22:58:45 +00:00
|
|
|
u8 pin_ref, int *found_certificates)
|
2010-08-16 00:56:27 +00:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
sc_path_t path;
|
|
|
|
sc_pkcs15_id_t cert_id;
|
2010-09-08 21:23:49 +00:00
|
|
|
int ext_info_ok;
|
2018-03-13 20:56:32 +00:00
|
|
|
int ku = 0, xku = 0;
|
2010-09-08 21:23:49 +00:00
|
|
|
int pubkey_usage_flags = 0, prkey_usage_flags = 0;
|
2010-08-16 00:56:27 +00:00
|
|
|
|
|
|
|
cert_id.len = 1;
|
|
|
|
cert_id.value[0] = sec_env;
|
|
|
|
*found_certificates = 0;
|
|
|
|
|
|
|
|
/* Certificate */
|
|
|
|
if (!cert_path) {
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
"We cannot use keys without a matching certificate");
|
|
|
|
return SC_ERROR_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
sc_format_path(cert_path, &path);
|
|
|
|
r = sc_select_file(p15card->card, &path, NULL);
|
|
|
|
if (r == SC_ERROR_FILE_NOT_FOUND)
|
|
|
|
return 0;
|
|
|
|
if (r != SC_SUCCESS) {
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
"Could not find certificate for %s", label);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Infocamere 1204 (and others?) store a more complex structure. We
|
|
|
|
* are going to read the first bytes to guess its length, and invoke
|
|
|
|
* itacns_add_cert so that it only reads the certificate.
|
|
|
|
*/
|
|
|
|
if (cert_offset) {
|
|
|
|
u8 certlen[3];
|
|
|
|
r = loadFile(p15card, &path, certlen, sizeof(certlen));
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not read certificate file");
|
|
|
|
path.index = cert_offset;
|
|
|
|
path.count = (certlen[1] << 8) + certlen[2];
|
2018-04-14 17:38:34 +00:00
|
|
|
/* If those bytes are 00, then we are probably dealing with an
|
2010-08-16 00:56:27 +00:00
|
|
|
* empty file. */
|
|
|
|
if (path.count == 0)
|
|
|
|
return 0;
|
|
|
|
}
|
2010-09-08 21:23:49 +00:00
|
|
|
|
2010-08-16 00:56:27 +00:00
|
|
|
r = itacns_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, 0,
|
|
|
|
&path, &cert_id, label, 0, &ext_info_ok, &ku, &xku);
|
|
|
|
if (r == SC_ERROR_INVALID_ASN1_OBJECT)
|
|
|
|
return 0;
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add certificate");
|
|
|
|
(*found_certificates)++;
|
|
|
|
|
|
|
|
/* Set usage flags */
|
|
|
|
if(ext_info_ok) {
|
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
if (ku & KU_DIGITAL_SIGNATURE) {
|
|
|
|
pubkey_usage_flags |= SC_PKCS15_PRKEY_USAGE_VERIFY;
|
|
|
|
prkey_usage_flags |= SC_PKCS15_PRKEY_USAGE_SIGN;
|
|
|
|
}
|
|
|
|
if (ku & KU_NON_REPUDIATION) {
|
|
|
|
pubkey_usage_flags |= SC_PKCS15_PRKEY_USAGE_VERIFY;
|
|
|
|
prkey_usage_flags |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
|
|
|
|
}
|
|
|
|
if (ku & KU_KEY_ENCIPHERMENT || ku & KU_KEY_AGREEMENT
|
|
|
|
|| xku & XKU_SSL_CLIENT) {
|
|
|
|
pubkey_usage_flags |= SC_PKCS15_PRKEY_USAGE_WRAP;
|
|
|
|
prkey_usage_flags |= SC_PKCS15_PRKEY_USAGE_UNWRAP;
|
|
|
|
}
|
|
|
|
if (ku & KU_DATA_ENCIPHERMENT || xku & XKU_SMIME) {
|
|
|
|
pubkey_usage_flags |= SC_PKCS15_PRKEY_USAGE_ENCRYPT;
|
|
|
|
prkey_usage_flags |= SC_PKCS15_PRKEY_USAGE_DECRYPT;
|
|
|
|
}
|
|
|
|
#else /* ENABLE_OPENSSL */
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
|
|
|
|
"Extended certificate info retrieved without OpenSSL. "
|
|
|
|
"How is this possible?");
|
|
|
|
return SC_ERROR_INTERNAL;
|
|
|
|
#endif /* ENABLE_OPENSSL */
|
|
|
|
} else {
|
|
|
|
/* Certificate info not retrieved; fall back onto defaults */
|
|
|
|
pubkey_usage_flags =
|
|
|
|
SC_PKCS15_PRKEY_USAGE_VERIFY
|
|
|
|
| SC_PKCS15_PRKEY_USAGE_WRAP;
|
|
|
|
prkey_usage_flags =
|
|
|
|
SC_PKCS15_PRKEY_USAGE_SIGN
|
|
|
|
| SC_PKCS15_PRKEY_USAGE_UNWRAP;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = itacns_add_keyset(p15card, label, sec_env, &cert_id,
|
|
|
|
pubkey_path, prkey_path, pubkey_usage_flags, prkey_usage_flags,
|
2010-09-02 22:58:45 +00:00
|
|
|
pin_ref);
|
2010-08-16 00:56:27 +00:00
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add keys for this certificate");
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialization. */
|
|
|
|
|
|
|
|
static int itacns_init(sc_pkcs15_card_t *p15card)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
sc_path_t path;
|
|
|
|
int certificate_count = 0;
|
|
|
|
int found_certs;
|
2010-09-08 21:23:49 +00:00
|
|
|
int card_is_cie_v1, cns0_secenv;
|
|
|
|
|
|
|
|
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
2010-08-16 00:56:27 +00:00
|
|
|
|
2010-10-05 15:44:58 +00:00
|
|
|
set_string(&p15card->tokeninfo->label, p15card->card->name);
|
2010-08-16 00:56:27 +00:00
|
|
|
if(p15card->card->drv_data) {
|
2010-09-02 22:58:47 +00:00
|
|
|
unsigned int mask_code, ic_code;
|
2010-08-16 00:56:27 +00:00
|
|
|
char buffer[256];
|
|
|
|
itacns_drv_data_t *data =
|
|
|
|
(itacns_drv_data_t*) p15card->card->drv_data;
|
|
|
|
mask_code = data->mask_manufacturer_code;
|
2010-12-19 11:18:43 +00:00
|
|
|
if (mask_code >= sizeof(itacns_mask_manufacturers)
|
|
|
|
/sizeof(itacns_mask_manufacturers[0]))
|
2010-08-16 00:56:27 +00:00
|
|
|
mask_code = 0;
|
|
|
|
ic_code = data->ic_manufacturer_code;
|
2010-12-19 11:18:43 +00:00
|
|
|
if (ic_code >= sizeof(iso7816_ic_manufacturers)
|
|
|
|
/sizeof(iso7816_ic_manufacturers[0]))
|
2010-08-16 00:56:27 +00:00
|
|
|
ic_code = 0;
|
|
|
|
snprintf(buffer, sizeof(buffer), "IC: %s; mask: %s",
|
|
|
|
iso7816_ic_manufacturers[ic_code],
|
|
|
|
itacns_mask_manufacturers[mask_code]);
|
2010-10-05 15:44:58 +00:00
|
|
|
set_string(&p15card->tokeninfo->manufacturer_id, buffer);
|
2010-08-16 00:56:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Read and set serial */
|
|
|
|
{
|
2010-09-08 21:23:49 +00:00
|
|
|
u8 serial[17];
|
2010-08-16 00:56:27 +00:00
|
|
|
int bytes;
|
|
|
|
sc_format_path(path_serial, &path);
|
|
|
|
bytes = loadFile(p15card, &path, serial, 16);
|
|
|
|
if (bytes < 0) return bytes;
|
|
|
|
if (bytes > 16) return -1;
|
|
|
|
serial[bytes] = '\0';
|
2010-10-05 15:44:58 +00:00
|
|
|
set_string(&p15card->tokeninfo->serial_number, (char*)serial);
|
2010-08-16 00:56:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Is the card a CIE v1? */
|
2010-09-08 21:23:49 +00:00
|
|
|
card_is_cie_v1 =
|
2010-08-16 00:56:27 +00:00
|
|
|
(p15card->card->type == SC_CARD_TYPE_ITACNS_CIE_V1)
|
|
|
|
|| (p15card->card->type == SC_CARD_TYPE_CARDOS_CIE_V1);
|
2010-09-08 21:23:49 +00:00
|
|
|
cns0_secenv = (card_is_cie_v1 ? 0x31 : 0x01);
|
2010-08-16 00:56:27 +00:00
|
|
|
|
|
|
|
/* If it's a Siemens CIE v1 card, set algo flags accordingly. */
|
|
|
|
if (card_is_cie_v1) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < p15card->card->algorithm_count; i++) {
|
|
|
|
sc_algorithm_info_t *info =
|
|
|
|
&p15card->card->algorithms[i];
|
|
|
|
|
|
|
|
if (info->algorithm != SC_ALGORITHM_RSA)
|
|
|
|
continue;
|
|
|
|
info->flags &= ~(SC_ALGORITHM_RSA_RAW
|
|
|
|
| SC_ALGORITHM_RSA_HASH_NONE);
|
|
|
|
info->flags |= (SC_ALGORITHM_RSA_PAD_PKCS1
|
|
|
|
| SC_ALGORITHM_RSA_HASHES);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Data files */
|
|
|
|
r = itacns_add_data_files(p15card);
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add data files");
|
|
|
|
|
|
|
|
/*** Certificate and keys. ***/
|
|
|
|
/* Standard CNS */
|
|
|
|
r = itacns_check_and_add_keyset(p15card, "CNS0", cns0_secenv,
|
|
|
|
0, "3F0011001101", "3F003F01", NULL,
|
2010-09-02 22:58:45 +00:00
|
|
|
0x10, &found_certs);
|
2010-08-16 00:56:27 +00:00
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add CNS0");
|
|
|
|
certificate_count += found_certs;
|
|
|
|
|
|
|
|
/* Infocamere 1204 */
|
|
|
|
r = itacns_check_and_add_keyset(p15card, "CNS01", 0x21,
|
|
|
|
5, "3F002FFF8228", NULL, "3F002FFF0000",
|
2010-09-02 22:58:45 +00:00
|
|
|
0x10, &found_certs);
|
2010-08-16 00:56:27 +00:00
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add CNS01");
|
|
|
|
certificate_count += found_certs;
|
|
|
|
|
|
|
|
/* Digital signature */
|
|
|
|
r = itacns_check_and_add_keyset(p15card, "CNS1", 0x10,
|
|
|
|
0, "3F0014009010", "3F00140081108010", "3F0014008110",
|
2010-09-02 22:58:45 +00:00
|
|
|
0x1a, &found_certs);
|
2010-08-16 00:56:27 +00:00
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not add CNS1");
|
|
|
|
certificate_count += found_certs;
|
|
|
|
|
|
|
|
/* Did we find anything? */
|
|
|
|
if (certificate_count == 0)
|
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE,
|
|
|
|
"Warning: no certificates found!");
|
|
|
|
|
|
|
|
/* Back to Master File */
|
|
|
|
sc_format_path("3F00", &path);
|
|
|
|
r = sc_select_file(p15card->card, &path, NULL);
|
|
|
|
SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r,
|
|
|
|
"Could not select master file again");
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
int sc_pkcs15emu_itacns_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *aid,
|
|
|
|
sc_pkcs15emu_opt_t *opts)
|
2010-08-16 00:56:27 +00:00
|
|
|
{
|
|
|
|
sc_card_t *card = p15card->card;
|
|
|
|
SC_FUNC_CALLED(card->ctx, 1);
|
|
|
|
|
|
|
|
/* Check card */
|
|
|
|
if (!(opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)) {
|
|
|
|
if (! (
|
|
|
|
(card->type > SC_CARD_TYPE_ITACNS_BASE &&
|
|
|
|
card->type < SC_CARD_TYPE_ITACNS_BASE + 1000)
|
|
|
|
|| card->type == SC_CARD_TYPE_CARDOS_CIE_V1)
|
|
|
|
)
|
|
|
|
return SC_ERROR_WRONG_CARD;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Init card */
|
|
|
|
return itacns_init(p15card);
|
|
|
|
}
|