- 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
This commit is contained in:
jey 2002-01-24 16:02:54 +00:00
parent ec83c728ad
commit c1cac5f311
21 changed files with 658 additions and 533 deletions

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -0,0 +1,132 @@
/*
* pkcs15-cache.c: PKCS #15 file caching functions
*
* Copyright (C) 2001 Juha Yrjölä <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,
* 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 <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <assert.h>
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;
}

View File

@ -29,8 +29,6 @@
#include <unistd.h>
#include <assert.h>
#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)

View File

@ -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;
}

View File

@ -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,

View File

@ -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)
{

View File

@ -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

View File

@ -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[] = {

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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");
}

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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)

View File

@ -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);