2001-11-06 18:34:19 +00:00
|
|
|
|
/*
|
|
|
|
|
* sc-pkcs15.c: PKCS#15 general functions
|
2001-11-01 15:43:20 +00:00
|
|
|
|
*
|
2001-11-06 18:34:19 +00:00
|
|
|
|
* Copyright (C) 2001 Juha Yrj<EFBFBD>l<EFBFBD> <juha.yrjola@iki.fi>
|
|
|
|
|
*
|
|
|
|
|
* 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,
|
2001-11-01 15:43:20 +00:00
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2001-11-06 18:34:19 +00:00
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
2001-11-01 15:43:20 +00:00
|
|
|
|
*
|
2001-11-06 18:34:19 +00:00
|
|
|
|
* 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
|
2001-11-01 15:43:20 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2001-12-25 20:45:48 +00:00
|
|
|
|
#include "sc-internal.h"
|
2001-11-24 13:32:52 +00:00
|
|
|
|
#include "opensc-pkcs15.h"
|
2001-11-06 18:34:19 +00:00
|
|
|
|
#include "sc-asn1.h"
|
2001-12-13 21:19:11 +00:00
|
|
|
|
#include "sc-log.h"
|
2001-11-01 15:43:20 +00:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
void sc_pkcs15_print_card(const struct sc_pkcs15_card *card)
|
|
|
|
|
{
|
|
|
|
|
const char *flags[] = {
|
|
|
|
|
"Read-only",
|
|
|
|
|
"Login required",
|
|
|
|
|
"PRN generation",
|
|
|
|
|
"EID compliant"
|
|
|
|
|
};
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
assert(card != NULL);
|
|
|
|
|
printf("PKCS#15 Card [%s]:\n", card->label);
|
|
|
|
|
printf("\tVersion : %d\n", card->version);
|
|
|
|
|
printf("\tSerial number : %s\n", card->serial_number);
|
|
|
|
|
printf("\tManufacturer ID: %s\n", card->manufacturer_id);
|
|
|
|
|
printf("\tFlags : ");
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
int count = 0;
|
|
|
|
|
if ((card->flags >> i) & 1) {
|
|
|
|
|
if (count)
|
|
|
|
|
printf(", ");
|
|
|
|
|
printf("%s", flags[i]);
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-30 21:17:34 +00:00
|
|
|
|
void parse_tokeninfo(struct sc_pkcs15_card *card, const u8 * buf, size_t buflen)
|
2001-11-01 15:43:20 +00:00
|
|
|
|
{
|
2001-12-16 18:46:32 +00:00
|
|
|
|
int i, r;
|
|
|
|
|
u8 serial[128];
|
|
|
|
|
int serial_len = sizeof(serial);
|
|
|
|
|
u8 mnfid[128];
|
|
|
|
|
int mnfid_len = sizeof(mnfid);
|
|
|
|
|
int flags_len = sizeof(card->flags);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
|
2001-12-16 18:46:32 +00:00
|
|
|
|
struct sc_asn1_struct asn1_tokeninfo[] = {
|
|
|
|
|
{ "version", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &card->version },
|
|
|
|
|
{ "serialNumber", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0, serial, &serial_len },
|
|
|
|
|
{ "manufacturerID", SC_ASN1_UTF8STRING, ASN1_UTF8STRING, SC_ASN1_OPTIONAL, mnfid, &mnfid_len },
|
|
|
|
|
{ "label", SC_ASN1_UTF8STRING, SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, NULL },
|
|
|
|
|
{ "tokenflags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, 0, &card->flags, &flags_len },
|
|
|
|
|
{ "seInfo", SC_ASN1_SEQUENCE, SC_ASN1_CONS | ASN1_SEQUENCE, SC_ASN1_OPTIONAL, NULL },
|
2001-12-19 21:58:04 +00:00
|
|
|
|
{ "recordInfo", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL, NULL },
|
|
|
|
|
{ "supportedAlgorithms", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 2, SC_ASN1_OPTIONAL, NULL },
|
|
|
|
|
{ NULL }
|
|
|
|
|
};
|
2001-12-16 18:46:32 +00:00
|
|
|
|
|
2001-12-29 19:03:46 +00:00
|
|
|
|
buf = sc_asn1_verify_tag(card->card->ctx, buf, buflen, SC_ASN1_CONS | ASN1_SEQUENCE, &buflen);
|
2001-12-16 18:46:32 +00:00
|
|
|
|
if (buf == NULL) {
|
|
|
|
|
error(card->card->ctx, "invalid EF(TokenInfo)\n");
|
2001-11-01 15:43:20 +00:00
|
|
|
|
goto err;
|
2001-12-16 18:46:32 +00:00
|
|
|
|
}
|
|
|
|
|
r = sc_asn1_parse(card->card->ctx, asn1_tokeninfo, buf, buflen, NULL, NULL);
|
|
|
|
|
if (r) {
|
|
|
|
|
error(card->card->ctx, "ASN.1 parsing failed: %s\n", sc_strerror(r));
|
2001-11-01 15:43:20 +00:00
|
|
|
|
goto err;
|
2001-12-16 18:46:32 +00:00
|
|
|
|
}
|
|
|
|
|
card->version += 1;
|
|
|
|
|
card->serial_number = malloc(serial_len * 2 + 1);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
card->serial_number[0] = 0;
|
2001-12-16 18:46:32 +00:00
|
|
|
|
for (i = 0; i < serial_len; i++) {
|
2001-11-01 15:43:20 +00:00
|
|
|
|
char byte[3];
|
|
|
|
|
|
2001-12-16 18:46:32 +00:00
|
|
|
|
sprintf(byte, "%02X", serial[i]);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
strcat(card->serial_number, byte);
|
|
|
|
|
}
|
2001-12-20 13:57:58 +00:00
|
|
|
|
if (card->manufacturer_id == NULL) {
|
|
|
|
|
if (asn1_tokeninfo[2].flags & SC_ASN1_PRESENT)
|
2001-12-30 21:17:34 +00:00
|
|
|
|
card->manufacturer_id = strdup((char *) mnfid);
|
2001-12-20 13:57:58 +00:00
|
|
|
|
else
|
|
|
|
|
card->manufacturer_id = strdup("(unknown)");
|
|
|
|
|
}
|
2001-11-01 15:43:20 +00:00
|
|
|
|
return;
|
2001-12-16 18:46:32 +00:00
|
|
|
|
err:
|
2001-11-01 15:43:20 +00:00
|
|
|
|
if (card->serial_number == NULL)
|
|
|
|
|
card->serial_number = strdup("(unknown)");
|
|
|
|
|
if (card->manufacturer_id == NULL)
|
|
|
|
|
card->manufacturer_id = strdup("(unknown)");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-30 21:17:34 +00:00
|
|
|
|
static int parse_dir(const u8 * buf, size_t buflen, struct sc_pkcs15_card *card)
|
2001-11-01 15:43:20 +00:00
|
|
|
|
{
|
2001-12-30 21:17:34 +00:00
|
|
|
|
const u8 *aidref = (const u8 *) "\xA0\x00\x00\x00\x63PKCS-15";
|
2001-12-16 18:46:32 +00:00
|
|
|
|
const int aidref_len = 12;
|
|
|
|
|
int r;
|
|
|
|
|
u8 aid[128], label[128], path[128];
|
|
|
|
|
int aid_len = sizeof(aid), label_len = sizeof(label),
|
|
|
|
|
path_len = sizeof(path);
|
|
|
|
|
|
|
|
|
|
struct sc_asn1_struct asn1_ddo[] = {
|
|
|
|
|
{ "oid", SC_ASN1_OBJECT, ASN1_OBJECT, 0, NULL },
|
|
|
|
|
{ "odfPath", SC_ASN1_PATH, SC_ASN1_CONS | ASN1_SEQUENCE, SC_ASN1_OPTIONAL, &card->file_odf.path },
|
|
|
|
|
{ "tokenInfoPath", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, &card->file_tokeninfo.path },
|
|
|
|
|
{ "unusedPath", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL, NULL },
|
|
|
|
|
{ NULL }
|
|
|
|
|
};
|
|
|
|
|
struct sc_asn1_struct asn1_dir[] = {
|
|
|
|
|
{ "aid", SC_ASN1_OCTET_STRING, SC_ASN1_APP | 15, 0, aid, &aid_len },
|
|
|
|
|
{ "label", SC_ASN1_UTF8STRING, SC_ASN1_APP | 16, SC_ASN1_OPTIONAL, label, &label_len },
|
|
|
|
|
{ "path", SC_ASN1_OCTET_STRING, SC_ASN1_APP | 17, 0, path, &path_len },
|
|
|
|
|
{ "ddo", SC_ASN1_STRUCT, SC_ASN1_APP | 19 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_ddo },
|
|
|
|
|
{ NULL }
|
|
|
|
|
};
|
2001-11-01 15:43:20 +00:00
|
|
|
|
|
2001-12-29 19:03:46 +00:00
|
|
|
|
buf = sc_asn1_verify_tag(card->card->ctx, buf, buflen, SC_ASN1_APP | 1 | SC_ASN1_CONS, &buflen);
|
2001-12-16 18:46:32 +00:00
|
|
|
|
if (buf == NULL) {
|
|
|
|
|
error(card->card->ctx, "No [APPLICATION 1] tag in EF(DIR)\n");
|
2001-11-01 15:43:20 +00:00
|
|
|
|
return -1;
|
2001-12-16 18:46:32 +00:00
|
|
|
|
}
|
|
|
|
|
r = sc_asn1_parse(card->card->ctx, asn1_dir, buf, buflen, NULL, NULL);
|
|
|
|
|
if (r) {
|
|
|
|
|
error(card->card->ctx, "EF(DIR) parsing failed: %s\n",
|
|
|
|
|
sc_strerror(r));
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
if (aid_len != aidref_len || memcmp(aidref, aid, aid_len) != 0) {
|
|
|
|
|
error(card->card->ctx, "AID in EF(DIR) is invalid\n");
|
2001-11-01 15:43:20 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
2001-12-16 18:46:32 +00:00
|
|
|
|
if (asn1_dir[1].flags & SC_ASN1_PRESENT)
|
2001-12-30 21:17:34 +00:00
|
|
|
|
card->label = strdup((char *) label);
|
2001-12-16 18:46:32 +00:00
|
|
|
|
else
|
|
|
|
|
card->label = strdup("(unknown)");
|
|
|
|
|
memcpy(card->file_app.path.value, path, path_len);
|
|
|
|
|
card->file_app.path.len = path_len;
|
2001-12-22 20:43:09 +00:00
|
|
|
|
card->file_app.path.type = SC_PATH_TYPE_PATH;
|
2001-12-16 18:46:32 +00:00
|
|
|
|
|
2001-11-01 15:43:20 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int parse_odf(const u8 * buf, int buflen, struct sc_pkcs15_card *card)
|
|
|
|
|
{
|
2001-12-16 18:46:32 +00:00
|
|
|
|
const u8 *p = buf;
|
|
|
|
|
int r, left = buflen;
|
|
|
|
|
struct sc_path path;
|
|
|
|
|
struct sc_asn1_struct asn1_obj_or_path[] = {
|
|
|
|
|
{ "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, &path },
|
2001-12-19 21:58:04 +00:00
|
|
|
|
{ NULL }
|
|
|
|
|
};
|
2001-12-16 18:46:32 +00:00
|
|
|
|
struct sc_asn1_struct asn1_odf[] = {
|
|
|
|
|
{ "privateKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, 0, asn1_obj_or_path },
|
|
|
|
|
{ "certificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 4 | SC_ASN1_CONS, 0, asn1_obj_or_path },
|
|
|
|
|
{ "trustedCertificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 5 | SC_ASN1_CONS, 0, asn1_obj_or_path },
|
|
|
|
|
{ "dataObjects", SC_ASN1_STRUCT, SC_ASN1_CTX | 7 | SC_ASN1_CONS, 0, asn1_obj_or_path },
|
|
|
|
|
{ "authObjects", SC_ASN1_STRUCT, SC_ASN1_CTX | 8 | SC_ASN1_CONS, 0, asn1_obj_or_path },
|
2001-12-19 21:58:04 +00:00
|
|
|
|
{ NULL }
|
2001-12-16 18:46:32 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
while (left > 0) {
|
|
|
|
|
r = sc_asn1_parse_choice(card->card->ctx, asn1_odf, p, left, &p, &left);
|
|
|
|
|
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
|
|
|
|
|
break;
|
|
|
|
|
if (r < 0)
|
|
|
|
|
return r;
|
|
|
|
|
switch (r) {
|
|
|
|
|
case 0:
|
2001-12-22 20:43:09 +00:00
|
|
|
|
if (card->file_prkdf.path.len)
|
|
|
|
|
error(card->card->ctx, "warning: card has too many PrKDF's\n");
|
2001-12-16 18:46:32 +00:00
|
|
|
|
card->file_prkdf.path = path;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
case 2:
|
|
|
|
|
if (card->cdf_count == SC_PKCS15_MAX_CDFS) {
|
|
|
|
|
error(card->card->ctx, "too many CDFs on card\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
card->file_cdf[card->cdf_count].path = path;
|
|
|
|
|
card->cdf_count++;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
2001-12-22 20:43:09 +00:00
|
|
|
|
if (card->file_dodf.path.len)
|
|
|
|
|
error(card->card->ctx, "warning: card has too many DODF's\n");
|
2001-12-16 18:46:32 +00:00
|
|
|
|
card->file_dodf.path = path;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
if (card->aodf_count == SC_PKCS15_MAX_AODFS) {
|
|
|
|
|
error(card->card->ctx, "too many AODFs on card\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
card->file_aodf[card->aodf_count].path = path;
|
|
|
|
|
card->aodf_count++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-11-01 15:43:20 +00:00
|
|
|
|
return 0;
|
2001-11-14 13:43:39 +00:00
|
|
|
|
}
|
2001-11-01 15:43:20 +00:00
|
|
|
|
|
2001-11-26 16:14:22 +00:00
|
|
|
|
static const struct sc_pkcs15_defaults * find_defaults(u8 *dir, int dirlen)
|
|
|
|
|
{
|
2001-12-22 20:43:09 +00:00
|
|
|
|
#if 0
|
2001-11-26 16:14:22 +00:00
|
|
|
|
int i = 0;
|
|
|
|
|
const struct sc_pkcs15_defaults *match = NULL;
|
|
|
|
|
|
|
|
|
|
while (sc_card_table[i].atr != NULL) {
|
|
|
|
|
u8 defdir[128];
|
|
|
|
|
int len = sizeof(defdir);
|
|
|
|
|
const struct sc_pkcs15_defaults *def = &sc_pkcs15_card_table[i];
|
|
|
|
|
const char *dirp = def->ef_dir_dump;
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
if (dirp == NULL)
|
|
|
|
|
break;
|
|
|
|
|
if (sc_hex_to_bin(dirp, defdir, &len))
|
|
|
|
|
continue;
|
|
|
|
|
if (memcmp(dir, defdir, len) != 0)
|
|
|
|
|
continue;
|
|
|
|
|
match = def;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return match;
|
2001-12-22 20:43:09 +00:00
|
|
|
|
#endif
|
|
|
|
|
return NULL;
|
2001-11-26 16:14:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-21 23:34:47 +00:00
|
|
|
|
int sc_pkcs15_bind(struct sc_card *card,
|
2001-11-01 15:43:20 +00:00
|
|
|
|
struct sc_pkcs15_card **p15card_out)
|
|
|
|
|
{
|
|
|
|
|
unsigned char buf[MAX_BUFFER_SIZE];
|
|
|
|
|
int err, len;
|
|
|
|
|
struct sc_pkcs15_card *p15card = NULL;
|
|
|
|
|
struct sc_path tmppath;
|
2001-11-26 16:14:22 +00:00
|
|
|
|
const struct sc_pkcs15_defaults *defaults = NULL;
|
2001-12-25 20:45:48 +00:00
|
|
|
|
struct sc_context *ctx;
|
2001-11-01 15:43:20 +00:00
|
|
|
|
|
2001-12-25 20:45:48 +00:00
|
|
|
|
assert(sc_card_valid(card) && p15card_out != NULL);
|
|
|
|
|
ctx = card->ctx;
|
|
|
|
|
SC_FUNC_CALLED(ctx, 1);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
p15card = malloc(sizeof(struct sc_pkcs15_card));
|
|
|
|
|
if (p15card == NULL)
|
|
|
|
|
return SC_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
memset(p15card, 0, sizeof(struct sc_pkcs15_card));
|
|
|
|
|
p15card->card = card;
|
2001-11-17 14:55:41 +00:00
|
|
|
|
|
2001-12-22 20:43:09 +00:00
|
|
|
|
sc_format_path("2F00", &tmppath);
|
2001-12-25 20:45:48 +00:00
|
|
|
|
err = sc_lock(card);
|
|
|
|
|
if (err) {
|
|
|
|
|
error(ctx, "sc_lock() failed: %s\n", sc_strerror(err));
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2001-12-22 23:51:12 +00:00
|
|
|
|
err = sc_select_file(card, &tmppath, &p15card->file_dir);
|
2001-12-25 20:45:48 +00:00
|
|
|
|
if (err) {
|
|
|
|
|
error(ctx, "Error selecting EF(DIR): %s\n", sc_strerror(err));
|
2001-11-01 15:43:20 +00:00
|
|
|
|
goto error;
|
2001-12-25 20:45:48 +00:00
|
|
|
|
}
|
2001-12-29 02:07:32 +00:00
|
|
|
|
err = sc_read_binary(card, 0, buf, p15card->file_dir.size, 0);
|
2001-12-25 20:45:48 +00:00
|
|
|
|
if (err < 0) {
|
|
|
|
|
error(ctx, "Error reading EF(DIR): %s\n", sc_strerror(err));
|
2001-11-01 15:43:20 +00:00
|
|
|
|
goto error;
|
2001-12-25 20:45:48 +00:00
|
|
|
|
}
|
2001-11-01 15:43:20 +00:00
|
|
|
|
if (err <= 2) {
|
|
|
|
|
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
2001-12-25 20:45:48 +00:00
|
|
|
|
error(ctx, "Error reading EF(DIR): too few bytes read\n");
|
2001-11-01 15:43:20 +00:00
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
len = err;
|
|
|
|
|
if (parse_dir(buf, len, p15card)) {
|
|
|
|
|
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
2001-12-25 20:45:48 +00:00
|
|
|
|
error(ctx, "Error parsing EF(DIR)\n");
|
2001-11-01 15:43:20 +00:00
|
|
|
|
goto error;
|
|
|
|
|
}
|
2001-12-22 20:43:09 +00:00
|
|
|
|
if (p15card->use_cache)
|
2001-12-16 18:46:32 +00:00
|
|
|
|
defaults = find_defaults(buf, err);
|
2001-11-26 16:14:22 +00:00
|
|
|
|
if (defaults == NULL) {
|
2001-12-16 18:46:32 +00:00
|
|
|
|
if (p15card->file_odf.path.len == 0) {
|
|
|
|
|
tmppath = p15card->file_app.path;
|
|
|
|
|
memcpy(tmppath.value + tmppath.len, "\x50\x31", 2);
|
|
|
|
|
tmppath.len += 2;
|
|
|
|
|
} else
|
|
|
|
|
tmppath = p15card->file_odf.path;
|
2001-12-22 20:43:09 +00:00
|
|
|
|
|
2001-12-22 23:51:12 +00:00
|
|
|
|
err = sc_select_file(card, &tmppath, &p15card->file_odf);
|
2001-12-25 20:45:48 +00:00
|
|
|
|
if (err) /* FIXME: finish writing error stuff */
|
2001-11-26 16:14:22 +00:00
|
|
|
|
goto error;
|
2001-12-29 02:07:32 +00:00
|
|
|
|
err = sc_read_binary(card, 0, buf, p15card->file_odf.size, 0);
|
2001-11-26 16:14:22 +00:00
|
|
|
|
if (err < 0)
|
|
|
|
|
goto error;
|
|
|
|
|
if (err < 2) {
|
|
|
|
|
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
len = err;
|
|
|
|
|
if (parse_odf(buf, len, p15card)) {
|
|
|
|
|
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2001-12-16 18:46:32 +00:00
|
|
|
|
if (p15card->file_tokeninfo.path.len == 0) {
|
|
|
|
|
tmppath.len -= 2;
|
|
|
|
|
memcpy(tmppath.value + tmppath.len, "\x50\x32", 2);
|
|
|
|
|
tmppath.len += 2;
|
|
|
|
|
} else
|
|
|
|
|
tmppath = p15card->file_tokeninfo.path;
|
2001-11-26 16:14:22 +00:00
|
|
|
|
} else {
|
|
|
|
|
defaults->defaults_func(p15card, defaults->arg);
|
|
|
|
|
tmppath = p15card->file_tokeninfo.path;
|
2001-11-01 15:43:20 +00:00
|
|
|
|
}
|
2001-12-22 23:51:12 +00:00
|
|
|
|
err = sc_select_file(card, &tmppath, &p15card->file_tokeninfo);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
if (err)
|
|
|
|
|
goto error;
|
2001-12-29 02:07:32 +00:00
|
|
|
|
err = sc_read_binary(card, 0, buf, p15card->file_tokeninfo.size, 0);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
if (err < 0)
|
|
|
|
|
goto error;
|
|
|
|
|
if (err <= 2) {
|
|
|
|
|
err = SC_ERROR_PKCS15_CARD_NOT_FOUND;
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
parse_tokeninfo(p15card, buf, err);
|
2001-12-22 20:43:09 +00:00
|
|
|
|
|
|
|
|
|
p15card->use_cache = card->ctx->use_cache;
|
|
|
|
|
|
2001-11-01 15:43:20 +00:00
|
|
|
|
*p15card_out = p15card;
|
2001-12-25 20:45:48 +00:00
|
|
|
|
sc_unlock(card);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
return 0;
|
2001-12-16 18:46:32 +00:00
|
|
|
|
error:
|
2001-11-01 15:43:20 +00:00
|
|
|
|
free(p15card);
|
2001-12-25 20:45:48 +00:00
|
|
|
|
sc_unlock(card);
|
|
|
|
|
SC_FUNC_RETURN(ctx, 1, err);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-21 23:34:47 +00:00
|
|
|
|
int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card)
|
2001-11-01 15:43:20 +00:00
|
|
|
|
{
|
2001-12-22 20:43:09 +00:00
|
|
|
|
assert(p15card != NULL);
|
|
|
|
|
SC_FUNC_CALLED(p15card->card->ctx, 1);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
free(p15card->label);
|
2001-12-20 13:57:58 +00:00
|
|
|
|
free(p15card->serial_number);
|
|
|
|
|
free(p15card->manufacturer_id);
|
2001-11-01 15:43:20 +00:00
|
|
|
|
free(p15card);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1,
|
|
|
|
|
const struct sc_pkcs15_id *id2)
|
|
|
|
|
{
|
|
|
|
|
assert(id1 != NULL && id2 != NULL);
|
|
|
|
|
if (id1->len != id2->len)
|
|
|
|
|
return 0;
|
|
|
|
|
return memcmp(id1->value, id2->value, id1->len) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sc_pkcs15_print_id(const struct sc_pkcs15_id *id)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < id->len; i++)
|
|
|
|
|
printf("%02X", id->value[i]);
|
|
|
|
|
}
|
2001-11-20 22:21:58 +00:00
|
|
|
|
|
|
|
|
|
int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out)
|
|
|
|
|
{
|
|
|
|
|
out->len = sizeof(out->value);
|
|
|
|
|
return sc_hex_to_bin(in, out->value, &out->len);
|
|
|
|
|
}
|