From c1cac5f311a0f282e7db0989675dbd39dbae654e Mon Sep 17 00:00:00 2001 From: jey Date: Thu, 24 Jan 2002 16:02:54 +0000 Subject: [PATCH] - bumped up version number in preparation of the new release - unified PKCS #15 DF decoding - added PKCS #15 file caching git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@191 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/Makefile.am | 2 +- src/libopensc/iso7816.c | 9 +- src/libopensc/log.c | 55 +++++---- src/libopensc/opensc-pkcs15.h | 70 ++++++++--- src/libopensc/opensc.h | 4 +- src/libopensc/pkcs15-cache.c | 132 +++++++++++++++++++++ src/libopensc/pkcs15-cert.c | 212 ++++++++-------------------------- src/libopensc/pkcs15-pin.c | 103 ++++++----------- src/libopensc/pkcs15-prkey.c | 120 ++++++++----------- src/libopensc/pkcs15.c | 189 +++++++++++++++++++----------- src/libopensc/pkcs15.h | 70 ++++++++--- src/libopensc/sc.c | 17 ++- src/pam/pam_pkcs15.c | 3 +- src/pkcs11/pkcs11-global.c | 6 +- src/tools/cryptoflex-tool.c | 50 +++++--- src/tools/opensc-explorer.c | 13 ++- src/tools/opensc-tool.c | 9 +- src/tools/pkcs15-crypt.c | 3 +- src/tools/pkcs15-tool.c | 113 +++++++++--------- src/tools/util.c | 9 +- src/tools/util.h | 2 +- 21 files changed, 658 insertions(+), 533 deletions(-) create mode 100644 src/libopensc/pkcs15-cache.c diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am index 3297f74c..8e05fb53 100644 --- a/src/libopensc/Makefile.am +++ b/src/libopensc/Makefile.am @@ -5,7 +5,7 @@ INCLUDES = @CFLAGS_PCSC@ lib_LTLIBRARIES = libopensc.la libopensc_la_SOURCES = asn1.c base64.c sec.c log.c sc.c card.c iso7816.c \ pkcs15.c pkcs15-cert.c pkcs15-pin.c \ - pkcs15-prkey.c pkcs15-sec.c \ + pkcs15-prkey.c pkcs15-sec.c pkcs15-cache.c \ card-setec.c card-flex.c \ card-emv.c card-default.c libopensc_la_LDFLAGS = -version-info 0:5:0 diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index dd18bde3..233e423c 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -298,19 +298,12 @@ static int iso7816_select_file(struct sc_card *card, memset(file, 0, sizeof(struct sc_file)); for (i = 0; i < SC_MAX_AC_OPS; i++) file->acl[i] = SC_AC_UNKNOWN; - memcpy(&file->path.value, path, pathlen); - file->path.len = pathlen; + file->path = *in_path; } -#if 0 - if (file == NULL || sc_file_valid(file)) -#endif if (file == NULL) apdu.resplen = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); -#if 0 - if (file == NULL || sc_file_valid(file)) -#endif if (file == NULL) { if (apdu.sw1 == 0x61) SC_FUNC_RETURN(card->ctx, 2, 0); diff --git a/src/libopensc/log.c b/src/libopensc/log.c index 3dac0f11..8040aa01 100644 --- a/src/libopensc/log.c +++ b/src/libopensc/log.c @@ -66,7 +66,7 @@ int use_color(struct sc_context *ctx, FILE *outf) int do_color = 0; int i; - if (!ctx->use_std_output) + if (!isatty(fileno(outf))) return 0; if (term == NULL) { term = getenv("TERM"); @@ -81,8 +81,6 @@ int use_color(struct sc_context *ctx, FILE *outf) } if (!do_color) return 0; - if (!isatty(fileno(outf))) - return 0; return do_color; } @@ -93,48 +91,49 @@ void do_log2(struct sc_context *ctx, int type, const char *file, char buf[1024], *p; int left, r; struct timeval tv; + const char *color_pfx = "", *color_sfx = ""; assert(ctx != NULL); gettimeofday(&tv, NULL); - if (ctx->use_std_output) { + switch (type) { + case SC_LOG_TYPE_ERROR: + if (ctx->log_errors == 0) + return; + outf = ctx->error_file; + break; + case SC_LOG_TYPE_DEBUG: + outf = ctx->debug_file; + break; + } + if (outf == NULL) + return; + if (use_color(ctx, outf)) { + color_sfx = "\33[0m"; switch (type) { case SC_LOG_TYPE_ERROR: - outf = stderr; + color_pfx = "\33[01;31m"; break; - case SC_LOG_TYPE_DEBUG: - outf = stdout; + color_pfx = "\33[00;32m"; + break; } - if (outf == NULL) - return; } - r = 0; if (file != NULL) { r = snprintf(buf, sizeof(buf), "%s:%d:%s: ", file, line, func); if (r < 0) return; - } + } else + r = 0; p = buf + r; left = sizeof(buf) - r; - if (vsnprintf(p, left, format, args) < 0) + r = vsnprintf(p, left, format, args); + if (r < 0) return; - if (ctx->use_std_output) { - const char *color_pfx = "", *color_sfx = ""; - if (use_color(ctx, outf)) { - color_sfx = "\33[0m"; - switch (type) { - case SC_LOG_TYPE_ERROR: - color_pfx = "\33[01;31m"; - break; - case SC_LOG_TYPE_DEBUG: - color_pfx = "\33[00;32m"; - break; - } - } - fprintf(outf, "%s%s%s", color_pfx, buf, color_sfx); - fflush(outf); - } + p += r; + left -= r; + + fprintf(outf, "%s%s%s", color_pfx, buf, color_sfx); } void sc_hex_dump(struct sc_context *ctx, const u8 *in, size_t count, diff --git a/src/libopensc/opensc-pkcs15.h b/src/libopensc/opensc-pkcs15.h index d24c8411..82a10909 100644 --- a/src/libopensc/opensc-pkcs15.h +++ b/src/libopensc/opensc-pkcs15.h @@ -42,6 +42,8 @@ struct sc_pkcs15_id { size_t len; }; +#define SC_PKCS15_CO_FLAG_PRIVATE 0x00000001 +#define SC_PKCS15_CO_FLAG_MODIFIABLE 0x00000002 #define SC_PKCS15_CO_FLAG_OBJECT_SEEN 0x80000000 /* for PKCS #11 module */ struct sc_pkcs15_common_obj_attr { @@ -53,6 +55,23 @@ struct sc_pkcs15_common_obj_attr { /* FIXME: add accessControlRules */ }; +#define SC_PKCS15_PIN_FLAG_CASE_SENSITIVE 0x0001 +#define SC_PKCS15_PIN_FLAG_LOCAL 0x0002 +#define SC_PKCS15_PIN_FLAG_CHANGE_DISABLED 0x0004 +#define SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED 0x0008 +#define SC_PKCS15_PIN_FLAG_INITIALIZED 0x0010 +#define SC_PKCS15_PIN_FLAG_NEEDS_PADDING 0x0020 +#define SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN 0x0040 +#define SC_PKCS15_PIN_FLAG_SO_PIN 0x0080 +#define SC_PKCS15_PIN_FLAG_DISABLE_ALLOW 0x0100 +#define SC_PKCS15_PIN_FLAG_INTEGRITY_PROTECTED 0x0200 +#define SC_PKCS15_PIN_FLAG_CONFIDENTIALITY_PROTECTED 0x0400 +#define SC_PKCS15_PIN_FLAG_EXCHANGE_REF_DATA 0x0800 + +#define SC_PKCS15_PIN_TYPE_BCD 0 +#define SC_PKCS15_PIN_TYPE_ASCII_NUMERIC 1 +#define SC_PKCS15_PIN_TYPE_UTF8 2 + struct sc_pkcs15_pin_info { struct sc_pkcs15_common_obj_attr com_attr; @@ -93,7 +112,7 @@ struct sc_pkcs15_rsa_pubkey { struct sc_pkcs15_cert { int version; unsigned long serial; - + struct sc_pkcs15_rsa_pubkey key; u8 *data; /* DER encoded raw cert */ int data_len; @@ -125,13 +144,6 @@ struct sc_pkcs15_cert_info { #define SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE 0x08 #define SC_PKCS15_PRKEY_ACCESS_LOCAL 0x10 -#define SC_PKCS15_TYPE_PRKEY_RSA 0x100 -#define SC_PKCS15_TYPE_PUBKEY_RSA 0x200 -#define SC_PKCS15_TYPE_CERT_X509 0x400 -#define SC_PKCS15_TYPE_CERT_SPKI 0x402 -#define SC_PKCS15_TYPE_DATA_OBJECT 0x500 -#define SC_PKCS15_TYPE_AUTH_PIN 0x600 - struct sc_pkcs15_prkey_info { struct sc_pkcs15_common_obj_attr com_attr; @@ -143,6 +155,13 @@ struct sc_pkcs15_prkey_info { struct sc_path path; }; +#define SC_PKCS15_TYPE_PRKEY_RSA 0x100 +#define SC_PKCS15_TYPE_PUBKEY_RSA 0x200 +#define SC_PKCS15_TYPE_CERT_X509 0x400 +#define SC_PKCS15_TYPE_CERT_SPKI 0x402 +#define SC_PKCS15_TYPE_DATA_OBJECT 0x500 +#define SC_PKCS15_TYPE_AUTH_PIN 0x600 + struct sc_pkcs15_object { int type; void *data; @@ -200,12 +219,6 @@ struct sc_pkcs15_card { #define SC_PKCS15_CARD_FLAG_PRN_GENERATION 0x04 #define SC_PKCS15_CARD_FLAG_EID_COMPLIANT 0x08 -struct sc_pkcs15_defaults { - const char *ef_dir_dump; - int (*defaults_func)(struct sc_pkcs15_card *, int arg); - int arg; -}; - /* sc_pkcs15_bind: Binds a card object to a PKCS #15 card object * and initializes a new PKCS#15 card object. Will return * SC_ERROR_PKCS15_APP_NOT_FOUND, if the card hasn't got a @@ -282,17 +295,36 @@ int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *bufsize); +int sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_df *df, int file_nr); +int sc_pkcs15_read_df(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_df *df, int file_nr); +int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 **buf, size_t *bufsize); +int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 **buf, size_t *bufsize); +int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 **buf, size_t *bufsize); + int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1, const struct sc_pkcs15_id *id2); void sc_pkcs15_print_id(const struct sc_pkcs15_id *id); void sc_pkcs15_format_id(const char *id_in, struct sc_pkcs15_id *id_out); - +int sc_pkcs15_add_object(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df, + int file_nr, struct sc_pkcs15_object *obj); + int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out); -int sc_pkcs15_add_object(struct sc_context *ctx, struct sc_pkcs15_df *df, - int file_nr, int obj_type, const void *data, - size_t data_size); -extern const struct sc_pkcs15_defaults sc_pkcs15_card_table[]; +/* Caching functions */ +int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, + const struct sc_path *path, + u8 **buf, size_t *bufsize); +int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card, + const struct sc_path *path, + const u8 *buf, size_t bufsize); #ifdef __cplusplus } #endif diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index df3f7650..999b455c 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -373,7 +373,8 @@ struct sc_context { int debug; - int use_std_output, use_cache; + FILE *debug_file, *error_file; + int log_errors; const struct sc_card_driver *card_drivers[SC_MAX_CARD_DRIVERS+1]; const struct sc_card_driver *forced_driver; pthread_mutex_t mutex; @@ -525,6 +526,7 @@ void sc_format_path(const char *path_in, struct sc_path *path_out); int sc_append_path(struct sc_path *dest, const struct sc_path *src); int sc_append_path_id(struct sc_path *dest, const u8 *id, size_t idlen); int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen); +int sc_get_cache_dir(struct sc_context *ctx, char *buf, size_t bufsize); /* Possibly only valid on Setec cards */ int sc_list_files(struct sc_card *card, u8 * buf, size_t buflen); diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c new file mode 100644 index 00000000..712e54bc --- /dev/null +++ b/src/libopensc/pkcs15-cache.c @@ -0,0 +1,132 @@ +/* + * pkcs15-cache.c: PKCS #15 file caching functions + * + * Copyright (C) 2001 Juha Yrjölä + * + * 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 "sc-internal.h" +#include "opensc-pkcs15.h" +#include "sc-log.h" +#include +#include +#include +#include +#include +#include + +static int generate_cache_filename(struct sc_pkcs15_card *p15card, + const struct sc_path *path, + u8 *buf, size_t bufsize) +{ + char dir[80]; + char pathname[SC_MAX_PATH_SIZE*2+1]; + int i, r; + const u8 *pathptr; + size_t pathlen; + + if (path->type != SC_PATH_TYPE_PATH) + return SC_ERROR_INVALID_ARGUMENTS; + assert(path->len <= SC_MAX_PATH_SIZE); + r = sc_get_cache_dir(p15card->card->ctx, dir, sizeof(dir)); + if (r) + return r; + pathptr = path->value; + pathlen = path->len; + if (pathlen > 2 && memcmp(pathptr, "\x3F\x00", 2) == 0) { + pathptr += 2; + pathlen -= 2; + } + for (i = 0; i < pathlen; i++) + sprintf(pathname + 2*i, "%02X", pathptr[i]); + r = snprintf(buf, bufsize, "%s/%s_%s_%s_%s", dir, + p15card->manufacturer_id, p15card->label, + p15card->serial_number, pathname); + if (r < 0) + return SC_ERROR_BUFFER_TOO_SMALL; + return 0; +} + +int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, + const struct sc_path *path, + u8 **buf, size_t *bufsize) +{ + char fname[160]; + int r; + FILE *f; + size_t c; + struct stat stbuf; + u8 *data = NULL; + + r = generate_cache_filename(p15card, path, fname, sizeof(fname)); + if (r != 0) + return r; + r = stat(fname, &stbuf); + if (r) + return SC_ERROR_FILE_NOT_FOUND; + c = stbuf.st_size; + if (*buf == NULL) { + data = malloc(stbuf.st_size); + if (data == NULL) + return SC_ERROR_OUT_OF_MEMORY; + } else + if (c > *bufsize) + return SC_ERROR_BUFFER_TOO_SMALL; + f = fopen(fname, "r"); + if (f == NULL) { + if (data) + free(data); + return SC_ERROR_FILE_NOT_FOUND; + } + if (data) + *buf = data; + c = fread(*buf, 1, c, f); + fclose(f); + if (c != stbuf.st_size) { + if (data) + free(data); + return SC_ERROR_BUFFER_TOO_SMALL; + } + *bufsize = c; + if (data) + *buf = data; + return 0; +} + +int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card, + const struct sc_path *path, + const u8 *buf, size_t bufsize) +{ + char fname[160]; + int r; + FILE *f; + size_t c; + + r = generate_cache_filename(p15card, path, fname, sizeof(fname)); + if (r != 0) + return r; + f = fopen(fname, "w"); + if (f == NULL) + return 0; + c = fwrite(buf, 1, bufsize, f); + fclose(f); + if (c != bufsize) { + error(p15card->card->ctx, "fwrite() wrote only %d bytes", c); + unlink(fname); + return SC_ERROR_INTERNAL; + } + return 0; +} diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index 8576205d..5274c3ee 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -29,8 +29,6 @@ #include #include -#undef CACHE_CERTS - static int parse_rsa_pubkey(struct sc_context *ctx, struct sc_pkcs15_rsa_pubkey *key) { struct sc_asn1_entry asn1_rsa_pubkey[] = { @@ -134,108 +132,19 @@ static int parse_x509_cert(struct sc_context *ctx, const u8 *buf, size_t buflen, return 0; } -static int generate_cert_filename(struct sc_pkcs15_card *p15card, - const struct sc_pkcs15_cert_info *info, - char *fname, int len) -{ - char *homedir; - char cert_id[SC_PKCS15_MAX_ID_SIZE*2+1]; - int i, r; - - homedir = getenv("HOME"); - if (homedir == NULL) - return -1; - cert_id[0] = 0; - for (i = 0; i < info->id.len; i++) { - char tmp[3]; - - sprintf(tmp, "%02X", info->id.value[i]); - strcat(cert_id, tmp); - } - r = snprintf(fname, len, "%s/%s/%s_%s_%s.crt", homedir, - SC_PKCS15_CACHE_DIR, p15card->label, - p15card->serial_number, cert_id); - if (r < 0) - return -1; - return 0; -} - -static int find_cached_cert(struct sc_pkcs15_card *p15card, - const struct sc_pkcs15_cert_info *info, - u8 **out, int *outlen) -{ - int r; - u8 *data; - char fname[1024]; - FILE *crtf; - struct stat stbuf; - - if (getuid() != geteuid()) /* no caching in SUID processes */ - return -1; - if (p15card->use_cache == 0) - return -1; - - r = generate_cert_filename(p15card, info, fname, sizeof(fname)); - if (r) - return SC_ERROR_UNKNOWN; - r = stat(fname, &stbuf); - if (r) - return SC_ERROR_OBJECT_NOT_FOUND; - crtf = fopen(fname, "r"); - if (crtf == NULL) - return SC_ERROR_OBJECT_NOT_FOUND; - data = malloc(stbuf.st_size); - if (data == NULL) - return SC_ERROR_OUT_OF_MEMORY; - r = fread(data, 1, stbuf.st_size, crtf); - fclose(crtf); - if (r <= 0) { - free(data); - return SC_ERROR_OBJECT_NOT_FOUND; - } - *outlen = r; - *out = data; - - return 0; -} - -#ifdef CACHE_CERTS -static int store_cert_to_cache(struct sc_pkcs15_card *p15card, - const struct sc_pkcs15_cert_info *info, - u8 *data, int len) -{ - char fname[1024]; - FILE *crtf; - int r; - - if (getuid() != geteuid()) /* no caching in SUID processes */ - return 0; - - r = generate_cert_filename(p15card, info, fname, sizeof(fname)); - if (r) - return SC_ERROR_UNKNOWN; - - crtf = fopen(fname, "w"); - if (crtf == NULL) - return SC_ERROR_UNKNOWN; - fwrite(data, len, 1, crtf); - fclose(crtf); - return 0; -} -#endif - int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_cert_info *info, struct sc_pkcs15_cert **cert_out) { - int r, len = 0; + int r; struct sc_file file; - u8 *data = NULL; struct sc_pkcs15_cert *cert; - + u8 *data = NULL; + size_t len; + assert(p15card != NULL && info != NULL && cert_out != NULL); SC_FUNC_CALLED(p15card->card->ctx, 1); - r = find_cached_cert(p15card, info, &data, &len); + r = sc_pkcs15_read_cached_file(p15card, &info->path, &data, &len); if (r) { r = sc_lock(p15card->card); SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); @@ -255,10 +164,7 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card, free(data); return r; } - len = r; -#ifdef CACHE_CERTS - store_cert_to_cache(p15card, info, data, len); -#endif + len = file.size; sc_unlock(p15card->card); } cert = malloc(sizeof(struct sc_pkcs15_cert)); @@ -302,21 +208,21 @@ static const struct sc_asn1_entry c_asn1_cert[] = { { NULL } }; -static int parse_x509_cert_info(struct sc_context *ctx, - struct sc_pkcs15_cert_info *cert, - const u8 ** buf, size_t *buflen) +int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 ** buf, size_t *buflen) { + struct sc_context *ctx = p15card->card->ctx; + struct sc_pkcs15_cert_info info; struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4], asn1_x509_cert_attr[2], asn1_type_cert_attr[2], asn1_cert[2]; - struct sc_asn1_pkcs15_object cert_obj = { &cert->com_attr, asn1_com_cert_attr, NULL, + struct sc_asn1_pkcs15_object cert_obj = { &info.com_attr, asn1_com_cert_attr, NULL, asn1_type_cert_attr }; u8 id_value[128]; int id_type, id_value_len = sizeof(id_value); int r; - cert->authority = 0; - sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident); sc_copy_asn1_entry(c_asn1_com_cert_attr, asn1_com_cert_attr); sc_copy_asn1_entry(c_asn1_x509_cert_attr, asn1_x509_cert_attr); @@ -325,16 +231,34 @@ static int parse_x509_cert_info(struct sc_context *ctx, sc_format_asn1_entry(asn1_cred_ident + 0, &id_type, NULL, 0); sc_format_asn1_entry(asn1_cred_ident + 1, &id_value, &id_value_len, 0); - sc_format_asn1_entry(asn1_com_cert_attr + 0, &cert->id, NULL, 0); - sc_format_asn1_entry(asn1_com_cert_attr + 1, &cert->authority, NULL, 0); + sc_format_asn1_entry(asn1_com_cert_attr + 0, &info.id, NULL, 0); + sc_format_asn1_entry(asn1_com_cert_attr + 1, &info.authority, NULL, 0); sc_format_asn1_entry(asn1_com_cert_attr + 2, asn1_cred_ident, NULL, 0); - sc_format_asn1_entry(asn1_x509_cert_attr + 0, &cert->path, NULL, 0); + sc_format_asn1_entry(asn1_x509_cert_attr + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_type_cert_attr + 0, asn1_x509_cert_attr, NULL, 0); sc_format_asn1_entry(asn1_cert + 0, &cert_obj, NULL, 0); + /* Fill in defaults */ + memset(&info, 0, sizeof(info)); + info.authority = 0; + r = sc_asn1_decode(ctx, asn1_cert, *buf, *buflen, buf, buflen); + if (r == SC_ERROR_ASN1_END_OF_CONTENTS) + return r; + SC_TEST_RET(ctx, r, "ASN.1 decoding failed"); + obj->type = SC_PKCS15_TYPE_CERT_X509; + obj->data = malloc(sizeof(info)); + if (obj->data == NULL) + SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY); + memcpy(obj->data, &info, sizeof(info)); - return r; + /* Legacy code */ + if (p15card->cert_count >= SC_PKCS15_MAX_CERTS) + return SC_ERROR_TOO_MANY_OBJECTS; + p15card->cert_info[p15card->cert_count] = info; + p15card->cert_count++; + + return 0; } int sc_pkcs15_encode_cdf_entry(struct sc_context *ctx, @@ -383,78 +307,34 @@ void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert) printf("\n"); } -static int get_certs_from_file(struct sc_pkcs15_card *p15card, - struct sc_pkcs15_df *df, - int file_nr) +int sc_pkcs15_enum_certificates(struct sc_pkcs15_card *p15card) { - int r; - size_t bytes_left; - u8 buf[2048]; - const u8 *p = buf; - struct sc_file *file = df->file[file_nr]; - - r = sc_select_file(p15card->card, &file->path, file); - if (r) - return r; - if (file->size > sizeof(buf)) - return SC_ERROR_BUFFER_TOO_SMALL; - r = sc_read_binary(p15card->card, 0, buf, file->size, 0); - if (r < 0) - return r; - bytes_left = r; - do { - struct sc_pkcs15_cert_info info; - - memset(&info, 0, sizeof(info)); - r = parse_x509_cert_info(p15card->card->ctx, - &info, &p, &bytes_left); - if (r == SC_ERROR_ASN1_END_OF_CONTENTS) - break; - if (r) - return r; - r = sc_pkcs15_add_object(p15card->card->ctx, df, file_nr, - SC_PKCS15_TYPE_CERT_X509, - &info, sizeof(info)); - if (r) - return r; - if (p15card->cert_count >= SC_PKCS15_MAX_CERTS) - break; - p15card->cert_info[p15card->cert_count] = info; - p15card->cert_count++; - } while (bytes_left); - - return 0; -} - -int sc_pkcs15_enum_certificates(struct sc_pkcs15_card *card) -{ - int r = 0, i, j, type; + int r = 0, i, j; const int df_types[] = { SC_PKCS15_CDF, SC_PKCS15_CDF_TRUSTED, SC_PKCS15_CDF_USEFUL }; const int nr_types = sizeof(df_types)/sizeof(df_types[0]); - assert(card != NULL); + assert(p15card != NULL); - if (card->cert_count) - return card->cert_count; /* already enumerated */ - r = sc_lock(card->card); - SC_TEST_RET(card->card->ctx, r, "sc_lock() failed"); + if (p15card->cert_count) + return p15card->cert_count; /* already enumerated */ + r = sc_lock(p15card->card); + SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); for (j = 0; j < nr_types; j++) { - type = df_types[j]; - - for (i = 0; i < card->df[type].count; i++) { - r = get_certs_from_file(card, &card->df[type], i); + int type = df_types[j]; + for (i = 0; i < p15card->df[type].count; i++) { + r = sc_pkcs15_parse_df(p15card, &p15card->df[type], i); if (r != 0) break; } if (r != 0) break; } - sc_unlock(card->card); + sc_unlock(p15card->card); if (r != 0) return r; - return card->cert_count; + return p15card->cert_count; } void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert) diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c index 4254ec26..360e600e 100644 --- a/src/libopensc/pkcs15-pin.c +++ b/src/libopensc/pkcs15-pin.c @@ -52,16 +52,18 @@ static const struct sc_asn1_entry c_asn1_pin[] = { { NULL } }; -static int parse_pin_info(struct sc_context *ctx, - struct sc_pkcs15_pin_info *pin, - const u8 ** buf, size_t *buflen) +int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 ** buf, size_t *buflen) { + struct sc_context *ctx = p15card->card->ctx; + struct sc_pkcs15_pin_info info; int r; - int flags_len = sizeof(pin->flags); + int flags_len = sizeof(info.flags); int padchar_len = 1; struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2]; struct sc_asn1_entry asn1_pin[2]; - struct sc_asn1_pkcs15_object pin_obj = { &pin->com_attr, asn1_com_ao_attr, NULL, + struct sc_asn1_pkcs15_object pin_obj = { &info.com_attr, asn1_com_ao_attr, NULL, asn1_type_pin_attr }; sc_copy_asn1_entry(c_asn1_pin, asn1_pin); sc_copy_asn1_entry(c_asn1_type_pin_attr, asn1_type_pin_attr); @@ -72,26 +74,38 @@ static int parse_pin_info(struct sc_context *ctx, sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 0); - sc_format_asn1_entry(asn1_pin_attr + 0, &pin->flags, &flags_len, 0); - sc_format_asn1_entry(asn1_pin_attr + 1, &pin->type, NULL, 0); - sc_format_asn1_entry(asn1_pin_attr + 2, &pin->min_length, NULL, 0); - sc_format_asn1_entry(asn1_pin_attr + 3, &pin->stored_length, NULL, 0); - sc_format_asn1_entry(asn1_pin_attr + 5, &pin->reference, NULL, 0); - sc_format_asn1_entry(asn1_pin_attr + 6, &pin->pad_char, &padchar_len, 0); - sc_format_asn1_entry(asn1_pin_attr + 8, &pin->path, NULL, 0); + sc_format_asn1_entry(asn1_pin_attr + 0, &info.flags, &flags_len, 0); + sc_format_asn1_entry(asn1_pin_attr + 1, &info.type, NULL, 0); + sc_format_asn1_entry(asn1_pin_attr + 2, &info.min_length, NULL, 0); + sc_format_asn1_entry(asn1_pin_attr + 3, &info.stored_length, NULL, 0); + sc_format_asn1_entry(asn1_pin_attr + 5, &info.reference, NULL, 0); + sc_format_asn1_entry(asn1_pin_attr + 6, &info.pad_char, &padchar_len, 0); + sc_format_asn1_entry(asn1_pin_attr + 8, &info.path, NULL, 0); - sc_format_asn1_entry(asn1_com_ao_attr + 0, &pin->auth_id, NULL, 0); + sc_format_asn1_entry(asn1_com_ao_attr + 0, &info.auth_id, NULL, 0); /* Fill in defaults */ - pin->reference = 0; - - memset(pin, 0, sizeof(*pin)); + memset(&info, 0, sizeof(info)); + info.reference = 0; r = sc_asn1_decode(ctx, asn1_pin, *buf, *buflen, buf, buflen); - if (r == 0) - pin->magic = SC_PKCS15_PIN_MAGIC; + if (r == SC_ERROR_ASN1_END_OF_CONTENTS) + return r; + SC_TEST_RET(ctx, r, "ASN.1 decoding failed"); + info.magic = SC_PKCS15_PIN_MAGIC; + obj->type = SC_PKCS15_TYPE_AUTH_PIN; + obj->data = malloc(sizeof(info)); + if (obj->data == NULL) + SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY); + memcpy(obj->data, &info, sizeof(info)); - return r; + /* Legacy code */ + if (p15card->pin_count >= SC_PKCS15_MAX_PINS) + return SC_ERROR_TOO_MANY_OBJECTS; + p15card->pin_info[p15card->pin_count] = info; + p15card->pin_count++; + + return 0; } int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx, @@ -148,10 +162,11 @@ void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin) p += 2; } printf("PIN [%s]\n", pin->com_attr.label); + printf("\tCom. Flags: 0x%X\n", pin->com_attr.flags); printf("\tAuth ID : "); sc_pkcs15_print_id(&pin->auth_id); printf("\n"); - printf("\tFlags : %d\n", pin->com_attr.flags); + printf("\tFlags : 0x%X\n", pin->flags); printf("\tLength : %d..%d\n", pin->min_length, pin->stored_length); printf("\tPad char : 0x%02X\n", pin->pad_char); printf("\tReference : %d\n", pin->reference); @@ -159,60 +174,16 @@ void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin) printf("\tPath : %s\n", path); } -static int get_pins_from_file(struct sc_pkcs15_card *p15card, - struct sc_pkcs15_df *df, - int file_nr) -{ - int r; - size_t bytes_left; - u8 buf[2048]; - const u8 *p = buf; - struct sc_file *file = df->file[file_nr]; - - r = sc_select_file(p15card->card, &file->path, file); - if (r) - return r; - if (file->size > sizeof(buf)) - return SC_ERROR_BUFFER_TOO_SMALL; - r = sc_read_binary(p15card->card, 0, buf, file->size, 0); - if (r < 0) - return r; - bytes_left = r; - do { - struct sc_pkcs15_pin_info info; - - memset(&info, 0, sizeof(info)); - r = parse_pin_info(p15card->card->ctx, - &info, &p, &bytes_left); - if (r == SC_ERROR_ASN1_END_OF_CONTENTS) - break; - if (r) - return r; - r = sc_pkcs15_add_object(p15card->card->ctx, df, file_nr, - SC_PKCS15_TYPE_AUTH_PIN, - &info, sizeof(info)); - if (r) - return r; - if (p15card->pin_count >= SC_PKCS15_MAX_CERTS) - return SC_ERROR_TOO_MANY_OBJECTS; - p15card->pin_info[p15card->pin_count] = info; - p15card->pin_count++; - } while (bytes_left); - - return 0; -} - int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card) { int r, i, j; - struct sc_context *ctx = p15card->card->ctx; const int df_types[] = { SC_PKCS15_AODF }; const int nr_types = sizeof(df_types)/sizeof(df_types[0]); assert(p15card != NULL); - SC_FUNC_CALLED(ctx, 1); + SC_FUNC_CALLED(p15card->card->ctx, 1); if (p15card->pin_count) { for (i = 0; i < p15card->pin_count; i++) { if (p15card->pin_info[i].magic != SC_PKCS15_PIN_MAGIC) @@ -228,7 +199,7 @@ int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card) int type = df_types[j]; for (i = 0; r == 0 && i < p15card->df[type].count; i++) { - r = get_pins_from_file(p15card, &p15card->df[type], i); + r = sc_pkcs15_parse_df(p15card, &p15card->df[type], i); if (r != 0) break; } diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index d7fb5b2d..6ab3cc9b 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -36,6 +36,7 @@ void sc_pkcs15_print_prkey_info(const struct sc_pkcs15_prkey_info *prkey) printf("\tAccessFlags : %X\n", prkey->access_flags); printf("\tModLength : %d\n", prkey->modulus_length); printf("\tKey ref : %d\n", prkey->key_reference); + printf("\tNative : %s\n", prkey->native ? "yes" : "no"); printf("\tPath : "); for (i = 0; i < prkey->path.len; i++) printf("%02X", prkey->path.value[i]); @@ -79,18 +80,19 @@ static const struct sc_asn1_entry c_asn1_prkey[] = { { NULL } }; -static int parse_rsa_prkey_info(struct sc_context *ctx, - struct sc_pkcs15_prkey_info *prkey, - const u8 **buf, size_t *buflen) +int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 ** buf, size_t *buflen) { + struct sc_context *ctx = p15card->card->ctx; + struct sc_pkcs15_prkey_info info; int r; - int usage_len = sizeof(prkey->usage); - int af_len = sizeof(prkey->access_flags); + int usage_len = sizeof(info.usage); + int af_len = sizeof(info.access_flags); struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_prkey_attr[1]; struct sc_asn1_entry asn1_rsakey_attr[4], asn1_type_attr[2]; struct sc_asn1_entry asn1_prkey[2]; - - struct sc_asn1_pkcs15_object prkey_obj = { &prkey->com_attr, asn1_com_key_attr, + struct sc_asn1_pkcs15_object prkey_obj = { &info.com_attr, asn1_com_key_attr, asn1_com_prkey_attr, asn1_type_attr }; sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey); @@ -103,24 +105,38 @@ static int parse_rsa_prkey_info(struct sc_context *ctx, sc_format_asn1_entry(asn1_type_attr + 0, asn1_rsakey_attr, NULL, 0); - sc_format_asn1_entry(asn1_rsakey_attr + 0, &prkey->path, NULL, 0); - sc_format_asn1_entry(asn1_rsakey_attr + 1, &prkey->modulus_length, NULL, 0); + sc_format_asn1_entry(asn1_rsakey_attr + 0, &info.path, NULL, 0); + sc_format_asn1_entry(asn1_rsakey_attr + 1, &info.modulus_length, NULL, 0); - sc_format_asn1_entry(asn1_com_key_attr + 0, &prkey->id, NULL, 0); - sc_format_asn1_entry(asn1_com_key_attr + 1, &prkey->usage, &usage_len, 0); - sc_format_asn1_entry(asn1_com_key_attr + 2, &prkey->native, NULL, 0); - sc_format_asn1_entry(asn1_com_key_attr + 3, &prkey->access_flags, &af_len, 0); - sc_format_asn1_entry(asn1_com_key_attr + 4, &prkey->key_reference, NULL, 0); + sc_format_asn1_entry(asn1_com_key_attr + 0, &info.id, NULL, 0); + sc_format_asn1_entry(asn1_com_key_attr + 1, &info.usage, &usage_len, 0); + sc_format_asn1_entry(asn1_com_key_attr + 2, &info.native, NULL, 0); + sc_format_asn1_entry(asn1_com_key_attr + 3, &info.access_flags, &af_len, 0); + sc_format_asn1_entry(asn1_com_key_attr + 4, &info.key_reference, NULL, 0); /* Fill in defaults */ - prkey->key_reference = -1; - prkey->native = 1; + memset(&info, 0, sizeof(info)); + info.key_reference = -1; + info.native = 1; r = sc_asn1_decode(ctx, asn1_prkey, *buf, *buflen, buf, buflen); + if (r == SC_ERROR_ASN1_END_OF_CONTENTS) + return r; + SC_TEST_RET(ctx, r, "ASN.1 decoding failed"); + obj->type = SC_PKCS15_TYPE_PRKEY_RSA; + obj->data = malloc(sizeof(info)); + if (obj->data == NULL) + SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY); + memcpy(obj->data, &info, sizeof(info)); - return r; + /* Legacy code */ + if (p15card->prkey_count >= SC_PKCS15_MAX_PRKEYS) + return SC_ERROR_TOO_MANY_OBJECTS; + p15card->prkey_info[p15card->prkey_count] = info; + p15card->prkey_count++; + + return 0; } - int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *buflen) @@ -164,81 +180,35 @@ int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx, return r; } - -static int get_prkeys_from_file(struct sc_pkcs15_card *p15card, - struct sc_pkcs15_df *df, - int file_nr) -{ - int r; - size_t bytes_left; - u8 buf[2048]; - const u8 *p = buf; - struct sc_file *file = df->file[file_nr]; - - r = sc_select_file(p15card->card, &file->path, file); - if (r) - return r; - if (file->size > sizeof(buf)) - return SC_ERROR_BUFFER_TOO_SMALL; - r = sc_read_binary(p15card->card, 0, buf, file->size, 0); - if (r < 0) - return r; - bytes_left = r; - do { - struct sc_pkcs15_prkey_info info; - - memset(&info, 0, sizeof(info)); - r = parse_rsa_prkey_info(p15card->card->ctx, - &info, &p, &bytes_left); - if (r == SC_ERROR_ASN1_END_OF_CONTENTS) - break; - if (r) - return r; - r = sc_pkcs15_add_object(p15card->card->ctx, df, file_nr, - SC_PKCS15_TYPE_PRKEY_RSA, - &info, sizeof(info)); - if (r) - return r; - if (p15card->prkey_count >= SC_PKCS15_MAX_PRKEYS) - break; - p15card->prkey_info[p15card->prkey_count] = info; - p15card->prkey_count++; - } while (bytes_left); - - return 0; -} - - -int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card) +int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *p15card) { int r, i, j; - struct sc_context *ctx = card->card->ctx; const int df_types[] = { SC_PKCS15_PRKDF }; const int nr_types = sizeof(df_types)/sizeof(df_types[0]); - assert(card != NULL); - SC_FUNC_CALLED(ctx, 1); - if (card->prkey_count) - return card->prkey_count; /* already enumerated */ - r = sc_lock(card->card); - SC_TEST_RET(card->card->ctx, r, "sc_lock() failed"); + assert(p15card != NULL); + SC_FUNC_CALLED(p15card->card->ctx, 1); + if (p15card->prkey_count) + return p15card->prkey_count; /* already enumerated */ + r = sc_lock(p15card->card); + SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); for (j = 0; r == 0 && j < nr_types; j++) { int type = df_types[j]; - for (i = 0; r == 0 && i < card->df[type].count; i++) { - r = get_prkeys_from_file(card, &card->df[type], i); + for (i = 0; r == 0 && i < p15card->df[type].count; i++) { + r = sc_pkcs15_parse_df(p15card, &p15card->df[type], i); if (r != 0) break; } if (r != 0) break; } - sc_unlock(card->card); + sc_unlock(p15card->card); if (r != 0) return r; - return card->prkey_count; + return p15card->prkey_count; } int sc_pkcs15_find_prkey_by_id(struct sc_pkcs15_card *card, diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index a9984e27..31a87223 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -306,7 +306,10 @@ int sc_pkcs15_create_dir(struct sc_pkcs15_card *p15card, struct sc_card *card) file.id = 0x2F00; file.status = SC_FILE_STATUS_ACTIVATED; sc_format_path("3F002F00", &path); + i = card->ctx->log_errors; + card->ctx->log_errors = 0; r = sc_select_file(card, &path, NULL); + card->ctx->log_errors = i; if (r != 0) { r = sc_create_file(card, &file); if (r) { @@ -447,12 +450,6 @@ err: return r; } -static const struct sc_pkcs15_defaults * find_defaults(u8 *dir, int dirlen) -{ - /* FIXME: CODEME */ - return NULL; -} - struct sc_pkcs15_card * sc_pkcs15_card_new() { struct sc_pkcs15_card *p15card; @@ -498,7 +495,6 @@ int sc_pkcs15_bind(struct sc_card *card, int err, len; struct sc_pkcs15_card *p15card = NULL; struct sc_path tmppath; - const struct sc_pkcs15_defaults *defaults = NULL; struct sc_context *ctx; struct sc_file file; @@ -538,41 +534,34 @@ int sc_pkcs15_bind(struct sc_card *card, error(ctx, "Error parsing EF(DIR)\n"); goto error; } - if (p15card->use_cache) - defaults = find_defaults(buf, err); - if (defaults == NULL) { - 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; - - err = sc_select_file(card, &tmppath, &file); - if (err) /* FIXME: finish writing error stuff */ - goto error; - err = sc_read_binary(card, 0, buf, file.size, 0); - if (err < 0) - goto error; - if (err < 2) { - err = SC_ERROR_PKCS15_APP_NOT_FOUND; - goto error; - } - len = err; - if (parse_odf(buf, len, p15card)) { - err = SC_ERROR_PKCS15_APP_NOT_FOUND; - goto error; - } - 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; - } else { - defaults->defaults_func(p15card, defaults->arg); - tmppath = p15card->file_tokeninfo.path; + 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; + + err = sc_select_file(card, &tmppath, &file); + if (err) /* FIXME: finish writing error stuff */ + goto error; + err = sc_read_binary(card, 0, buf, file.size, 0); + if (err < 0) + goto error; + if (err < 2) { + err = SC_ERROR_PKCS15_APP_NOT_FOUND; + goto error; } + len = err; + if (parse_odf(buf, len, p15card)) { + err = SC_ERROR_PKCS15_APP_NOT_FOUND; + goto error; + } + 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; err = sc_select_file(card, &tmppath, &file); if (err) goto error; @@ -585,7 +574,7 @@ int sc_pkcs15_bind(struct sc_card *card, } parse_tokeninfo(p15card, buf, err); - p15card->use_cache = card->ctx->use_cache; + p15card->use_cache = 1; *p15card_out = p15card; sc_unlock(card); @@ -617,35 +606,22 @@ int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card) return 0; } -int sc_pkcs15_add_object(struct sc_context *ctx, struct sc_pkcs15_df *df, - int file_nr, int obj_type, const void *data, - size_t data_size) -{ +int sc_pkcs15_add_object(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df, + int file_nr, struct sc_pkcs15_object *obj) +{ struct sc_pkcs15_object *p = df->obj[file_nr]; - struct sc_pkcs15_object *newobj; - - newobj = malloc(sizeof(struct sc_pkcs15_object)); - if (newobj == NULL) - return SC_ERROR_OUT_OF_MEMORY; - newobj->next = NULL; - newobj->type = obj_type; - newobj->data = malloc(data_size); - if (newobj->data == NULL) { - free(newobj); - return SC_ERROR_OUT_OF_MEMORY; - } - memcpy(newobj->data, data, data_size); - + + obj->next = NULL; if (p == NULL) { - df->obj[file_nr] = newobj; + df->obj[file_nr] = obj; return 0; } while (p->next != NULL) - p = p->next; - p->next = newobj; - + p = p->next; + p->next = obj; + return 0; -} +} int sc_pkcs15_encode_df(struct sc_context *ctx, struct sc_pkcs15_df *df, @@ -702,7 +678,7 @@ int sc_pkcs15_encode_df(struct sc_context *ctx, static int create_file(struct sc_card *card, struct sc_file *file) { struct sc_path path; - int r; + int r, i; path = file->path; if (path.len < 2) { @@ -711,7 +687,10 @@ static int create_file(struct sc_card *card, struct sc_file *file) } r = sc_lock(card); SC_TEST_RET(card->ctx, r, "sc_lock() failed"); + i = card->ctx->log_errors; + card->ctx->log_errors = 0; r = sc_select_file(card, &path, NULL); + card->ctx->log_errors = 1; if (r == 0) { sc_unlock(card); return 0; /* File already exists */ @@ -850,6 +829,84 @@ err: return r; } +int sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_df *df, int file_nr) +{ + struct sc_context *ctx = p15card->card->ctx; + u8 buf[2048], *bufptr = buf; + const u8 *p = buf; + size_t bufsize = sizeof(buf); + int r, cached_file = 0; + struct sc_file *file = df->file[file_nr]; + struct sc_path path = file->path; + struct sc_pkcs15_object *obj = NULL; + int (* func)(struct sc_pkcs15_card *, struct sc_pkcs15_object *, + const u8 **buf, size_t *bufsize) = NULL; + + switch (df->type) { + case SC_PKCS15_PRKDF: + func = sc_pkcs15_decode_prkdf_entry; + break; + case SC_PKCS15_CDF: + case SC_PKCS15_CDF_TRUSTED: + case SC_PKCS15_CDF_USEFUL: + func = sc_pkcs15_decode_cdf_entry; + break; + case SC_PKCS15_AODF: + func = sc_pkcs15_decode_aodf_entry; + break; + } + if (func == NULL) { + error(ctx, "unknown DF type: %d\n", df->type); + return SC_ERROR_INVALID_ARGUMENTS; + } + if (p15card->use_cache) { + r = sc_pkcs15_read_cached_file(p15card, &file->path, + &bufptr, &bufsize); + if (r == 0) + cached_file = 1; + } + if (cached_file == 0) { + r = sc_select_file(p15card->card, &path, file); + if (r) { + sc_perror(ctx, r, "sc_select_file() failed"); + return r; + } + if (file->size > sizeof(buf)) { + error(ctx, "Buffer too small to handle DF contents\n"); + return SC_ERROR_INTERNAL; + } + r = sc_read_binary(p15card->card, 0, buf, file->size, 0); + if (r < 0) + return r; + bufsize = file->size; + } + do { + obj = malloc(sizeof(struct sc_pkcs15_object)); + if (obj == NULL) + return SC_ERROR_OUT_OF_MEMORY; + memset(obj, 0, sizeof(sizeof(struct sc_pkcs15_object))); + r = func(p15card, obj, &p, &bufsize); + if (r) { + free(obj); + if (r == SC_ERROR_ASN1_END_OF_CONTENTS) + break; + sc_perror(ctx, r, "Error decoding DF entry"); + return r; + } + r = sc_pkcs15_add_object(p15card, df, file_nr, obj); + if (r) { + if (obj->data) + free(obj->data); + free(obj); + sc_perror(ctx, r, "Error adding object"); + return r; + } + } while (bufsize && *p != 0x00); + + return 0; +} + int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1, const struct sc_pkcs15_id *id2) { diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index d24c8411..82a10909 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -42,6 +42,8 @@ struct sc_pkcs15_id { size_t len; }; +#define SC_PKCS15_CO_FLAG_PRIVATE 0x00000001 +#define SC_PKCS15_CO_FLAG_MODIFIABLE 0x00000002 #define SC_PKCS15_CO_FLAG_OBJECT_SEEN 0x80000000 /* for PKCS #11 module */ struct sc_pkcs15_common_obj_attr { @@ -53,6 +55,23 @@ struct sc_pkcs15_common_obj_attr { /* FIXME: add accessControlRules */ }; +#define SC_PKCS15_PIN_FLAG_CASE_SENSITIVE 0x0001 +#define SC_PKCS15_PIN_FLAG_LOCAL 0x0002 +#define SC_PKCS15_PIN_FLAG_CHANGE_DISABLED 0x0004 +#define SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED 0x0008 +#define SC_PKCS15_PIN_FLAG_INITIALIZED 0x0010 +#define SC_PKCS15_PIN_FLAG_NEEDS_PADDING 0x0020 +#define SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN 0x0040 +#define SC_PKCS15_PIN_FLAG_SO_PIN 0x0080 +#define SC_PKCS15_PIN_FLAG_DISABLE_ALLOW 0x0100 +#define SC_PKCS15_PIN_FLAG_INTEGRITY_PROTECTED 0x0200 +#define SC_PKCS15_PIN_FLAG_CONFIDENTIALITY_PROTECTED 0x0400 +#define SC_PKCS15_PIN_FLAG_EXCHANGE_REF_DATA 0x0800 + +#define SC_PKCS15_PIN_TYPE_BCD 0 +#define SC_PKCS15_PIN_TYPE_ASCII_NUMERIC 1 +#define SC_PKCS15_PIN_TYPE_UTF8 2 + struct sc_pkcs15_pin_info { struct sc_pkcs15_common_obj_attr com_attr; @@ -93,7 +112,7 @@ struct sc_pkcs15_rsa_pubkey { struct sc_pkcs15_cert { int version; unsigned long serial; - + struct sc_pkcs15_rsa_pubkey key; u8 *data; /* DER encoded raw cert */ int data_len; @@ -125,13 +144,6 @@ struct sc_pkcs15_cert_info { #define SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE 0x08 #define SC_PKCS15_PRKEY_ACCESS_LOCAL 0x10 -#define SC_PKCS15_TYPE_PRKEY_RSA 0x100 -#define SC_PKCS15_TYPE_PUBKEY_RSA 0x200 -#define SC_PKCS15_TYPE_CERT_X509 0x400 -#define SC_PKCS15_TYPE_CERT_SPKI 0x402 -#define SC_PKCS15_TYPE_DATA_OBJECT 0x500 -#define SC_PKCS15_TYPE_AUTH_PIN 0x600 - struct sc_pkcs15_prkey_info { struct sc_pkcs15_common_obj_attr com_attr; @@ -143,6 +155,13 @@ struct sc_pkcs15_prkey_info { struct sc_path path; }; +#define SC_PKCS15_TYPE_PRKEY_RSA 0x100 +#define SC_PKCS15_TYPE_PUBKEY_RSA 0x200 +#define SC_PKCS15_TYPE_CERT_X509 0x400 +#define SC_PKCS15_TYPE_CERT_SPKI 0x402 +#define SC_PKCS15_TYPE_DATA_OBJECT 0x500 +#define SC_PKCS15_TYPE_AUTH_PIN 0x600 + struct sc_pkcs15_object { int type; void *data; @@ -200,12 +219,6 @@ struct sc_pkcs15_card { #define SC_PKCS15_CARD_FLAG_PRN_GENERATION 0x04 #define SC_PKCS15_CARD_FLAG_EID_COMPLIANT 0x08 -struct sc_pkcs15_defaults { - const char *ef_dir_dump; - int (*defaults_func)(struct sc_pkcs15_card *, int arg); - int arg; -}; - /* sc_pkcs15_bind: Binds a card object to a PKCS #15 card object * and initializes a new PKCS#15 card object. Will return * SC_ERROR_PKCS15_APP_NOT_FOUND, if the card hasn't got a @@ -282,17 +295,36 @@ int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *bufsize); +int sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_df *df, int file_nr); +int sc_pkcs15_read_df(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_df *df, int file_nr); +int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 **buf, size_t *bufsize); +int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 **buf, size_t *bufsize); +int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 **buf, size_t *bufsize); + int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1, const struct sc_pkcs15_id *id2); void sc_pkcs15_print_id(const struct sc_pkcs15_id *id); void sc_pkcs15_format_id(const char *id_in, struct sc_pkcs15_id *id_out); - +int sc_pkcs15_add_object(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df, + int file_nr, struct sc_pkcs15_object *obj); + int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out); -int sc_pkcs15_add_object(struct sc_context *ctx, struct sc_pkcs15_df *df, - int file_nr, int obj_type, const void *data, - size_t data_size); -extern const struct sc_pkcs15_defaults sc_pkcs15_card_table[]; +/* Caching functions */ +int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, + const struct sc_path *path, + u8 **buf, size_t *bufsize); +int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card, + const struct sc_path *path, + const u8 *buf, size_t bufsize); #ifdef __cplusplus } #endif diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 42c4308b..cee30bdd 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -146,8 +146,8 @@ int sc_establish_context(struct sc_context **ctx_out) ctx = malloc(sizeof(struct sc_context)); if (ctx == NULL) return SC_ERROR_OUT_OF_MEMORY; - memset(ctx, sizeof(struct sc_context), 0); - ctx->use_cache = 1; + memset(ctx, 0, sizeof(struct sc_context)); + ctx->log_errors = 1; rv = SCardEstablishContext(SCARD_SCOPE_GLOBAL, "localhost", NULL, &ctx->pcsc_ctx); if (rv != SCARD_S_SUCCESS) @@ -277,6 +277,19 @@ int sc_append_path_id(struct sc_path *dest, const u8 *id, size_t idlen) return 0; } +int sc_get_cache_dir(struct sc_context *ctx, char *buf, size_t bufsize) +{ + char *homedir; + const char *cache_dir = ".eid/cache"; + + homedir = getenv("HOME"); + if (homedir == NULL) + return SC_ERROR_INTERNAL; + if (snprintf(buf, bufsize, "%s/%s", homedir, cache_dir) < 0) + return SC_ERROR_BUFFER_TOO_SMALL; + return 0; +} + const char *sc_strerror(int error) { const char *errors[] = { diff --git a/src/pam/pam_pkcs15.c b/src/pam/pam_pkcs15.c index c6393690..90057aef 100644 --- a/src/pam/pam_pkcs15.c +++ b/src/pam/pam_pkcs15.c @@ -299,7 +299,8 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, con printf("establish_context() failed: %s\n", sc_strerror(r)); return PAM_AUTH_ERR; } - ctx->use_std_output = 1; + ctx->error_file = stderr; + ctx->debug_file = stdout; ctx->debug = 0; for (i = 0; i < ctx->reader_count; i++) { if (sc_detect_card(ctx, i) == 1) { diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index c3073f13..51c37d6d 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -41,9 +41,11 @@ CK_RV C_Initialize(CK_VOID_PTR pReserved) if (rc != 0) return CKR_DEVICE_ERROR; #ifdef DEBUG - context->use_std_output = 1; + context->debug_file = stdout; + context->error_file = stderr; #else - context->use_std_output = 0; + context->debug_file = NULL; + context->error_file = NULL; #endif pool_initialize(&session_pool); diff --git a/src/tools/cryptoflex-tool.c b/src/tools/cryptoflex-tool.c index 6001ea51..ce0e47c2 100644 --- a/src/tools/cryptoflex-tool.c +++ b/src/tools/cryptoflex-tool.c @@ -872,7 +872,9 @@ int create_file(struct sc_file *file) path = file->path; if (path.len < 2) return SC_ERROR_INVALID_ARGUMENTS; + ctx->log_errors = 0; r = sc_select_file(card, &path, NULL); + ctx->log_errors = 1; if (r == 0) return 0; /* File already exists */ path.len -= 2; @@ -952,7 +954,9 @@ int create_pin_file(const struct sc_path *inpath, int chv, const char *key_id) r = sc_select_file(card, inpath, NULL); if (r) return -1; + ctx->log_errors = 0; r = sc_select_file(card, &file_id, NULL); + ctx->log_errors = 1; if (r == 0) return 0; for (;;) { @@ -1045,6 +1049,25 @@ int create_pin_file(const struct sc_path *inpath, int chv, const char *key_id) return 0; } +int add_object(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_df *df, int file_nr, + unsigned int type, void *data, size_t datalen) +{ + struct sc_pkcs15_object *obj; + + obj = malloc(sizeof(*obj)); + if (obj == NULL) + return -1; + obj->type = type; + obj->data = malloc(datalen); + if (obj->data == NULL) { + free(obj); + return -1; + } + memcpy(obj->data, data, datalen); + return sc_pkcs15_add_object(p15card, df, file_nr, obj); +} + int create_pkcs15() { struct sc_pkcs15_card *p15card; @@ -1095,14 +1118,14 @@ int create_pkcs15() strcpy(cert.com_attr.label, "Authentication certificate"); sc_pkcs15_format_id("41", &cert.id); sc_format_path("3F0050154301", &cert.path); - sc_pkcs15_add_object(ctx, &p15card->df[SC_PKCS15_CDF], file_no, - SC_PKCS15_TYPE_CERT_X509, &cert, sizeof(cert)), + add_object(p15card, &p15card->df[SC_PKCS15_CDF], file_no, + SC_PKCS15_TYPE_CERT_X509, &cert, sizeof(cert)), strcpy(cert.com_attr.label, "Non-repudiation certificate"); sc_pkcs15_format_id("42", &cert.id); sc_format_path("3F0050154302", &cert.path); - sc_pkcs15_add_object(ctx, &p15card->df[SC_PKCS15_CDF], file_no, - SC_PKCS15_TYPE_CERT_X509, &cert, sizeof(cert)), + add_object(p15card, &p15card->df[SC_PKCS15_CDF], file_no, + SC_PKCS15_TYPE_CERT_X509, &cert, sizeof(cert)), memset(&prkey, 0, sizeof(prkey)); prkey.modulus_length = 1024; @@ -1112,16 +1135,16 @@ int create_pkcs15() sc_pkcs15_format_id("01", &prkey.com_attr.auth_id); sc_format_path("0012", &prkey.path); prkey.key_reference = 0; - sc_pkcs15_add_object(ctx, &p15card->df[SC_PKCS15_PRKDF], file_no, - SC_PKCS15_TYPE_PRKEY_RSA, &prkey, sizeof(prkey)), + add_object(p15card, &p15card->df[SC_PKCS15_PRKDF], file_no, + SC_PKCS15_TYPE_PRKEY_RSA, &prkey, sizeof(prkey)), strcpy(prkey.com_attr.label, "Non-repudiation key"); sc_pkcs15_format_id("42", &prkey.id); sc_pkcs15_format_id("02", &prkey.com_attr.auth_id); sc_format_path("3F004B020012", &prkey.path); prkey.key_reference = 0; - sc_pkcs15_add_object(ctx, &p15card->df[SC_PKCS15_PRKDF], file_no, - SC_PKCS15_TYPE_PRKEY_RSA, &prkey, sizeof(prkey)), + add_object(p15card, &p15card->df[SC_PKCS15_PRKDF], file_no, + SC_PKCS15_TYPE_PRKEY_RSA, &prkey, sizeof(prkey)), memset(&pin, 0, sizeof(pin)); pin.magic = SC_PKCS15_PIN_MAGIC; @@ -1133,8 +1156,8 @@ int create_pkcs15() pin.stored_length = 8; pin.pad_char = 0x00; pin.type = 1; - sc_pkcs15_add_object(ctx, &p15card->df[SC_PKCS15_AODF], file_no, - SC_PKCS15_TYPE_AUTH_PIN, &pin, sizeof(pin)), + add_object(p15card, &p15card->df[SC_PKCS15_AODF], file_no, + SC_PKCS15_TYPE_AUTH_PIN, &pin, sizeof(pin)), strcpy(pin.com_attr.label, "Non-repuditiation PIN"); sc_pkcs15_format_id("02", &pin.auth_id); @@ -1144,8 +1167,8 @@ int create_pkcs15() pin.stored_length = 8; pin.pad_char = 0x00; pin.type = 1; - sc_pkcs15_add_object(ctx, &p15card->df[SC_PKCS15_AODF], file_no, - SC_PKCS15_TYPE_AUTH_PIN, &pin, sizeof(pin)), + add_object(p15card, &p15card->df[SC_PKCS15_AODF], file_no, + SC_PKCS15_TYPE_AUTH_PIN, &pin, sizeof(pin)), r = create_app_df(&p15card->file_app.path, 5000); if (r) { @@ -1282,7 +1305,8 @@ int main(int argc, char * const argv[]) fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); return 1; } - ctx->use_std_output = 1; + ctx->error_file = stderr; + ctx->debug_file = stdout; ctx->debug = opt_debug; if (opt_reader >= ctx->reader_count || opt_reader < 0) { fprintf(stderr, "Illegal reader number. Only %d reader(s) configured.\n", ctx->reader_count); diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 94466542..f2e9167b 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -52,7 +52,7 @@ const char *option_help[] = { const char *cmds[] = { "ls", "cd", "debug", "cat", "info", "create", "delete", - "verify", "put", "get", "mkdir" + "verify", "put", "get", "mkdir", "quit" }; const int nr_cmds = sizeof(cmds)/sizeof(cmds[0]); @@ -681,9 +681,12 @@ int handle_cmd(int cmd, const char *arg, const char *arg2) printf("Debug level set to %d\n", i); ctx->debug = i; if (i) { - ctx->use_std_output = 1; - } else - ctx->use_std_output = 0; + ctx->error_file = stderr; + ctx->debug_file = stdout; + } else { + ctx->error_file = NULL; + ctx->debug_file = NULL; + } return 0; case 3: return do_cat(arg); @@ -701,6 +704,8 @@ int handle_cmd(int cmd, const char *arg, const char *arg2) return do_get(arg, arg2); case 10: return do_mkdir(arg, arg2); + case 11: + die(0); default: printf("Don't know how to handle command.\n"); } diff --git a/src/tools/opensc-tool.c b/src/tools/opensc-tool.c index 70ff99fe..09cdc11e 100644 --- a/src/tools/opensc-tool.c +++ b/src/tools/opensc-tool.c @@ -163,14 +163,14 @@ int print_file(struct sc_card *card, const struct sc_file *file, const struct sc * 4 MSB's of the octet mean: * 0 = ALW, 1 = PIN1, 2 = PIN2, 4 = SYS, * 15 = NEV */ - hex_dump(stdout, file->sec_attr, file->sec_attr_len); + hex_dump(stdout, file->sec_attr, file->sec_attr_len, ":"); } if (file->prop_attr_len) { printf("\n"); for (r = 0; r < depth; r++) printf(" "); printf("prop: "); - hex_dump(stdout, file->prop_attr, file->prop_attr_len); + hex_dump(stdout, file->prop_attr, file->prop_attr_len, ":"); } printf("\n\n"); #if 1 @@ -373,10 +373,9 @@ int main(int argc, char * const argv[]) fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); return 1; } - ctx->use_std_output = 1; + ctx->error_file = stderr; + ctx->debug_file = stdout; ctx->debug = opt_debug; - if (opt_no_cache) - ctx->use_cache = 0; if (do_list_readers) { if ((err = list_readers())) goto end; diff --git a/src/tools/pkcs15-crypt.c b/src/tools/pkcs15-crypt.c index 54d7b161..70f35a1c 100644 --- a/src/tools/pkcs15-crypt.c +++ b/src/tools/pkcs15-crypt.c @@ -246,7 +246,8 @@ int main(int argc, char * const argv[]) fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); return 1; } - ctx->use_std_output = 1; + ctx->error_file = stderr; + ctx->debug_file = stdout; ctx->debug = opt_debug; if (opt_reader >= ctx->reader_count || opt_reader < 0) { fprintf(stderr, "Illegal reader number. Only %d reader(s) configured.\n", ctx->reader_count); diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 2a419065..26fc0a50 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -288,84 +288,92 @@ int change_pin(void) return 0; } -static int generate_cert_filename(struct sc_pkcs15_card *p15card, - const struct sc_pkcs15_cert_info *info, - char *fname, int len) +int read_and_cache_file(const struct sc_path *path) { - char *homedir; - char cert_id[SC_PKCS15_MAX_ID_SIZE*2+1]; - int i, r; + struct sc_file tmpfile; + u8 buf[16384]; + int r; - homedir = getenv("HOME"); - if (homedir == NULL) - return -1; - cert_id[0] = 0; - for (i = 0; i < info->id.len; i++) { - char tmp[3]; - - sprintf(tmp, "%02X", info->id.value[i]); - strcat(cert_id, tmp); + if (!quiet) { + printf("Reading file "); + hex_dump(stdout, path->value, path->len, ""); + printf("...\n"); } - r = snprintf(fname, len, "%s/%s/%s_%s_%s.crt", homedir, - SC_PKCS15_CACHE_DIR, p15card->label, - p15card->serial_number, cert_id); - if (r < 0) + r = sc_select_file(card, path, &tmpfile); + if (r != 0) { + fprintf(stderr, "sc_select_file() failed: %s\n", sc_strerror(r)); return -1; + } + if (tmpfile.acl[SC_AC_OP_READ] != SC_AC_NONE) { + if (!quiet) + printf("Skipping; ACL for read operation is not NONE.\n"); + return -1; + } + r = sc_read_binary(card, 0, buf, tmpfile.size, 0); + if (r < 0) { + fprintf(stderr, "sc_read_binary() failed: %s\n", sc_strerror(r)); + return -1; + } + r = sc_pkcs15_cache_file(p15card, path, buf, tmpfile.size); + if (r) { + fprintf(stderr, "Unable to cache file: %s\n", sc_strerror(r)); + return -1; + } return 0; } int learn_card(void) { struct stat stbuf; - char fname[512], *home; + char dir[120]; int r, i; - home = getenv("HOME"); - if (home == NULL) { - fprintf(stderr, "No $HOME environment variable set.\n"); + r = sc_get_cache_dir(ctx, dir, sizeof(dir)); + if (r) { + fprintf(stderr, "Unable to find cache directory: %s\n", sc_strerror(r)); return 1; } - sprintf(fname, "%s/%s", home, SC_PKCS15_CACHE_DIR); - r = stat(fname, &stbuf); + r = stat(dir, &stbuf); if (r) { - printf("No '%s' directory found, creating...\n", fname); - r = mkdir(fname, 0700); + printf("No '%s' directory found, creating...\n", dir); + r = mkdir(dir, 0700); if (r) { perror("Directory creation failed"); return 1; } } - printf("Using cache directory '%s'.\n", fname); + printf("Using cache directory '%s'.\n", dir); r = sc_pkcs15_enum_certificates(p15card); if (r < 0) { fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r)); return 1; } + r = sc_pkcs15_enum_private_keys(p15card); + if (r < 0) { + fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r)); + return 1; + } + r = sc_pkcs15_enum_pins(p15card); + if (r < 0) { + fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r)); + return 1; + } + for (i = 0; i < SC_PKCS15_DF_TYPE_COUNT; i++) { + int file_nr; + struct sc_pkcs15_df *df = &p15card->df[i]; + + for (file_nr = 0; file_nr < df->count; file_nr++) { + struct sc_file *file = df->file[file_nr]; + + read_and_cache_file(&file->path); + } + } printf("Caching %d certificate(s)...\n", r); - p15card->use_cache = 0; for (i = 0; i < p15card->cert_count; i++) { struct sc_pkcs15_cert_info *cinfo = &p15card->cert_info[i]; - struct sc_pkcs15_cert *cert; - FILE *crtf; - printf("Reading certificate: %s...\n", cinfo->com_attr.label); - r = sc_pkcs15_read_certificate(p15card, cinfo, &cert); - if (r) { - fprintf(stderr, "Certificate read failed: %s\n", sc_strerror(r)); - return 1; - } - r = generate_cert_filename(p15card, cinfo, fname, sizeof(fname)); - if (r) - return 1; - crtf = fopen(fname, "w"); - if (crtf == NULL) { - perror(fname); - return 1; - } - fwrite(cert->data, cert->data_len, 1, crtf); - fclose(crtf); - - sc_pkcs15_free_certificate(cert); + printf("[%s]\n", cinfo->com_attr.label); + read_and_cache_file(&cinfo->path); } return 0; @@ -441,10 +449,9 @@ int main(int argc, char * const argv[]) fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); return 1; } - ctx->use_std_output = 1; + ctx->error_file = stderr; + ctx->debug_file = stdout; ctx->debug = opt_debug; - if (opt_no_cache) - ctx->use_cache = 0; if (opt_reader >= ctx->reader_count || opt_reader < 0) { fprintf(stderr, "Illegal reader number. Only %d reader(s) configured.\n", ctx->reader_count); err = 1; @@ -477,6 +484,8 @@ int main(int argc, char * const argv[]) err = 1; goto end; } + if (opt_no_cache) + p15card->use_cache = 0; if (!quiet) fprintf(stderr, "Found %s!\n", p15card->label); if (do_learn_card) { diff --git a/src/tools/util.c b/src/tools/util.c index 49d9b699..931601ff 100644 --- a/src/tools/util.c +++ b/src/tools/util.c @@ -23,12 +23,15 @@ void print_binary(FILE *f, const u8 *buf, int count) (void) fflush(f); } -void hex_dump(FILE *f, const u8 *in, int len) +void hex_dump(FILE *f, const u8 *in, int len, const char *sep) { int i; - for (i = 0; i < len; i++) - fprintf(f, "%02X ", in[i]); + for (i = 0; i < len; i++) { + if (sep != NULL && i) + fprintf(f, "%s", sep); + fprintf(f, "%02X", in[i]); + } } void hex_dump_asc(FILE *f, const u8 *in, size_t count, int addr) diff --git a/src/tools/util.h b/src/tools/util.h index 35620f9f..87300396 100644 --- a/src/tools/util.h +++ b/src/tools/util.h @@ -22,7 +22,7 @@ extern const struct option options[]; extern const char *option_help[]; void print_binary(FILE *f, const u8 *buf, int count); -void hex_dump(FILE *f, const u8 *in, int len); +void hex_dump(FILE *f, const u8 *in, int len, const char *sep); void hex_dump_asc(FILE *f, const u8 *in, size_t count, int addr); void print_usage_and_die(const char *pgmname); const char * acl_to_str(unsigned int acl);