2005-05-08 21:30:06 +00:00
|
|
|
/*
|
|
|
|
* PKCS15 emulation layer for Actalis card.
|
|
|
|
* To see how this works, run p15dump on your Actalis Card.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2005, Andrea Frigido <andrea@frisoft.it>
|
|
|
|
* Copyright (C) 2005, Sirio Capizzi <graaf@virgilio.it>
|
|
|
|
* Copyright (C) 2004, Antonino Iacono <ant_iacono@tin.it>
|
|
|
|
* Copyright (C) 2003, Olaf Kirch <okir@suse.de>
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2015-04-22 21:55:33 +00:00
|
|
|
#if HAVE_CONFIG_H
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "config.h"
|
2015-04-22 21:55:33 +00:00
|
|
|
#endif
|
2010-12-19 11:18:40 +00:00
|
|
|
|
2005-05-08 21:30:06 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2008-03-06 16:06:59 +00:00
|
|
|
#ifdef ENABLE_ZLIB
|
2005-05-08 21:30:06 +00:00
|
|
|
#include <zlib.h>
|
|
|
|
#endif
|
|
|
|
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "common/compat_strlcpy.h"
|
|
|
|
#include "libopensc/pkcs15.h"
|
|
|
|
#include "libopensc/log.h"
|
2020-06-04 10:21:47 +00:00
|
|
|
#include "libopensc/internal.h"
|
2010-03-04 08:14:36 +00:00
|
|
|
|
2005-05-08 21:30:06 +00:00
|
|
|
static int (*set_security_env) (sc_card_t *, const sc_security_env_t *, int);
|
|
|
|
|
|
|
|
static int set_sec_env(sc_card_t * card, const sc_security_env_t *env,
|
|
|
|
int se_num)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
sc_security_env_t tenv = *env;
|
|
|
|
if (tenv.operation == SC_SEC_OPERATION_SIGN)
|
|
|
|
tenv.operation = SC_SEC_OPERATION_DECIPHER;
|
|
|
|
|
|
|
|
if ((r =
|
|
|
|
card->ops->restore_security_env(card, 0x40)) == SC_SUCCESS)
|
|
|
|
return set_security_env(card, &tenv, se_num);
|
|
|
|
else
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int do_sign(sc_card_t * card, const u8 * in, size_t inlen, u8 * out,
|
|
|
|
size_t outlen)
|
|
|
|
{
|
|
|
|
return card->ops->decipher(card, in, inlen, out, outlen);
|
|
|
|
}
|
|
|
|
|
2005-10-30 21:42:35 +00:00
|
|
|
#if 1
|
|
|
|
/* XXX: temporary copy of the old pkcs15emu functions,
|
|
|
|
* to be removed */
|
|
|
|
static int sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
|
|
|
|
const sc_pkcs15_id_t *id, const char *label,
|
|
|
|
const sc_path_t *path, int ref, int type,
|
|
|
|
unsigned int min_length,
|
|
|
|
unsigned int max_length,
|
|
|
|
int flags, int tries_left, const char pad_char, int obj_flags)
|
|
|
|
{
|
2011-06-05 15:46:25 +00:00
|
|
|
sc_pkcs15_auth_info_t info;
|
2005-10-30 21:42:35 +00:00
|
|
|
sc_pkcs15_object_t obj;
|
|
|
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
memset(&obj, 0, sizeof(obj));
|
|
|
|
|
|
|
|
info.auth_id = *id;
|
2011-06-05 15:46:25 +00:00
|
|
|
info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
|
|
|
|
info.attrs.pin.min_length = min_length;
|
|
|
|
info.attrs.pin.max_length = max_length;
|
|
|
|
info.attrs.pin.stored_length = max_length;
|
|
|
|
info.attrs.pin.type = type;
|
|
|
|
info.attrs.pin.reference = ref;
|
|
|
|
info.attrs.pin.flags = flags;
|
|
|
|
info.attrs.pin.pad_char = pad_char;
|
2005-10-30 21:42:35 +00:00
|
|
|
info.tries_left = tries_left;
|
2016-08-11 16:26:01 +00:00
|
|
|
info.logged_in = SC_PIN_STATE_UNKNOWN;
|
2005-10-30 21:42:35 +00:00
|
|
|
|
|
|
|
if (path)
|
|
|
|
info.path = *path;
|
|
|
|
if (type == SC_PKCS15_PIN_TYPE_BCD)
|
2011-06-05 15:46:25 +00:00
|
|
|
info.attrs.pin.stored_length /= 2;
|
2005-10-30 21:42:35 +00:00
|
|
|
|
2006-07-12 08:12:38 +00:00
|
|
|
strlcpy(obj.label, label, sizeof(obj.label));
|
2005-10-30 21:42:35 +00:00
|
|
|
obj.flags = obj_flags;
|
|
|
|
|
|
|
|
return sc_pkcs15emu_add_pin_obj(p15card, &obj, &info);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card,
|
|
|
|
const sc_pkcs15_id_t *id,
|
|
|
|
const char *label,
|
|
|
|
int type, unsigned int modulus_length, int usage,
|
|
|
|
const sc_path_t *path, int ref,
|
|
|
|
const sc_pkcs15_id_t *auth_id, int obj_flags)
|
|
|
|
{
|
|
|
|
sc_pkcs15_prkey_info_t info;
|
|
|
|
sc_pkcs15_object_t obj;
|
|
|
|
|
|
|
|
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;
|
2006-07-12 08:12:38 +00:00
|
|
|
strlcpy(obj.label, label, sizeof(obj.label));
|
2005-10-30 21:42:35 +00:00
|
|
|
if (auth_id != NULL)
|
|
|
|
obj.auth_id = *auth_id;
|
|
|
|
|
|
|
|
return sc_pkcs15emu_add_rsa_prkey(p15card, &obj, &info);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-05-08 21:30:06 +00:00
|
|
|
static int sc_pkcs15emu_actalis_init(sc_pkcs15_card_t * p15card)
|
|
|
|
{
|
|
|
|
sc_card_t *card = p15card->card;
|
|
|
|
sc_path_t path;
|
|
|
|
sc_pkcs15_id_t id, auth_id;
|
2010-12-19 11:18:40 +00:00
|
|
|
unsigned char serial_buf[13], *serial;
|
2005-05-08 21:30:06 +00:00
|
|
|
int flags;
|
2006-03-02 14:16:52 +00:00
|
|
|
int r;
|
2005-05-08 21:30:06 +00:00
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
#ifdef ENABLE_ZLIB
|
2010-12-20 08:57:07 +00:00
|
|
|
int i = 0, j = 0;
|
2005-05-08 21:30:06 +00:00
|
|
|
const char *certLabel[] = {
|
|
|
|
"User Non-repudiation Certificate", /* "User Non-repudiation Certificate" */
|
2010-12-19 11:18:40 +00:00
|
|
|
"TSA Certificate",
|
2005-05-08 21:30:06 +00:00
|
|
|
"CA Certificate"
|
|
|
|
};
|
|
|
|
const char *certPath[] =
|
|
|
|
{ "3F00300060006002", "3F00300060006003", "3F00300060006004" };
|
2006-03-02 14:16:52 +00:00
|
|
|
#endif
|
2005-05-08 21:30:06 +00:00
|
|
|
|
|
|
|
const char *keyPath = "3F00300040000008";
|
|
|
|
const char *pinDfName = "05040200";
|
|
|
|
|
|
|
|
/* const int prkey_usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; */
|
|
|
|
const int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN
|
|
|
|
| SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
|
|
|
|
| SC_PKCS15_PRKEY_USAGE_ENCRYPT
|
|
|
|
| SC_PKCS15_PRKEY_USAGE_DECRYPT;
|
|
|
|
|
|
|
|
const char *authPIN = "Authentication PIN";
|
|
|
|
/* const char *nonrepPIN = "Non-repudiation PIN"; */
|
|
|
|
|
|
|
|
const char *authPRKEY = "Authentication Key";
|
|
|
|
/* const char *nonrepPRKEY = "Non repudiation Key"; */
|
|
|
|
|
2009-10-22 08:59:59 +00:00
|
|
|
p15card->opts.use_file_cache = 1;
|
2010-12-19 11:18:40 +00:00
|
|
|
|
2005-05-08 21:30:06 +00:00
|
|
|
/* Get Serial number */
|
|
|
|
sc_format_path("3F0030000001", &path);
|
|
|
|
r = sc_select_file(card, &path, NULL);
|
|
|
|
if (r != SC_SUCCESS)
|
|
|
|
return SC_ERROR_WRONG_CARD;
|
|
|
|
|
2019-04-30 11:29:32 +00:00
|
|
|
r = sc_read_binary(card, 0xC3, serial_buf, 12, 0);
|
|
|
|
if (r != SC_SUCCESS)
|
|
|
|
return SC_ERROR_WRONG_CARD;
|
2010-12-19 11:18:40 +00:00
|
|
|
serial = serial_buf;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The serial number is 8 characters long. Later versions of the
|
|
|
|
* card have the serial number at a different offset, after 4 more
|
|
|
|
* bytes.
|
|
|
|
*/
|
|
|
|
if (serial[0] != 'H') {
|
|
|
|
if (serial[4] == 'H')
|
|
|
|
serial = &serial_buf[4];
|
|
|
|
else
|
|
|
|
return SC_ERROR_WRONG_CARD;
|
|
|
|
}
|
2005-05-08 21:30:06 +00:00
|
|
|
serial[8] = '\0';
|
|
|
|
|
|
|
|
/* Controllo che il serial number inizi per "H" */
|
|
|
|
if( serial[0] != 'H' )
|
|
|
|
return SC_ERROR_WRONG_CARD;
|
|
|
|
|
2010-10-05 15:44:58 +00:00
|
|
|
set_string(&p15card->tokeninfo->label, "Actalis");
|
|
|
|
set_string(&p15card->tokeninfo->manufacturer_id, "Actalis");
|
|
|
|
set_string(&p15card->tokeninfo->serial_number, (char *)serial);
|
2005-05-08 21:30:06 +00:00
|
|
|
|
2008-03-06 16:06:59 +00:00
|
|
|
#ifdef ENABLE_ZLIB
|
2005-05-08 21:30:06 +00:00
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
sc_path_t cpath;
|
|
|
|
sc_format_path(certPath[i], &cpath);
|
|
|
|
|
2010-12-19 11:18:40 +00:00
|
|
|
if (sc_select_file(card, &cpath, NULL) == SC_SUCCESS) {
|
|
|
|
unsigned char *compCert = NULL, *cert = NULL, size[2];
|
2011-05-22 10:16:36 +00:00
|
|
|
unsigned long compLen, len;
|
2010-12-19 11:18:40 +00:00
|
|
|
|
|
|
|
sc_pkcs15_cert_info_t cert_info;
|
|
|
|
sc_pkcs15_object_t cert_obj;
|
|
|
|
memset(&cert_info, 0, sizeof(cert_info));
|
|
|
|
memset(&cert_obj, 0, sizeof(cert_obj));
|
|
|
|
|
2019-04-25 13:40:03 +00:00
|
|
|
if (SC_SUCCESS != sc_read_binary(card, 2, size, 2, 0))
|
|
|
|
continue;
|
2010-12-19 11:18:40 +00:00
|
|
|
compLen = (size[0] << 8) + size[1];
|
|
|
|
compCert = malloc(compLen * sizeof(unsigned char));
|
|
|
|
len = 3 * compLen; /*Approximation of the uncompressed size */
|
|
|
|
cert = malloc(len * sizeof(unsigned char));
|
2017-04-20 19:08:49 +00:00
|
|
|
if (!cert || !compCert) {
|
|
|
|
free(cert);
|
|
|
|
free(compCert);
|
|
|
|
return SC_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
2010-12-19 11:18:40 +00:00
|
|
|
|
2019-04-25 13:40:03 +00:00
|
|
|
if (sc_read_binary(card, 4, compCert, compLen, 0) != SC_SUCCESS
|
|
|
|
|| uncompress(cert, &len, compCert, compLen) != Z_OK) {
|
2019-01-25 00:15:01 +00:00
|
|
|
free(cert);
|
|
|
|
free(compCert);
|
2019-04-25 13:40:03 +00:00
|
|
|
continue;
|
2019-01-25 00:15:01 +00:00
|
|
|
}
|
2010-12-19 11:18:40 +00:00
|
|
|
cpath.index = 0;
|
|
|
|
cpath.count = len;
|
|
|
|
|
|
|
|
sc_pkcs15_cache_file(p15card, &cpath, cert, len);
|
|
|
|
id.value[0] = j + 1;
|
|
|
|
id.len = 1;
|
|
|
|
cert_info.id = id;
|
|
|
|
cert_info.path = cpath;
|
|
|
|
cert_info.authority = (j>0);
|
|
|
|
|
|
|
|
strlcpy(cert_obj.label, certLabel[j], sizeof(cert_obj.label));
|
|
|
|
|
|
|
|
j++;
|
|
|
|
cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;
|
2020-03-02 17:13:32 +00:00
|
|
|
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);
|
|
|
|
free(cert);
|
|
|
|
free(compCert);
|
|
|
|
continue;
|
|
|
|
}
|
2019-01-25 00:15:01 +00:00
|
|
|
|
|
|
|
free(cert);
|
|
|
|
free(compCert);
|
2010-12-19 11:18:40 +00:00
|
|
|
}
|
2005-05-08 21:30:06 +00:00
|
|
|
}
|
2005-05-10 12:59:38 +00:00
|
|
|
#endif
|
2005-05-08 21:30:06 +00:00
|
|
|
|
|
|
|
/* adding PINs & private keys */
|
|
|
|
flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
|
|
|
|
SC_PKCS15_PIN_FLAG_INITIALIZED |
|
|
|
|
SC_PKCS15_PIN_FLAG_NEEDS_PADDING;
|
|
|
|
|
|
|
|
sc_format_path(pinDfName, &path);
|
|
|
|
path.type = SC_PATH_TYPE_DF_NAME;
|
|
|
|
|
|
|
|
id.value[0] = 1;
|
|
|
|
id.len = 1;
|
|
|
|
sc_pkcs15emu_add_pin(p15card, &id,
|
|
|
|
authPIN, &path, 0x81,
|
|
|
|
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
|
|
|
|
5, 8, flags, 3, 0,
|
|
|
|
SC_PKCS15_CO_FLAG_MODIFIABLE |
|
|
|
|
SC_PKCS15_CO_FLAG_PRIVATE);
|
|
|
|
|
|
|
|
sc_format_path(keyPath, &path);
|
|
|
|
id.value[0] = 1;
|
|
|
|
id.len = 1;
|
|
|
|
auth_id.value[0] = 1;
|
|
|
|
auth_id.len = 1;
|
|
|
|
sc_pkcs15emu_add_prkey(p15card, &id,
|
|
|
|
authPRKEY,
|
|
|
|
SC_PKCS15_TYPE_PRKEY_RSA,
|
|
|
|
1024, authprkey_usage,
|
|
|
|
&path, 0x08,
|
|
|
|
&auth_id,
|
|
|
|
SC_PKCS15_CO_FLAG_PRIVATE);
|
|
|
|
|
|
|
|
/* return to MF */
|
|
|
|
sc_format_path("3F00", &path);
|
|
|
|
sc_select_file(card, &path, NULL);
|
|
|
|
{
|
|
|
|
/* save old signature funcs */
|
|
|
|
set_security_env = card->ops->set_security_env;
|
|
|
|
/* set new one */
|
|
|
|
card->ops->set_security_env = set_sec_env;
|
|
|
|
card->ops->compute_signature = do_sign;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SC_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int actalis_detect_card(sc_pkcs15_card_t * p15card)
|
|
|
|
{
|
|
|
|
sc_card_t *card = p15card->card;
|
|
|
|
|
|
|
|
/* check if we have the correct card OS */
|
|
|
|
if (strcmp(card->name, "CardOS M4"))
|
|
|
|
return SC_ERROR_WRONG_CARD;
|
|
|
|
|
|
|
|
return SC_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sc_pkcs15emu_actalis_init_ex(sc_pkcs15_card_t * p15card,
|
2019-03-26 14:14:25 +00:00
|
|
|
struct sc_aid *aid)
|
2005-05-08 21:30:06 +00:00
|
|
|
{
|
2019-03-26 14:14:25 +00:00
|
|
|
if (actalis_detect_card(p15card))
|
|
|
|
return SC_ERROR_WRONG_CARD;
|
|
|
|
return sc_pkcs15emu_actalis_init(p15card);
|
2005-05-08 21:30:06 +00:00
|
|
|
}
|