Add support for Estonian ID card. Written by Martin Paljak.

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1834 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
aj 2004-07-14 21:13:54 +00:00
parent 78d32814a1
commit 268a302950
6 changed files with 518 additions and 70 deletions

View File

@ -30,7 +30,7 @@ libopensc_la_SOURCES = \
card-oberthur.c card-oberthur.h \
\
pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \
pkcs15-netkey.c
pkcs15-netkey.c pkcs15-esteid.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@ @LIBPCSC@
@ -39,7 +39,7 @@ include_HEADERS = \
cardctl.h asn1.h log.h ui.h \
errors.h types.h
noinst_HEADERS = ctbcs.h internal.h
noinst_HEADERS = ctbcs.h internal.h esteid.h
pkgconfigdir = @libdir@/pkgconfig
pkgconfig_DATA = libopensc.pc

View File

@ -28,7 +28,7 @@ OBJECTS = \
card-oberthur.obj \
\
pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \
pkcs15-netkey.obj \
pkcs15-netkey.obj pkcs15-esteid.c \
\
$(TOPDIR)\win32\version.res

View File

@ -1,6 +1,10 @@
/*
* card-mcrd.c: Support for MICARDO cards
*
* Copyright (C) 2004 Martin Paljak <martin@paljak.pri.ee>
* Copyright (C) 2004 Priit Randla <priit.randla@eyp.ee>
* Copyright (C) 2003 Marie Fischer <marie@vtl.ee>
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
* Copyright (C) 2002 g10 Code GmbH
*
@ -26,12 +30,26 @@
#include <string.h>
#include <ctype.h>
static const char *mcrd_atrs[] = {
"3B:FF:94:00:FF:80:B1:FE:45:1F:03:00:68:D2:76:00:00:28:FF"
":05:1E:31:80:00:90:00:23", /* German BMI card */
"3B:FE:94:00:FF:80:B1:FA:45:1F:03:45:73:74:45:49:44:20:76"
":65:72:20:31:2E:30:43", /* EstEID (Estonian Big Brother card) */
NULL
#include "esteid.h"
#define TYPE_UNKNOWN 0
#define TYPE_ANY 1
#define TYPE_ESTEID 2
/* this structure should be somewhere else. Copied from other card source.
* I need to make sure a 'variant' of a card to make decisions.
*/
struct sc_card_atrs {
const char *atr;
const int type;
const char *name;
};
static struct sc_card_atrs mcrd_atrs[] = {
{"3B:FF:94:00:FF:80:B1:FE:45:1F:03:00:68:D2:76:00:00:28:FF:05:1E:31:80:00:90:00:23", TYPE_ANY, "German BMI"},
{"3B:FE:94:00:FF:80:B1:FA:45:1F:03:45:73:74:45:49:44:20:76:65:72:20:31:2E:30:43", TYPE_ESTEID, "EstEID"},
{NULL, TYPE_UNKNOWN, NULL}
};
static struct sc_card_operations mcrd_ops;
@ -85,6 +103,7 @@ struct mcrd_priv_data {
size_t curpathlen; /* Length of this path or 0 if unknown. */
int is_ef; /* True if the path points to an EF. */
struct df_info_s *df_infos;
sc_security_env_t sec_env; /* current security environment */
};
#define DRVDATA(card) ((struct mcrd_priv_data *) ((card)->drv_data))
@ -145,30 +164,128 @@ static void clear_special_files (struct df_info_s *dfi)
}
}
static int mcrd_match_card(struct sc_card *card)
// this function should be somewhere else in opensc code, too
static int
sc_card_identify (struct sc_card *card, struct sc_card_atrs *atr_list)
{
int i, match = -1;
for (i = 0; mcrd_atrs[i] != NULL; i++) {
int i;
for (i = 0; atr_list[i].atr != NULL; i++)
{
u8 defatr[SC_MAX_ATR_SIZE];
size_t len = sizeof(defatr);
const char *atrp = mcrd_atrs[i];
if (sc_hex_to_bin(atrp, defatr, &len))
size_t len = sizeof (defatr);
const char *atrp = atr_list[i].atr;
if (sc_hex_to_bin (atrp, defatr, &len))
continue;
if (len != card->atr_len)
continue;
if (memcmp(card->atr, defatr, len) != 0)
continue;
match = i;
break;
if (memcmp (card->atr, defatr, len) == 0)
return atr_list[i].type;
}
if (match == -1)
return 0;
return 0;
}
/* Some functionality straight from the EstEID manual.
* Official notice: Refer to the Micardo 2.1 Public manual.
* Sad side: not available without a NDA.
*/
return 1;
int
mcrd_delete_ref_to_authkey (struct sc_card *card)
{
struct sc_apdu apdu;
int r;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
assert (card != NULL);
sc_format_apdu (card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xA4);
sbuf[0] = 0x83;
sbuf[1] = 0x00;
apdu.data = sbuf;
apdu.lc = 2;
apdu.datalen = 2;
r = sc_transmit_apdu (card, &apdu);
SC_TEST_RET (card->ctx, r, "APDU transmit failed");
SC_FUNC_RETURN (card->ctx, 2, sc_check_sw (card, apdu.sw1, apdu.sw2));
}
int
mcrd_delete_ref_to_signkey (struct sc_card *card)
{
struct sc_apdu apdu;
int r;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
assert (card != NULL);
sc_format_apdu (card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB6);
sbuf[0] = 0x83;
sbuf[1] = 0x00;
apdu.data = sbuf;
apdu.lc = 2;
apdu.datalen = 2;
r = sc_transmit_apdu (card, &apdu);
SC_TEST_RET (card->ctx, r, "APDU transmit failed");
SC_FUNC_RETURN (card->ctx, 2, sc_check_sw (card, apdu.sw1, apdu.sw2));
}
int
mcrd_set_decipher_key_ref (struct sc_card *card, int key_reference)
{
struct sc_apdu apdu;
struct sc_path path;
int r;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 keyref_data[SC_ESTEID_KEYREF_FILE_RECLEN];
assert (card != NULL);
sc_format_apdu (card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB8);
/* track the active keypair */
sc_format_path("0033", &path);
r = sc_select_file(card, &path, NULL);
SC_TEST_RET(card->ctx, r,
"Can't select keyref info file 0x0033");
r = sc_read_record(card, 1, keyref_data,
SC_ESTEID_KEYREF_FILE_RECLEN,
SC_RECORD_BY_REC_NR);
SC_TEST_RET(card->ctx, r,
"Can't read keyref info file!");
sc_debug(card->ctx,
"authkey reference 0x%02x%02x\n",
keyref_data[9], keyref_data[10]);
sc_debug(card->ctx,
"signkey reference 0x%02x%02x\n",
keyref_data[19], keyref_data[20]);
sbuf[0] = 0x83;
sbuf[1] = 0x03;
sbuf[2] = 0x80;
switch (key_reference)
{
case 1:
sbuf[3] = keyref_data[9];
sbuf[4] = keyref_data[10];
break;
case 2:
sbuf[3] = keyref_data[19];
sbuf[4] = keyref_data[20];
break;
}
apdu.data = sbuf;
apdu.lc = 5;
apdu.datalen = 5;
r = sc_transmit_apdu (card, &apdu);
SC_TEST_RET (card->ctx, r, "APDU transmit failed");
SC_FUNC_RETURN (card->ctx, 2, sc_check_sw (card, apdu.sw1, apdu.sw2));
}
static int mcrd_match_card(struct sc_card *card)
{
return sc_card_identify(card, mcrd_atrs) != 0;
}
static int mcrd_init(struct sc_card *card)
@ -193,8 +310,8 @@ static int mcrd_init(struct sc_card *card)
priv->curpath[0] = MFID;
priv->curpathlen = 1;
load_special_files (card);
if (sc_card_identify(card, mcrd_atrs) != TYPE_ESTEID)
load_special_files (card);
return 0;
}
@ -979,7 +1096,7 @@ mcrd_select_file(struct sc_card *card, const struct sc_path *path,
/* Crypto operations */
static int restore_se (struct sc_card *card, int se_num)
static int mcrd_enable_se (struct sc_card *card, int se_num)
{
struct sc_apdu apdu;
int r;
@ -994,19 +1111,59 @@ static int restore_se (struct sc_card *card, int se_num)
/* It seems that MICARDO does not fully comply with ISO, so I use
values gathered from peeking actual signing opeations using a
different system. */
different system.
It has been generalized [?] and modified by information coming from
openpgp card implementation, EstEID 'manual' and some other sources. -mp
*/
static int mcrd_set_security_env(struct sc_card *card,
const struct sc_security_env *env,
int se_num)
{
struct mcrd_priv_data *priv = DRVDATA(card);
struct sc_apdu apdu;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 *p;
int r, locked = 0;
assert(card != NULL && env != NULL);
if (se_num)
SC_FUNC_CALLED(card->ctx, 2);
/* if (se_num)
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
*/
/* special environemnt handling for esteid, stolen from openpgp */
if (sc_card_identify(card, mcrd_atrs) == TYPE_ESTEID) {
/* some sanity checks */
if (env->flags & SC_SEC_ENV_ALG_PRESENT) {
if (env->algorithm != SC_ALGORITHM_RSA)
return SC_ERROR_INVALID_ARGUMENTS;
}
if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
|| env->key_ref_len != 1)
return SC_ERROR_INVALID_ARGUMENTS;
select_esteid_df(card); // is it needed?
switch (env->operation) {
case SC_SEC_OPERATION_DECIPHER:
sc_debug(card->ctx,
"Using keyref %d to dechiper\n",
env->key_ref[0]);
mcrd_enable_se(card, 6);
mcrd_delete_ref_to_authkey(card);
mcrd_delete_ref_to_signkey(card);
mcrd_set_decipher_key_ref(card, env->key_ref[0]);
break;
case SC_SEC_OPERATION_SIGN:
sc_debug(card->ctx, "Using keyref %d to sign\n",
env->key_ref[0]);
mcrd_enable_se(card, 1);
break;
default:
return SC_ERROR_INVALID_ARGUMENTS;
}
priv->sec_env = *env;
return 0;
}
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
apdu.le = 0;
@ -1037,8 +1194,8 @@ static int mcrd_set_security_env(struct sc_card *card,
if (num != -1) {
/* Need to restore the security environmnet. */
if (num) {
r = restore_se (card, num);
SC_TEST_RET(card->ctx, r, "restore_se failed");
r = mcrd_enable_se (card, num);
SC_TEST_RET(card->ctx, r, "mcrd_enable_se failed");
}
p += 2;
}
@ -1080,61 +1237,118 @@ err:
return r;
}
/* heavily modified by -mp */
static int mcrd_compute_signature(struct sc_card *card,
const u8 * data, size_t datalen,
u8 * out, size_t outlen)
{
struct mcrd_priv_data *priv = DRVDATA(card);
sc_security_env_t *env = &priv->sec_env;
int r;
struct sc_apdu apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
assert(card != NULL && data != NULL && out != NULL);
SC_FUNC_CALLED(card->ctx, 2);
if (env->operation != SC_SEC_OPERATION_SIGN)
return SC_ERROR_INVALID_ARGUMENTS;
if (datalen > 255)
SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
/* 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_3_SHORT, 0x2A, 0x9E,
0x9A);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf); /* FIXME */
sc_debug(card->ctx,
"Will compute signature for %d (0x%02x) bytes using key %d\n",
datalen, datalen, env->key_ref[0]);
memcpy(sbuf, data, datalen);
apdu.data = sbuf;
switch (env->key_ref[0]) {
case SC_ESTEID_AUTH: /* authentication key */
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT,
0x88, 0, 0);
break;
default:
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT,
0x2A, 0x9E, 0x9A);
}
apdu.lc = datalen;
apdu.data = data;
apdu.datalen = datalen;
apdu.le = 0x80;
apdu.resp = out;
apdu.resplen = outlen;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
SC_TEST_RET(card->ctx, r, "Card returned error");
SC_FUNC_RETURN(card->ctx, 4, apdu.resplen);
}
/* added by -mp */
int mcrd_decipher(struct sc_card *card,
const u8 * crgram, size_t crgram_len, u8 * out,
size_t out_len)
{
int r;
struct sc_apdu apdu;
struct mcrd_priv_data *priv = DRVDATA(card);
sc_security_env_t *env = &priv->sec_env;
u8 *temp;
sc_debug(card->ctx,
"Will dechiper %d (0x%02x) bytes using key %d\n",
crgram_len, crgram_len, env->key_ref[0]);
/* saniti check */
if (env->operation != SC_SEC_OPERATION_DECIPHER)
return SC_ERROR_INVALID_ARGUMENTS;
if (!(temp = (u8 *) malloc(crgram_len + 1)))
return SC_ERROR_OUT_OF_MEMORY;
temp[0] = '\0';
memcpy(temp + 1, crgram, crgram_len);
crgram = temp;
crgram_len += 1;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x80,
0x86);
apdu.resp = out;
apdu.resplen = out_len;
apdu.data = crgram;
apdu.datalen = crgram_len;
apdu.lc = crgram_len;
apdu.sensitive = 1;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
int len = apdu.resplen > outlen ? outlen : apdu.resplen;
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
SC_TEST_RET(card->ctx, r, "Card returned error");
memcpy(out, apdu.resp, len);
SC_FUNC_RETURN(card->ctx, 4, len);
}
else if (apdu.sw1 == 0x60 && apdu.sw2 == 0x61) {
/* This might be a problem with by Cardman driver.
Status codes 60xx should never been seen at this
layer, so I assume 0x6180 here. FIXME! */
int len;
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT,
0xC0, 0, 0);
apdu.le = 0x80;
apdu.resp = rbuf;
apdu.resplen = 0x80;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
len = apdu.resplen > outlen ? outlen : apdu.resplen;
memcpy(out, apdu.resp, len);
SC_FUNC_RETURN(card->ctx, 4, len);
}
SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
SC_FUNC_RETURN(card->ctx, 4, apdu.resplen);
}
/* added by -mp */
int mcrd_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,
int *tries_left)
{
SC_FUNC_CALLED(card->ctx, 3);
if (sc_card_identify(card, mcrd_atrs) == TYPE_ESTEID)
if (data->cmd == SC_PIN_CMD_UNBLOCK) {
int r;
/* FIXME: the code in iso pin_cmd sets tries_left to -1 at once.
I guess it is a thing that need implementing. set it to NULL now -mp */
r = sc_verify(card, SC_AC_CHV, 0, data->pin1.data,
data->pin1.len, NULL);
SC_TEST_RET(card->ctx, r,
"PUK verification failed!");
}
SC_FUNC_RETURN(card->ctx, 4, iso_ops->pin_cmd(card, data, tries_left));
}
@ -1142,17 +1356,19 @@ static int mcrd_compute_signature(struct sc_card *card,
static struct sc_card_driver * sc_get_driver(void)
{
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
if (iso_ops == NULL)
iso_ops = iso_drv->ops;
mcrd_ops = *iso_drv->ops;
mcrd_ops.match_card = mcrd_match_card;
mcrd_ops.init = mcrd_init;
mcrd_ops.finish = mcrd_finish;
if (iso_ops == NULL)
iso_ops = iso_drv->ops;
mcrd_ops.select_file = mcrd_select_file;
mcrd_ops.set_security_env = mcrd_set_security_env;
mcrd_ops.compute_signature = mcrd_compute_signature;
mcrd_ops.decipher = mcrd_decipher;
mcrd_ops.pin_cmd = mcrd_pin_cmd;
return &mcrd_drv;
}

31
src/libopensc/esteid.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef _OPENSC_ESTEID_H
#define _OPENSC_ESTEID_H
#define SC_ESTEID_AUTH 1
#define SC_ESTEID_SIGN 2
/* personal data file record numbers */
#define SC_ESTEID_PD_SURNAME 1
#define SC_ESTEID_PD_GIVEN_NAMES1 2
#define SC_ESTEID_PD_GIVEN_NAMES2 3
#define SC_ESTEID_PD_SEX 4
#define SC_ESTEID_PD_CITIZENSHIP 5
#define SC_ESTEID_PD_DATE_OF_BIRTH 6
#define SC_ESTEID_PD_PERSONAL_ID 7
#define SC_ESTEID_PD_DOCUMENT_NR 8
#define SC_ESTEID_PD_EXPIRY_DATE 9
#define SC_ESTEID_PD_PLACE_OF_BIRTH 10
#define SC_ESTEID_PD_ISSUING_DATE 11
#define SC_ESTEID_PD_PERMIT_TYPE 12
#define SC_ESTEID_PD_REMARK1 13
#define SC_ESTEID_PD_REMARK2 14
#define SC_ESTEID_PD_REMARK3 15
#define SC_ESTEID_PD_REMARK4 16
/* i love constants */
#define SC_ESTEID_KEYREF_FILE_RECLEN 21
int select_esteid_df(sc_card_t * card);
#endif

View File

@ -0,0 +1,199 @@
/*
* PKCS15 emulation layer for EstEID card.
*
* Copyright (C) 2004, Martin Paljak <martin@paljak.pri.ee>
* Copyright (C) 2004, Bud P. Bruegger <bud@comune.grosseto.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
*/
#include "internal.h"
#include "pkcs15.h"
#include "asn1.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "esteid.h"
static void
set_string (char **strp, const char *value)
{
if (*strp)
free (strp);
*strp = value ? strdup (value) : NULL;
}
int
select_esteid_df (sc_card_t * card)
{
int r;
sc_path_t tmppath;
sc_format_path ("3F00EEEE", &tmppath);
tmppath.type = SC_PATH_TYPE_PATH;
r = sc_select_file (card, &tmppath, NULL);
SC_TEST_RET (card->ctx, r, "esteid select DF failed");
return r;
}
int
sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
{
sc_card_t *card = p15card->card;
unsigned char buff[256];
int r, i, flags;
sc_path_t tmppath;
sc_pkcs15_id_t id;
set_string (&p15card->label, "EstEID isikutunnistus");
set_string (&p15card->manufacturer_id, "AS Sertifitseerimiskeskus");
select_esteid_df (card);
/* read the serial (document number) */
sc_format_path ("5044", &tmppath);
tmppath.type = SC_PATH_TYPE_PATH;
r = sc_select_file (card, &tmppath, NULL);
SC_TEST_RET (card->ctx, r, "select esteid PD failed");
r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, 8,
SC_RECORD_BY_REC_NR);
SC_TEST_RET (card->ctx, r, "read document number failed");
// null-terminate
buff[r] = '\0';
set_string (&p15card->serial_number, buff);
p15card->flags =
SC_PKCS15_CARD_FLAG_PRN_GENERATION |
SC_PKCS15_CARD_FLAG_EID_COMPLIANT | SC_PKCS15_CARD_FLAG_READONLY;
/* EstEEID uses 1024b RSA */
card->algorithm_count = 0;
flags = SC_ALGORITHM_RSA_PAD_PKCS1;
_sc_card_add_rsa_alg (card, 1024, flags, 0);
/* add certificates */
for (i = 0; i < 2; i++)
{
static char *esteid_cert_names[2] = {
"Autentimissertifikaat",
"Allkirjasertifikaat"
};
static char *esteid_cert_paths[2] = {
"3f00eeeeaace",
"3f00eeeeddce"
};
static int esteid_cert_ids[2] = {
SC_ESTEID_AUTH,
SC_ESTEID_SIGN
};
sc_path_t path;
sc_pkcs15_id_t auth_id;
sc_format_path (esteid_cert_paths[i], &path);
path.type = SC_PATH_TYPE_PATH;
auth_id.value[0] = esteid_cert_ids[i];
auth_id.len = 1;
r = sc_pkcs15emu_add_cert (p15card,
SC_PKCS15_TYPE_CERT_X509, 0,
&path, &auth_id, esteid_cert_names[i], 0);
}
/* the file with key pin info (tries left) */
sc_format_path ("3f000016", &tmppath);
sc_select_file (card, &tmppath, NULL);
/* add pins */
for (i = 0; i < 3; i++)
{
char tries_left;
static char *esteid_pin_names[3] = {
"PIN1 - Autentiseerimine",
"PIN2 - Allkirjastamine",
"PUK"
};
static int esteid_pin_min[3] = {
4,
5,
8
};
static int esteid_pin_ref[3] = {
1,
2,
0
};
static int esteid_pin_flags[3] = {
0,
0,
SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN
};
r = sc_read_record (card, i + 1, buff, 128, SC_RECORD_BY_REC_NR);
tries_left = buff[5];
id.len = 1;
id.value[0] = i + 1;
sc_pkcs15emu_add_pin (p15card, &id,
esteid_pin_names[i], NULL,
esteid_pin_ref[i],
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
esteid_pin_min[i], 12,
esteid_pin_flags[i], tries_left, '\0', 0);
}
/* add private keys */
for (i = 0; i < 2; i++)
{
static int prkey_pin[2] = { SC_ESTEID_AUTH, SC_ESTEID_SIGN };
static int prkey_usage[2] = {
SC_PKCS15_PRKEY_USAGE_ENCRYPT |
SC_PKCS15_PRKEY_USAGE_DECRYPT |
SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
SC_PKCS15_PRKEY_USAGE_WRAP | SC_PKCS15_PRKEY_USAGE_UNWRAP,
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION
};
static char *prkey_name[2] = {
"Autentiseerimise v\365ti",
"Allkirjastamise v\365ti"
};
sc_pkcs15_id_t id, auth_id;
id.value[0] = prkey_pin[i];
id.len = 1;
auth_id.value[0] = prkey_pin[i];
auth_id.len = 1;
// NULL may be a path.... ?
r = sc_pkcs15emu_add_prkey (p15card, &id,
prkey_name[i],
SC_PKCS15_TYPE_PRKEY_RSA,
1024, prkey_usage[i], NULL,
i + 1, &auth_id, 0);
}
return 0;
}

View File

@ -33,6 +33,7 @@ extern int sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *);
extern int sc_pkcs15emu_infocamere_init(sc_pkcs15_card_t *);
extern int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *);
extern int sc_pkcs15emu_netkey_init(sc_pkcs15_card_t *);
extern int sc_pkcs15emu_esteid_init(sc_pkcs15_card_t *);
static struct {
const char * name;
@ -42,6 +43,7 @@ static struct {
{ "infocamere", sc_pkcs15emu_infocamere_init },
{ "starcert", sc_pkcs15emu_starcert_init },
{ "netkey", sc_pkcs15emu_netkey_init },
{ "esteid", sc_pkcs15emu_esteid_init },
{ NULL }
};