- 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:
parent
ec83c728ad
commit
c1cac5f311
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,34 +91,22 @@ 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:
|
||||
outf = stderr;
|
||||
if (ctx->log_errors == 0)
|
||||
return;
|
||||
outf = ctx->error_file;
|
||||
break;
|
||||
|
||||
case SC_LOG_TYPE_DEBUG:
|
||||
outf = stdout;
|
||||
outf = ctx->debug_file;
|
||||
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;
|
||||
}
|
||||
p = buf + r;
|
||||
left = sizeof(buf) - r;
|
||||
|
||||
if (vsnprintf(p, left, format, args) < 0)
|
||||
return;
|
||||
if (ctx->use_std_output) {
|
||||
const char *color_pfx = "", *color_sfx = "";
|
||||
if (use_color(ctx, outf)) {
|
||||
color_sfx = "\33[0m";
|
||||
switch (type) {
|
||||
@ -132,9 +118,22 @@ void do_log2(struct sc_context *ctx, int type, const char *file,
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
r = vsnprintf(p, left, format, args);
|
||||
if (r < 0)
|
||||
return;
|
||||
p += r;
|
||||
left -= r;
|
||||
|
||||
fprintf(outf, "%s%s%s", color_pfx, buf, color_sfx);
|
||||
fflush(outf);
|
||||
}
|
||||
}
|
||||
|
||||
void sc_hex_dump(struct sc_context *ctx, const u8 *in, size_t count,
|
||||
|
@ -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;
|
||||
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
132
src/libopensc/pkcs15-cache.c
Normal file
132
src/libopensc/pkcs15-cache.c
Normal 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;
|
||||
}
|
@ -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,
|
||||
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);
|
||||
|
||||
r = sc_asn1_decode(ctx, asn1_cert, *buf, *buflen, buf, buflen);
|
||||
/* 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));
|
||||
|
||||
/* 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)
|
||||
|
@ -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,
|
||||
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));
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -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,
|
||||
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));
|
||||
|
||||
/* 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,
|
||||
|
@ -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,9 +534,6 @@ 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);
|
||||
@ -569,10 +562,6 @@ int sc_pkcs15_bind(struct sc_card *card,
|
||||
tmppath.len += 2;
|
||||
} else
|
||||
tmppath = p15card->file_tokeninfo.path;
|
||||
} else {
|
||||
defaults->defaults_func(p15card, defaults->arg);
|
||||
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,32 +606,19 @@ 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->next = obj;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
@ -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
|
||||
|
@ -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[] = {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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,13 +1118,13 @@ 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,
|
||||
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,
|
||||
add_object(p15card, &p15card->df[SC_PKCS15_CDF], file_no,
|
||||
SC_PKCS15_TYPE_CERT_X509, &cert, sizeof(cert)),
|
||||
|
||||
memset(&prkey, 0, sizeof(prkey));
|
||||
@ -1112,7 +1135,7 @@ 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,
|
||||
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");
|
||||
@ -1120,7 +1143,7 @@ int create_pkcs15()
|
||||
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,
|
||||
add_object(p15card, &p15card->df[SC_PKCS15_PRKDF], file_no,
|
||||
SC_PKCS15_TYPE_PRKEY_RSA, &prkey, sizeof(prkey)),
|
||||
|
||||
memset(&pin, 0, sizeof(pin));
|
||||
@ -1133,7 +1156,7 @@ 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,
|
||||
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");
|
||||
@ -1144,7 +1167,7 @@ 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,
|
||||
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);
|
||||
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -23,13 +23,16 @@ 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++)
|
||||
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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user