add support for gpk16k gemsafe cards, Douglas E. Engert et al
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@2310 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
bf089a8fbb
commit
315b961d9a
@ -31,7 +31,7 @@ libopensc_la_SOURCES = \
|
||||
card-oberthur.c card-belpic.c \
|
||||
\
|
||||
pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \
|
||||
pkcs15-netkey.c pkcs15-esteid.c pkcs15-postecert.c
|
||||
pkcs15-netkey.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafe.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@
|
||||
|
||||
|
@ -29,6 +29,7 @@ OBJECTS = \
|
||||
\
|
||||
pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \
|
||||
pkcs15-netkey.obj pkcs15-esteid.obj pkcs15-postecert.obj \
|
||||
pkcs15-gemsafe.obj \
|
||||
\
|
||||
$(TOPDIR)\win32\version.res
|
||||
|
||||
|
@ -97,6 +97,7 @@ static struct sc_atr_table gpk_atrs[] = {
|
||||
{ "3B:A7:00:40:18:80:65:A2:08:01:01:52", NULL, "GPK 8K", SC_CARD_TYPE_GPK_GPK8000_8K },
|
||||
{ "3B:A7:00:40:18:80:65:A2:09:01:01:52", NULL, "GPK 8K", SC_CARD_TYPE_GPK_GPK8000_16K },
|
||||
{ "3B:A7:00:40:18:80:65:A2:09:01:02:52", NULL, "GPK 16K", SC_CARD_TYPE_GPK_GPK16000 },
|
||||
{ "3B:A7:00:40:18:80:65:A2:09:01:03:52", NULL, "GPK 16K", SC_CARD_TYPE_GPK_GPK16000 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
511
src/libopensc/pkcs15-gemsafe.c
Normal file
511
src/libopensc/pkcs15-gemsafe.c
Normal file
@ -0,0 +1,511 @@
|
||||
/*
|
||||
* partial PKCS15 emulation for gemsafe GPK cards
|
||||
*
|
||||
* Copyright (C) 2005, Douglas E. Engert <deengert@anl.gov>
|
||||
* 2004, Nils Larsch <larsch@trustcenter.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 <opensc/pkcs15.h>
|
||||
#include <opensc/log.h>
|
||||
#include <opensc/cardctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MANU_ID "GemSAFE on GPK16000"
|
||||
|
||||
int sc_pkcs15emu_gemsafe_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
|
||||
|
||||
static int (*pin_cmd_save)(struct sc_card *, struct sc_pin_cmd_data *,
|
||||
int *tries_left);
|
||||
|
||||
typedef struct cdata_st {
|
||||
const char *label;
|
||||
int authority;
|
||||
const char *path;
|
||||
const char *id;
|
||||
int obj_flags;
|
||||
} cdata;
|
||||
|
||||
typedef struct pdata_st {
|
||||
const char *id;
|
||||
const char *label;
|
||||
const char *path;
|
||||
int ref;
|
||||
int type;
|
||||
unsigned int maxlen;
|
||||
unsigned int minlen;
|
||||
unsigned int storedlen;
|
||||
int flags;
|
||||
int tries_left;
|
||||
const char pad_char;
|
||||
int obj_flags;
|
||||
} pindata;
|
||||
|
||||
typedef struct prdata_st {
|
||||
const char *id;
|
||||
const char *label;
|
||||
unsigned int modulus_len;
|
||||
int usage;
|
||||
const char *path;
|
||||
int ref;
|
||||
const char *auth_id;
|
||||
int obj_flags;
|
||||
} prdata;
|
||||
|
||||
typedef struct keyinfo_st {
|
||||
int fileid;
|
||||
sc_pkcs15_id_t id;
|
||||
unsigned int modulus_len;
|
||||
u8 modulus[1024/8];
|
||||
} keyinfo;
|
||||
|
||||
#define USAGE_NONREP SC_PKCS15_PRKEY_USAGE_NONREPUDIATION
|
||||
#define USAGE_KE SC_PKCS15_PRKEY_USAGE_ENCRYPT | \
|
||||
SC_PKCS15_PRKEY_USAGE_DECRYPT | \
|
||||
SC_PKCS15_PRKEY_USAGE_WRAP | \
|
||||
SC_PKCS15_PRKEY_USAGE_UNWRAP
|
||||
#define USAGE_AUT SC_PKCS15_PRKEY_USAGE_ENCRYPT | \
|
||||
SC_PKCS15_PRKEY_USAGE_DECRYPT | \
|
||||
SC_PKCS15_PRKEY_USAGE_WRAP | \
|
||||
SC_PKCS15_PRKEY_USAGE_UNWRAP | \
|
||||
SC_PKCS15_PRKEY_USAGE_SIGN
|
||||
|
||||
static const u8 gemsafe_aid[] = {0xA0, 0x00, 0x00, 0x00, 0x18,
|
||||
0x0F, 0x00, 0x00, 0x01, 0x63, 0x00, 0x01};
|
||||
|
||||
static int my_pin_cmd(sc_card_t * card, struct sc_pin_cmd_data * data,
|
||||
int *tries_left)
|
||||
{
|
||||
/* GemSAFE pin uses a null terminated string with 0xFF */
|
||||
/* so we need to add the 0x00 to the pin then pad with 0xFF */
|
||||
|
||||
int r;
|
||||
const u8 *saved_data = NULL;
|
||||
int saved_len = 0;
|
||||
char newpin[8];
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 2);
|
||||
|
||||
memset(newpin, 0xff, sizeof(newpin));
|
||||
|
||||
if (data->pin1.data && data->pin1.len < 8 && data->pin1.len > 0) {
|
||||
memcpy(newpin,data->pin1.data, data->pin1.len);
|
||||
newpin[data->pin1.len] = 0x00;
|
||||
|
||||
sc_debug(card->ctx, "pin len=%d", data->pin1.len);
|
||||
|
||||
saved_data = data->pin1.data;
|
||||
saved_len = data->pin1.len;
|
||||
data->pin1.data = newpin;
|
||||
data->pin1.len = sizeof(newpin);
|
||||
}
|
||||
|
||||
r = pin_cmd_save(card, data, tries_left);
|
||||
|
||||
if (saved_data) {
|
||||
data->pin1.data = saved_data;
|
||||
data->pin1.len = saved_len;
|
||||
}
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, 2, r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int is_seq(unsigned char * seq, int *seq_size, int *seq_len)
|
||||
{
|
||||
int i,j,k;
|
||||
|
||||
if (seq[0] != 0x30)
|
||||
return 0; /* not a sequence */
|
||||
if (seq[1] & 0x80) {
|
||||
i = seq[1] & 0x7f;
|
||||
if (i > 2 || i == 0)
|
||||
return 0; /* cert would be bigger then 65k or zero */
|
||||
if (seq[2] == 0)
|
||||
return 0; /* DER would not have extra zero */
|
||||
k = 0;
|
||||
for (j = 0; j < i; j++) {
|
||||
k = (k << 8) + seq[j + 2];
|
||||
}
|
||||
if (k < 128)
|
||||
return 0; /* DER would have used single byte for len */
|
||||
} else {
|
||||
i = 0;
|
||||
k = seq[1];
|
||||
}
|
||||
|
||||
*seq_size = i + 2;
|
||||
*seq_len = k;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gemsafe_detect_card(sc_pkcs15_card_t *p15card)
|
||||
{
|
||||
sc_card_t *card = p15card->card;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
|
||||
if (strcmp(card->name, "Gemplus GPK"))
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static int sc_pkcs15emu_gemsafe_init(sc_pkcs15_card_t *p15card)
|
||||
{
|
||||
const cdata certs[] = {
|
||||
{"User certificate",0, "","1", 0},
|
||||
{NULL, 0, NULL, 0, 0}
|
||||
};
|
||||
|
||||
const pindata pins[] = {
|
||||
{ "1", "pin", "3F000200", 0x00,
|
||||
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
|
||||
8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
|
||||
SC_PKCS15_PIN_FLAG_LOCAL, -1, 0x00,
|
||||
SC_PKCS15_CO_FLAG_PRIVATE },
|
||||
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
const prdata prkeys[] = {
|
||||
{ "1", "AUTH key", 1024, USAGE_AUT, "3F0002000009",
|
||||
0x00, "1", SC_PKCS15_CO_FLAG_PRIVATE},
|
||||
{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
int r, i, j;
|
||||
int dfpath;
|
||||
sc_path_t path;
|
||||
sc_file_t *file = NULL;
|
||||
sc_card_t *card = p15card->card;
|
||||
unsigned char *gsdata = NULL;
|
||||
unsigned int idxlen, idx1, idx2, seq_len1, seq_len2, seq_size1, seq_size2;
|
||||
sc_serial_number_t serial;
|
||||
|
||||
u8 sysrec[7];
|
||||
int num_keyinfo = 0;
|
||||
keyinfo keyinfo[8]; /* will loook for 8 keys */
|
||||
u8 modulus_buf[ 1 + 1024 / 8]; /* tag+modulus */
|
||||
u8 *cp;
|
||||
char buf[256];
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 1);
|
||||
|
||||
/* could read this off card if needed */
|
||||
|
||||
p15card->label = strdup("GemSAFE");
|
||||
p15card->manufacturer_id = strdup(MANU_ID);
|
||||
/* get serial number */
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
||||
r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
|
||||
if (r != SC_SUCCESS)
|
||||
return SC_ERROR_INTERNAL;
|
||||
p15card->serial_number = strdup(buf);
|
||||
|
||||
/* test if we have a gemsafe app df */
|
||||
memset(&path, 0, sizeof(path));
|
||||
memcpy(path.value, gemsafe_aid, sizeof(gemsafe_aid));
|
||||
path.len = sizeof(gemsafe_aid);
|
||||
path.type = SC_PATH_TYPE_DF_NAME;
|
||||
r = sc_select_file(card, &path, &file);
|
||||
if (r < 0)
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
|
||||
/* we will use dfpath in all other references */
|
||||
dfpath = file->id;
|
||||
free(file);
|
||||
file = NULL;
|
||||
|
||||
sc_debug(card->ctx, "GemSafe file found, id=%d",dfpath);
|
||||
|
||||
/* There may be more then one key in the directory. */
|
||||
/* we need to find them so we can associate them with the */
|
||||
/* the certificate. The files are 0007 to 000f */
|
||||
|
||||
for (i = 7; i < 16; i++) {
|
||||
path.value[0] = 0x00;
|
||||
path.value[1] = i;
|
||||
path.len = 2;
|
||||
path.type = SC_PATH_TYPE_FILE_ID;
|
||||
card->ctx->suppress_errors++; /* file may not exist, and not an error */
|
||||
r = sc_select_file(card, &path, NULL);
|
||||
card->ctx->suppress_errors--;
|
||||
if (r < 0)
|
||||
continue;
|
||||
card->ctx->suppress_errors++;
|
||||
r = sc_read_record(card, 1, sysrec, sizeof(sysrec), SC_RECORD_BY_REC_NR);
|
||||
card->ctx->suppress_errors--;
|
||||
if (r != 7 || sysrec[0] != 0) {
|
||||
continue;
|
||||
}
|
||||
if (sysrec[5] != 0x00) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (sysrec[1]) {
|
||||
case 0x00: keyinfo[num_keyinfo].modulus_len = 512 / 8; break;
|
||||
case 0x10: keyinfo[num_keyinfo].modulus_len = 768 / 8; break;
|
||||
case 0x11: keyinfo[num_keyinfo].modulus_len = 1024 / 8; break;
|
||||
default:
|
||||
sc_error(card->ctx, "Unsupported modulus length");
|
||||
continue;
|
||||
}
|
||||
|
||||
keyinfo[num_keyinfo].fileid = i;
|
||||
sc_pkcs15_format_id("NONE", &keyinfo[num_keyinfo].id);
|
||||
|
||||
sc_debug(card->ctx,"reading modulus");
|
||||
r = sc_read_record(card, 2, modulus_buf,
|
||||
keyinfo[num_keyinfo].modulus_len+1, SC_RECORD_BY_REC_NR);
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
/* need to reverse the modulus skiping the tag */
|
||||
j = keyinfo[num_keyinfo].modulus_len;
|
||||
cp = keyinfo[num_keyinfo].modulus;
|
||||
while (j--)
|
||||
*cp++ = modulus_buf[j + 1];
|
||||
num_keyinfo++;
|
||||
}
|
||||
|
||||
/* Get the gemsafe data with the cert */
|
||||
sc_format_path("3F000200004", &path);
|
||||
|
||||
/* file.id has the real DF of the GemSAFE file from above*/
|
||||
path.value[2] = dfpath >> 8;
|
||||
path.value[3] = dfpath & 0xff;
|
||||
|
||||
if (sc_select_file(card, &path, &file) < 0) {
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
}
|
||||
|
||||
/* the GemSAFE file has our cert, but we do not know the format */
|
||||
/* of the file. But we do know a cert has SEQ SEQ SEQOF INT 2 */
|
||||
/* so we will look for that. We assume cert is larger then 127 bytes */
|
||||
/* and less then 65K, and must be fit in the file->size */
|
||||
/* There is a chance that we might find something that is not */
|
||||
/* a cert, but the chances are low. If GemPlus ever publishes */
|
||||
/* the format of the file, we can used that instead. */
|
||||
|
||||
/* For performance reasons we will only */
|
||||
/* read part of the file , as it is about 6100 bytes */
|
||||
|
||||
gsdata = (unsigned char *) malloc(file->size);
|
||||
|
||||
if (!gsdata)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
/* set indcies of data in gsdata */
|
||||
idx1 = 0; /* start point */
|
||||
idx2 = 0; /* index of last data read so far */
|
||||
|
||||
|
||||
/* set certs We only have one we are interested in */
|
||||
/* but the read loop is set up to allow for more in future */
|
||||
|
||||
for (i = 0; certs[i].label; i++) {
|
||||
struct sc_pkcs15_cert_info cert_info;
|
||||
struct sc_pkcs15_object cert_obj;
|
||||
sc_pkcs15_cert_t *cert_out;
|
||||
|
||||
memset(&cert_info, 0, sizeof(cert_info));
|
||||
memset(&cert_obj, 0, sizeof(cert_obj));
|
||||
|
||||
sc_pkcs15_format_id(certs[i].id, &cert_info.id);
|
||||
cert_info.authority = certs[i].authority;
|
||||
|
||||
strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
|
||||
cert_obj.flags = certs[i].obj_flags;
|
||||
|
||||
while (idx1 < file->size - 16) { /* actually 13 for all these tests */
|
||||
if (idx1 > idx2 - 16) { /* need more data in buff */
|
||||
idxlen = 248; /* read in next 248 bytes */
|
||||
if (idxlen > file->size - idx2)
|
||||
idxlen = file->size - idx2;
|
||||
r = sc_read_binary(card, idx2, gsdata + idx2, idxlen, 0);
|
||||
if (r < 0)
|
||||
break;
|
||||
idx2 = idx2 + idxlen;
|
||||
}
|
||||
|
||||
if ( gsdata[idx1] == 0x30 &&
|
||||
is_seq(gsdata + idx1, &seq_size1, &seq_len1) &&
|
||||
is_seq(gsdata + idx1 + seq_size1, &seq_size2, &seq_len2) &&
|
||||
gsdata[idx1 + seq_size1 + seq_size2 + 0] == 0xa0 &&
|
||||
gsdata[idx1 + seq_size1 + seq_size2 + 1] == 0x03 &&
|
||||
gsdata[idx1 + seq_size1 + seq_size2 + 2] == 0x02 &&
|
||||
gsdata[idx1 + seq_size1 + seq_size2 + 3] == 0x01 &&
|
||||
gsdata[idx1 + seq_size1 + seq_size2 + 4] == 0x02 &&
|
||||
idx1 + 4 + seq_len1 < file->size) {
|
||||
/* we have a cert (I hope) */
|
||||
/* read in rest if needed */
|
||||
idxlen = idx1 + seq_len1 + 4 - idx2;
|
||||
if (idxlen > 0) {
|
||||
idxlen = (idxlen + 3) & 0xfffffffc;
|
||||
r = sc_read_binary(card, idx2, gsdata + idx2, idxlen, 0);
|
||||
if (r < 0)
|
||||
break; /* can not read cert */
|
||||
idx2 = idx2 + idxlen;
|
||||
}
|
||||
cert_info.value.len = seq_len1 + 4;
|
||||
sc_debug(card->ctx, "Found cert at offset %d", idx1);
|
||||
cert_info.value.value = (unsigned char *)
|
||||
malloc(cert_info.value.len);
|
||||
if (!cert_info.value.value)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
memcpy(cert_info.value.value, gsdata + idx1, cert_info.value.len);
|
||||
idx1 = idx1 + cert_info.value.len;
|
||||
break;
|
||||
}
|
||||
idx1++;
|
||||
}
|
||||
|
||||
if (cert_info.value.value == NULL)
|
||||
break; /* cert not found, no more certs */
|
||||
|
||||
r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
|
||||
if (r < 0)
|
||||
return SC_ERROR_INTERNAL;
|
||||
|
||||
/* now lets see if we have a matching key for this cert */
|
||||
|
||||
r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out);
|
||||
if (r < 0)
|
||||
return SC_ERROR_INTERNAL;
|
||||
|
||||
for (j = 0; j < num_keyinfo; j++) {
|
||||
if (cert_out->key.u.rsa.modulus.len == keyinfo[j].modulus_len &&
|
||||
memcmp(cert_out->key.u.rsa.modulus.data,
|
||||
&keyinfo[j].modulus, cert_out->key.u.rsa.modulus.len) == 0) {
|
||||
memcpy(&keyinfo[j].id, &cert_info.id, sizeof(sc_pkcs15_id_t));
|
||||
sc_debug(card->ctx, "found match");
|
||||
}
|
||||
}
|
||||
sc_pkcs15_free_certificate(cert_out);
|
||||
}
|
||||
|
||||
if (gsdata)
|
||||
free(gsdata);
|
||||
|
||||
/* set pins */
|
||||
|
||||
/* GemSAFE uses different padding, so need to trap */
|
||||
/* the pin_cmd and reset the padding */
|
||||
|
||||
pin_cmd_save = card->ops->pin_cmd;
|
||||
card->ops->pin_cmd = my_pin_cmd;
|
||||
|
||||
for (i = 0; pins[i].label; i++) {
|
||||
struct sc_pkcs15_pin_info pin_info;
|
||||
struct sc_pkcs15_object pin_obj;
|
||||
|
||||
memset(&pin_info, 0, sizeof(pin_info));
|
||||
memset(&pin_obj, 0, sizeof(pin_obj));
|
||||
|
||||
sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id);
|
||||
pin_info.reference = pins[i].ref;
|
||||
pin_info.flags = pins[i].flags;
|
||||
pin_info.type = pins[i].type;
|
||||
pin_info.min_length = pins[i].minlen;
|
||||
pin_info.stored_length = pins[i].storedlen;
|
||||
pin_info.max_length = pins[i].maxlen;
|
||||
pin_info.pad_char = pins[i].pad_char;
|
||||
sc_format_path(pins[i].path, &pin_info.path);
|
||||
pin_info.path.value[2] = dfpath >> 8;
|
||||
pin_info.path.value[3] = dfpath & 0xff;
|
||||
pin_info.tries_left = -1;
|
||||
|
||||
strncpy(pin_obj.label, pins[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
|
||||
pin_obj.flags = pins[i].obj_flags;
|
||||
|
||||
r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
|
||||
if (r < 0)
|
||||
return SC_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
/* needs work, as we may want to add more then one key */
|
||||
/* but not sure what the other keys do */
|
||||
|
||||
/* set private keys */
|
||||
for (i = 0; prkeys[i].label; i++) {
|
||||
struct sc_pkcs15_prkey_info prkey_info;
|
||||
struct sc_pkcs15_object prkey_obj;
|
||||
|
||||
memset(&prkey_info, 0, sizeof(prkey_info));
|
||||
memset(&prkey_obj, 0, sizeof(prkey_obj));
|
||||
|
||||
sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id);
|
||||
prkey_info.usage = prkeys[i].usage;
|
||||
prkey_info.native = 1;
|
||||
prkey_info.key_reference = prkeys[i].ref;
|
||||
prkey_info.modulus_length= prkeys[i].modulus_len;
|
||||
sc_format_path(prkeys[i].path, &prkey_info.path);
|
||||
|
||||
/*DEE need to look for them by reading and checking mudulus vs cert */
|
||||
|
||||
prkey_info.path.value[2] = dfpath >> 8;
|
||||
prkey_info.path.value[3] = dfpath & 0xff;
|
||||
|
||||
/* will use the default path, unless we found a key with */
|
||||
/* the same modulus as the cert(s) we already added */
|
||||
/* This allows us to have a card with a key but no cert */
|
||||
|
||||
for (j = 0; j < num_keyinfo; j++) {
|
||||
if (sc_pkcs15_compare_id(&keyinfo[j].id, &prkey_info.id)) {
|
||||
sc_debug(card->ctx, "found key in file %d for id %d",
|
||||
keyinfo[j].fileid, prkey_info.id);
|
||||
prkey_info.path.value[4] = keyinfo[j].fileid >> 8;
|
||||
prkey_info.path.value[5] = keyinfo[j].fileid & 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(prkey_obj.label, prkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
|
||||
prkey_obj.flags = prkeys[i].obj_flags;
|
||||
if (prkeys[i].auth_id)
|
||||
sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id);
|
||||
|
||||
r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
|
||||
if (r < 0)
|
||||
return SC_ERROR_INTERNAL;
|
||||
}
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
int sc_pkcs15emu_gemsafe_init_ex(sc_pkcs15_card_t *p15card,
|
||||
sc_pkcs15emu_opt_t *opts)
|
||||
{
|
||||
sc_card_t *card = p15card->card;
|
||||
sc_context_t *ctx = card->ctx;
|
||||
|
||||
sc_debug(ctx, "Entering %s", __FUNCTION__);
|
||||
|
||||
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
|
||||
return sc_pkcs15emu_gemsafe_init(p15card);
|
||||
else {
|
||||
int r = gemsafe_detect_card(p15card);
|
||||
if (r)
|
||||
return SC_ERROR_WRONG_CARD;
|
||||
return sc_pkcs15emu_gemsafe_init(p15card);
|
||||
}
|
||||
}
|
@ -40,6 +40,8 @@ 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 *);
|
||||
extern int sc_pkcs15emu_gemsafe_init_ex(sc_pkcs15_card_t *p15card,
|
||||
sc_pkcs15emu_opt_t *opts);
|
||||
|
||||
static struct {
|
||||
const char * name;
|
||||
@ -51,6 +53,7 @@ static struct {
|
||||
{ "netkey", sc_pkcs15emu_netkey_init_ex },
|
||||
{ "esteid", sc_pkcs15emu_esteid_init_ex },
|
||||
{ "postecert", sc_pkcs15emu_postecert_init_ex },
|
||||
{ "gemsafe", sc_pkcs15emu_gemsafe_init_ex },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user