add pkcs15 emulation support for the Italian postecert card
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1985 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
9dc98ed262
commit
2d2a6d8bac
|
@ -169,8 +169,9 @@ app default {
|
|||
# Default: yes
|
||||
enable_builtin_emulation = yes;
|
||||
# list of the builtin pkcs15 emulators to test
|
||||
# possible values: esteid, openpgp, netkey, netkey, starcert, infocamere
|
||||
builtin_emulators = esteid, openpgp, netkey, netkey, starcert, infocamere;
|
||||
# possible values: esteid, openpgp, netkey, netkey,
|
||||
# starcert, infocamere, postecert
|
||||
builtin_emulators = esteid, openpgp, netkey, netkey, starcert, infocamere, postecert;
|
||||
|
||||
# additional pkcs15 emulators (dynamic or builtin with
|
||||
# a different atr etc.)
|
||||
|
|
|
@ -31,7 +31,7 @@ libopensc_la_SOURCES = \
|
|||
card-oberthur.c card-oberthur.h \
|
||||
\
|
||||
pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \
|
||||
pkcs15-netkey.c pkcs15-esteid.c
|
||||
pkcs15-netkey.c pkcs15-esteid.c pkcs15-postecert.c
|
||||
libopensc_la_LDFLAGS = -version-info @OPENSC_LT_CURRENT@:@OPENSC_LT_REVISION@:@OPENSC_LT_AGE@
|
||||
libopensc_la_LIBADD = @LIBSCCONF@ ../scdl/libscdl.la @LIBDL@ @LIBCRYPTO@ @OPENCT_LIBS@ @PCSC_LIBS@
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ OBJECTS = \
|
|||
card-oberthur.obj \
|
||||
\
|
||||
pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \
|
||||
pkcs15-netkey.obj pkcs15-esteid.obj \
|
||||
pkcs15-netkey.obj pkcs15-esteid.obj pkcs15-postecert.obj \
|
||||
\
|
||||
$(TOPDIR)\win32\version.res
|
||||
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* PKCS15 emulation layer for Postecert and Cnipa card.
|
||||
* To see how this works, run p15dump on your Postecert or Cnipa Card.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
#include "pkcs15.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int (*set_security_env)(sc_card_t *, const struct sc_security_env *, int);
|
||||
int (*compute_signature)(sc_card_t *, const u8 *, size_t, u8 *, size_t);
|
||||
|
||||
static int set_sec_env(sc_card_t *card, const struct sc_security_env *env, int se_num)
|
||||
{
|
||||
struct sc_security_env tenv = *env;
|
||||
if (tenv.operation == SC_SEC_OPERATION_SIGN)
|
||||
tenv.operation = SC_SEC_OPERATION_DECIPHER;
|
||||
return set_security_env(card, &tenv, se_num);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_string(char **strp, const char *value)
|
||||
{
|
||||
if (*strp)
|
||||
free(strp);
|
||||
*strp = value? strdup(value) : NULL;
|
||||
}
|
||||
|
||||
int
|
||||
sc_pkcs15emu_postecert_init(sc_pkcs15_card_t *p15card)
|
||||
{
|
||||
|
||||
static int prkey_usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION ;
|
||||
|
||||
static int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN
|
||||
| SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
|
||||
| SC_PKCS15_PRKEY_USAGE_ENCRYPT
|
||||
| SC_PKCS15_PRKEY_USAGE_DECRYPT ;
|
||||
|
||||
sc_card_t *card = p15card->card;
|
||||
sc_path_t path;
|
||||
sc_pkcs15_id_t id, auth_id;
|
||||
unsigned char certlen[2];
|
||||
unsigned char *certi = NULL;
|
||||
int index_cert[4];
|
||||
int count_cert[4];
|
||||
int flags;
|
||||
int authority;
|
||||
int count;
|
||||
int i,r;
|
||||
int o=0;
|
||||
|
||||
const char *label = "User Non-repudiation Certificate";
|
||||
const char *calabel = "CA Certificate";
|
||||
const char *catmslabel = "CA TimeStamper Certificate";
|
||||
const char *authlabel = "User Authentication Certificate";
|
||||
|
||||
const char *postecert_auth_cert_path = "504B0001";
|
||||
|
||||
const char *authPIN = "Authentication PIN";
|
||||
const char *nonrepPIN = "Non-repudiation PIN";
|
||||
|
||||
const char *authPRKEY = "Authentication Key";
|
||||
const char *nonrepPRKEY = "Non repudiation Key";
|
||||
|
||||
|
||||
/* Get the non-repudiation certificate length */
|
||||
|
||||
sc_format_path(postecert_auth_cert_path, &path);
|
||||
|
||||
if (sc_select_file(card, &path, NULL) < 0)
|
||||
{
|
||||
r = SC_ERROR_WRONG_CARD;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
set_string(&p15card->label, "Postecert & Cnipa Card");
|
||||
set_string(&p15card->manufacturer_id, "Postecert");
|
||||
set_string(&p15card->serial_number, "0000");
|
||||
|
||||
sc_read_binary(card, 0, certlen, 2, 0);
|
||||
|
||||
/* Now set the certificate offset/len */
|
||||
|
||||
count = (certlen[0] << 8) + certlen[1];
|
||||
|
||||
certi = malloc(count);
|
||||
|
||||
if (!certi)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
sc_read_binary(card, 0, certi, count - 500 , 0);
|
||||
|
||||
for (i = 2; i < (count-256); i++)
|
||||
{
|
||||
/* this file contain more than one certificate */
|
||||
|
||||
if (*(certi+i)==0x30 && *(certi+i+1)==0x82 && *(certi+i+4)==0x30 && *(certi+i+5)==0x82 && *(certi+i+2)>1 && *(certi+i+2)<8 && *(certi+i+6)<=*(certi+i+2))
|
||||
{
|
||||
index_cert[o]=i;
|
||||
count_cert[o]=(*(certi+i+2) << 8) + *(certi+i+3) + 4;
|
||||
o++;
|
||||
if (o>4) break;
|
||||
i+= (*(certi+i+2) << 8) + *(certi+i+3);
|
||||
}
|
||||
}
|
||||
|
||||
free(certi);
|
||||
|
||||
path.index = index_cert[0];
|
||||
path.count = count_cert[0];
|
||||
|
||||
id.value[0] = 1;
|
||||
id.len = 1;
|
||||
|
||||
authority = 1;
|
||||
|
||||
sc_pkcs15emu_add_cert(p15card,
|
||||
SC_PKCS15_TYPE_CERT_X509, authority,
|
||||
&path, &id, calabel, SC_PKCS15_CO_FLAG_MODIFIABLE);
|
||||
|
||||
path.index = index_cert[1];
|
||||
path.count = count_cert[1];
|
||||
|
||||
id.value[0] = 2;
|
||||
id.len = 1;
|
||||
|
||||
authority = 1;
|
||||
|
||||
sc_pkcs15emu_add_cert(p15card,
|
||||
SC_PKCS15_TYPE_CERT_X509, authority,
|
||||
&path, &id, catmslabel, SC_PKCS15_CO_FLAG_MODIFIABLE);
|
||||
|
||||
path.index = index_cert[2];
|
||||
path.count = count_cert[2];
|
||||
|
||||
id.value[0] = 3;
|
||||
id.len = 1;
|
||||
|
||||
authority = 0;
|
||||
|
||||
sc_pkcs15emu_add_cert(p15card,
|
||||
SC_PKCS15_TYPE_CERT_X509, authority,
|
||||
&path, &id, label, SC_PKCS15_CO_FLAG_MODIFIABLE);
|
||||
|
||||
path.index = index_cert[3];
|
||||
path.count = count_cert[3];
|
||||
|
||||
id.value[0] = 4;
|
||||
id.len = 1;
|
||||
|
||||
sc_pkcs15emu_add_cert(p15card,
|
||||
SC_PKCS15_TYPE_CERT_X509, authority,
|
||||
&path, &id, authlabel, SC_PKCS15_CO_FLAG_MODIFIABLE);
|
||||
|
||||
|
||||
flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE |
|
||||
SC_PKCS15_PIN_FLAG_INITIALIZED |
|
||||
SC_PKCS15_PIN_FLAG_NEEDS_PADDING;
|
||||
|
||||
/* add authentication PIN */
|
||||
|
||||
sc_format_path("3F00504B", &path);
|
||||
id.value[0] = 1;
|
||||
|
||||
sc_pkcs15emu_add_pin(p15card, &id,
|
||||
authPIN, &path, 0x82,
|
||||
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
|
||||
6, 14, flags, 3, 0,
|
||||
SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE);
|
||||
|
||||
/* add authentication private key */
|
||||
|
||||
id.value[0] = 4;
|
||||
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, 0x06,
|
||||
&auth_id, SC_PKCS15_CO_FLAG_PRIVATE);
|
||||
|
||||
/* add non repudiation PIN */
|
||||
|
||||
sc_format_path("3F00504B", &path);
|
||||
id.value[0] = 2;
|
||||
|
||||
sc_pkcs15emu_add_pin(p15card, &id,
|
||||
nonrepPIN, &path, 0x82,
|
||||
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
|
||||
6, 14, flags, 3, 0,
|
||||
SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE);
|
||||
|
||||
|
||||
/* add non repudiation private key */
|
||||
|
||||
id.value[0] = 3;
|
||||
auth_id.value[0] = 2;
|
||||
sc_pkcs15emu_add_prkey(p15card, &id,
|
||||
nonrepPRKEY,
|
||||
SC_PKCS15_TYPE_PRKEY_RSA,
|
||||
1024, prkey_usage,
|
||||
&path, 0x01,
|
||||
&auth_id, SC_PKCS15_CO_FLAG_PRIVATE);
|
||||
|
||||
|
||||
/* return to MF */
|
||||
sc_format_path("3F00", &path);
|
||||
sc_select_file(card, &path, NULL);
|
||||
{
|
||||
struct sc_card_operations *new_ops;
|
||||
new_ops = calloc(1, sizeof(*new_ops));
|
||||
if (!new_ops)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
/* copy normal cardos card ops */
|
||||
*new_ops = *card->ops;
|
||||
/* save old signature funcs */
|
||||
set_security_env = new_ops->set_security_env;
|
||||
compute_signature = new_ops->compute_signature;
|
||||
/* set new one */
|
||||
new_ops->set_security_env = set_sec_env;
|
||||
new_ops->compute_signature = do_sign;
|
||||
/* use new ops */
|
||||
card->ops = new_ops;
|
||||
}
|
||||
return 0;
|
||||
|
||||
failed: sc_error(card->ctx, "Failed to initialize Postecert and Cnipa emulation: %s\n",
|
||||
sc_strerror(r));
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
static int postecert_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_postecert_init_ex(sc_pkcs15_card_t *p15card,
|
||||
sc_pkcs15emu_opt_t *opts)
|
||||
{
|
||||
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
|
||||
return sc_pkcs15emu_postecert_init(p15card);
|
||||
else {
|
||||
int r = postecert_detect_card(p15card);
|
||||
if (r)
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
return sc_pkcs15emu_postecert_init(p15card);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -39,17 +39,20 @@ extern int sc_pkcs15emu_netkey_init_ex(sc_pkcs15_card_t *,
|
|||
sc_pkcs15emu_opt_t *);
|
||||
extern int sc_pkcs15emu_esteid_init_ex(sc_pkcs15_card_t *,
|
||||
sc_pkcs15emu_opt_t *);
|
||||
extern int sc_pkcs15emu_postecert_init_ex(sc_pkcs15_card_t *,
|
||||
sc_pkcs15emu_opt_t *);
|
||||
|
||||
static struct {
|
||||
const char * name;
|
||||
int (*handler)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||
} builtin_emulators[] = {
|
||||
{ "openpgp", sc_pkcs15emu_openpgp_init_ex },
|
||||
{ "infocamere", sc_pkcs15emu_infocamere_init_ex },
|
||||
{ "starcert", sc_pkcs15emu_starcert_init_ex },
|
||||
{ "netkey", sc_pkcs15emu_netkey_init_ex },
|
||||
{ "esteid", sc_pkcs15emu_esteid_init_ex },
|
||||
{ NULL }
|
||||
{ "openpgp", sc_pkcs15emu_openpgp_init_ex },
|
||||
{ "infocamere", sc_pkcs15emu_infocamere_init_ex },
|
||||
{ "starcert", sc_pkcs15emu_starcert_init_ex },
|
||||
{ "netkey", sc_pkcs15emu_netkey_init_ex },
|
||||
{ "esteid", sc_pkcs15emu_esteid_init_ex },
|
||||
{ "postecert", sc_pkcs15emu_postecert_init_ex },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static int parse_emu_block(sc_pkcs15_card_t *, scconf_block *);
|
||||
|
|
Loading…
Reference in New Issue