- continued to improve PKCS #15 generation

- fixed a few problems in sc_set_security_env
- started to implement Better (tm) object handling for
  PKCS #15 objects


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@167 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
jey 2002-01-16 23:59:18 +00:00
parent 2d95b18b27
commit 20adb4b39c
21 changed files with 455 additions and 213 deletions

2
THANKS
View File

@ -2,4 +2,4 @@ The following people provided inspiration, moral support and/or valuable
information during the development of OpenSC: information during the development of OpenSC:
Antti Partanen <antti.partanen@vrk.intermin.fi> Antti Partanen <antti.partanen@vrk.intermin.fi>
Antti Siltanen <antti.siltanen@siltanet.fi> David Corcoran <corcoran@linuxnet.com>

View File

@ -703,7 +703,7 @@ static const struct sc_asn1_entry c_asn1_p15_obj[5] = {
}; };
static int asn1_decode_p15_object(struct sc_context *ctx, const u8 *in, static int asn1_decode_p15_object(struct sc_context *ctx, const u8 *in,
size_t len, struct sc_pkcs15_object *obj, size_t len, struct sc_asn1_pkcs15_object *obj,
int depth) int depth)
{ {
int r; int r;
@ -729,7 +729,7 @@ static int asn1_decode_p15_object(struct sc_context *ctx, const u8 *in,
return r; return r;
} }
static int asn1_encode_p15_object(struct sc_context *ctx, const struct sc_pkcs15_object *obj, static int asn1_encode_p15_object(struct sc_context *ctx, const struct sc_asn1_pkcs15_object *obj,
u8 **buf, size_t *bufsize, int depth) u8 **buf, size_t *bufsize, int depth)
{ {
int r; int r;
@ -885,7 +885,7 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_entry *entry
break; break;
case SC_ASN1_PKCS15_OBJECT: case SC_ASN1_PKCS15_OBJECT:
if (entry->parm != NULL) if (entry->parm != NULL)
r = asn1_decode_p15_object(ctx, obj, objlen, (struct sc_pkcs15_object *) parm, depth); r = asn1_decode_p15_object(ctx, obj, objlen, (struct sc_asn1_pkcs15_object *) parm, depth);
break; break;
case SC_ASN1_CALLBACK: case SC_ASN1_CALLBACK:
if (entry->parm != NULL) if (entry->parm != NULL)
@ -1061,7 +1061,7 @@ static int asn1_encode_entry(struct sc_context *ctx, const struct sc_asn1_entry
} }
break; break;
case SC_ASN1_PKCS15_OBJECT: case SC_ASN1_PKCS15_OBJECT:
r = asn1_encode_p15_object(ctx, (const struct sc_pkcs15_object *) parm, &buf, &buflen, depth); r = asn1_encode_p15_object(ctx, (const struct sc_asn1_pkcs15_object *) parm, &buf, &buflen, depth);
break; break;
case SC_ASN1_CALLBACK: case SC_ASN1_CALLBACK:
r = callback_func(ctx, entry->arg, &buf, &buflen, depth); r = callback_func(ctx, entry->arg, &buf, &buflen, depth);
@ -1071,7 +1071,7 @@ static int asn1_encode_entry(struct sc_context *ctx, const struct sc_asn1_entry
assert(0); assert(0);
} }
if (r) { if (r) {
error(ctx, "decoding of ASN.1 object '%s' failed: %s\n", entry->name, error(ctx, "encoding of ASN.1 object '%s' failed: %s\n", entry->name,
sc_strerror(r)); sc_strerror(r));
if (buf) if (buf)
free(buf); free(buf);

View File

@ -33,7 +33,7 @@ struct sc_asn1_entry {
void *arg; void *arg;
}; };
struct sc_pkcs15_object { struct sc_asn1_pkcs15_object {
struct sc_pkcs15_common_obj_attr *com_attr; struct sc_pkcs15_common_obj_attr *com_attr;
struct sc_asn1_entry *asn1_class_attr; struct sc_asn1_entry *asn1_class_attr;
struct sc_asn1_entry *asn1_subclass_attr; struct sc_asn1_entry *asn1_subclass_attr;

View File

@ -538,6 +538,98 @@ static int iso7816_verify(struct sc_card *card, unsigned int type, int ref,
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
} }
static int iso7816_set_security_env(struct sc_card *card,
const struct sc_security_env *env,
int se_num)
{
struct sc_apdu apdu;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 *p;
int r, locked = 0;
assert(card != NULL && env != NULL);
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
switch (env->operation) {
case SC_SEC_OPERATION_DECIPHER:
apdu.p1 = 0x41;
apdu.p2 = 0xB8;
break;
case SC_SEC_OPERATION_SIGN:
apdu.p1 = 0x81;
apdu.p2 = 0xB6;
break;
default:
return SC_ERROR_INVALID_ARGUMENTS;
}
apdu.le = 0;
p = sbuf;
if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
*p++ = 0x80; /* algorithm reference */
*p++ = env->algorithm_ref >> 8;
*p++ = env->algorithm_ref & 0xFF;
}
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
*p++ = 0x81;
*p++ = env->key_file_id.len;
memcpy(p, env->key_file_id.value, env->key_file_id.len);
p += env->key_file_id.len;
}
if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
*p++ = 0x84;
*p++ = env->key_ref >> 8;
*p++ = env->key_ref & 0xFF;
}
r = p - sbuf;
apdu.lc = r;
apdu.datalen = r;
apdu.data = sbuf;
apdu.resplen = 0;
if (se_num > 0) {
r = sc_lock(card);
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
locked = 1;
}
if (apdu.datalen != 0) {
r = sc_transmit_apdu(card, &apdu);
if (r) {
sc_perror(card->ctx, r, "APDU transmit failed");
goto err;
}
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
if (r) {
sc_perror(card->ctx, r, "Card returned error");
goto err;
}
}
if (se_num <= 0)
return 0;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
r = sc_transmit_apdu(card, &apdu);
sc_unlock(card);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
err:
if (locked)
sc_unlock(card);
return r;
}
static int iso7816_restore_security_env(struct sc_card *card, int se_num)
{
struct sc_apdu apdu;
int r;
u8 rbuf[MAX_BUFFER_SIZE];
assert(card != NULL);
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, se_num);
apdu.resplen = sizeof(rbuf) > 250 ? 250 : sizeof(rbuf);
apdu.resp = rbuf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
}
static struct sc_card_operations iso_ops = { static struct sc_card_operations iso_ops = {
NULL, NULL,
}; };
@ -566,9 +658,11 @@ const struct sc_card_driver * sc_get_iso7816_driver(void)
iso_ops.select_file = iso7816_select_file; iso_ops.select_file = iso7816_select_file;
iso_ops.get_challenge = iso7816_get_challenge; iso_ops.get_challenge = iso7816_get_challenge;
iso_ops.create_file = iso7816_create_file; iso_ops.create_file = iso7816_create_file;
iso_ops.delete_file = iso7816_delete_file; iso_ops.delete_file = iso7816_delete_file;
iso_ops.list_files = iso7816_list_files; iso_ops.list_files = iso7816_list_files;
iso_ops.verify = iso7816_verify; iso_ops.verify = iso7816_verify;
iso_ops.set_security_env = iso7816_set_security_env;
iso_ops.restore_security_env = iso7816_restore_security_env;
} }
return &iso_driver; return &iso_driver;
} }

View File

@ -173,3 +173,8 @@ void sc_hex_dump(struct sc_context *ctx, const u8 *in, size_t count,
lines++; lines++;
} }
} }
void sc_perror(struct sc_context *ctx, int error, const char *str)
{
error(ctx, "%s: %s\n", sc_strerror(error), str);
}

View File

@ -66,5 +66,6 @@ void do_log2(struct sc_context *ctx, int facility, const char *file,
void sc_hex_dump(struct sc_context *ctx, const u8 *buf, size_t len, void sc_hex_dump(struct sc_context *ctx, const u8 *buf, size_t len,
char *out, size_t outlen); char *out, size_t outlen);
void sc_perror(struct sc_context *ctx, int error, const char *str);
#endif #endif

View File

@ -125,6 +125,13 @@ struct sc_pkcs15_cert_info {
#define SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE 0x08 #define SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE 0x08
#define SC_PKCS15_PRKEY_ACCESS_LOCAL 0x10 #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_prkey_info {
struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_common_obj_attr com_attr;
@ -136,21 +143,31 @@ struct sc_pkcs15_prkey_info {
int modulus_length; int modulus_length;
}; };
#define SC_PKCS15_PRKDF 0 struct sc_pkcs15_object {
#define SC_PKCS15_PUKDF 1 int type;
#define SC_PKCS15_PUKDF_TRUSTED 2 void *data;
#define SC_PKCS15_SKDF 3
#define SC_PKCS15_CDF 4 /* For linked list purposes */
#define SC_PKCS15_CDF_TRUSTED 5 struct sc_pkcs15_object *next;
#define SC_PKCS15_CDF_USEFUL 6 };
#define SC_PKCS15_DODF 7
#define SC_PKCS15_AODF 8
#define SC_PKCS15_DF_TYPE_COUNT 9
#define SC_PKCS15_PRKDF 0
#define SC_PKCS15_PUKDF 1
#define SC_PKCS15_PUKDF_TRUSTED 2
#define SC_PKCS15_SKDF 3
#define SC_PKCS15_CDF 4
#define SC_PKCS15_CDF_TRUSTED 5
#define SC_PKCS15_CDF_USEFUL 6
#define SC_PKCS15_DODF 7
#define SC_PKCS15_AODF 8
#define SC_PKCS15_DF_TYPE_COUNT 9
#define SC_PKCS15_MAX_DFS 4
struct sc_pkcs15_df { struct sc_pkcs15_df {
struct sc_file *file[SC_PKCS15_MAX_DFS]; struct sc_file *file[SC_PKCS15_MAX_DFS];
int count, record_length; struct sc_pkcs15_object *obj[SC_PKCS15_MAX_DFS];
int count, record_length, type;
}; };
struct sc_pkcs15_card { struct sc_pkcs15_card {
@ -199,6 +216,9 @@ int sc_pkcs15_bind(struct sc_card *card,
* memory allocations done on the card object. */ * memory allocations done on the card object. */
int sc_pkcs15_unbind(struct sc_pkcs15_card *card); int sc_pkcs15_unbind(struct sc_pkcs15_card *card);
struct sc_pkcs15_card * sc_pkcs15_card_new();
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card);
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey, const struct sc_pkcs15_prkey_info *prkey,
const u8 *in, int inlen, u8 *out, int outlen); const u8 *in, int inlen, u8 *out, int outlen);
@ -248,11 +268,19 @@ int sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *card,
const struct sc_pkcs15_id *id, const struct sc_pkcs15_id *id,
struct sc_pkcs15_pin_info **out); struct sc_pkcs15_pin_info **out);
int sc_pkcs15_encode_df(struct sc_pkcs15_card *card,
struct sc_pkcs15_df *df, int file_nr,
u8 **buf, size_t *bufsize);
int sc_pkcs15_encode_cdf_entry(struct sc_pkcs15_card *card,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize);
int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1, int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1,
const struct sc_pkcs15_id *id2); const struct sc_pkcs15_id *id2);
void sc_pkcs15_print_id(const struct sc_pkcs15_id *id); void sc_pkcs15_print_id(const struct sc_pkcs15_id *id);
int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out); 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, struct sc_pkcs15_object *new_obj);
extern const struct sc_pkcs15_defaults sc_pkcs15_card_table[]; extern const struct sc_pkcs15_defaults sc_pkcs15_card_table[];
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -195,12 +195,18 @@ struct sc_file {
#define SC_SEC_OPERATION_DECIPHER 0 #define SC_SEC_OPERATION_DECIPHER 0
#define SC_SEC_OPERATION_SIGN 1 #define SC_SEC_OPERATION_SIGN 1
/* sc_security_env flags */
#define SC_SEC_ENV_ALG_REF_PRESENT 0x01
#define SC_SEC_ENV_FILE_REF_PRESENT 0x02
#define SC_SEC_ENV_KEY_REF_PRESENT 0x04
struct sc_security_env { struct sc_security_env {
int algorithm_ref; int algorithm_ref;
struct sc_path key_file_id; struct sc_path key_file_id;
int operation; int operation;
int key_ref; int key_ref;
int flags;
}; };
/* /*
@ -291,8 +297,7 @@ struct sc_card_operations {
/* restore_security_env: Restores a previously saved security /* restore_security_env: Restores a previously saved security
* environment, and stores information about the environment to * environment, and stores information about the environment to
* <env_out>, if not NULL. */ * <env_out>, if not NULL. */
int (*restore_security_env)(struct sc_card *card, int se_num, int (*restore_security_env)(struct sc_card *card, int se_num);
struct sc_security_env *env_out);
/* set_security_env: Initializes the security environment on card /* set_security_env: Initializes the security environment on card
* according to <env>, and stores the environment as <se_num> on the * according to <env>, and stores the environment as <se_num> on the
@ -470,7 +475,7 @@ int sc_get_challenge(struct sc_card *card, u8 * rndout, size_t len);
/* ISO 7816-8 related functions */ /* ISO 7816-8 related functions */
int sc_restore_security_env(struct sc_card *card, int se_num); int sc_restore_security_env(struct sc_card *card, int se_num);
int sc_set_security_env(struct sc_card *card, int sc_set_security_env(struct sc_card *card,
const struct sc_security_env *env); const struct sc_security_env *env, int se_num);
int sc_decipher(struct sc_card *card, const u8 * crgram, size_t crgram_len, int sc_decipher(struct sc_card *card, const u8 * crgram, size_t crgram_len,
u8 * out, size_t outlen); u8 * out, size_t outlen);
int sc_compute_signature(struct sc_card *card, const u8 * data, int sc_compute_signature(struct sc_card *card, const u8 * data,

View File

@ -309,7 +309,7 @@ static int parse_x509_cert_info(struct sc_context *ctx,
struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4], struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4],
asn1_x509_cert_attr[2], asn1_type_cert_attr[2], asn1_x509_cert_attr[2], asn1_type_cert_attr[2],
asn1_cert[2]; asn1_cert[2];
struct sc_pkcs15_object cert_obj = { &cert->com_attr, asn1_com_cert_attr, NULL, struct sc_asn1_pkcs15_object cert_obj = { &cert->com_attr, asn1_com_cert_attr, NULL,
asn1_type_cert_attr }; asn1_type_cert_attr };
u8 id_value[128]; u8 id_value[128];
int id_type, id_value_len = sizeof(id_value); int id_type, id_value_len = sizeof(id_value);
@ -337,14 +337,16 @@ static int parse_x509_cert_info(struct sc_context *ctx,
return r; return r;
} }
static int encode_x509_cert_info(struct sc_context *ctx, int sc_pkcs15_encode_cdf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_cert_info *cert, const struct sc_pkcs15_object *obj,
u8 ** buf, size_t *buflen) u8 **buf, size_t *bufsize)
{ {
struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4], struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4],
asn1_x509_cert_attr[2], asn1_type_cert_attr[2], asn1_x509_cert_attr[2], asn1_type_cert_attr[2],
asn1_cert[2]; asn1_cert[2];
const struct sc_pkcs15_object cert_obj = { &cert->com_attr, asn1_com_cert_attr, NULL, struct sc_pkcs15_cert_info *infop =
(struct sc_pkcs15_cert_info *) obj->data;
const struct sc_asn1_pkcs15_object cert_obj = { &infop->com_attr, asn1_com_cert_attr, NULL,
asn1_type_cert_attr }; asn1_type_cert_attr };
int r; int r;
@ -354,45 +356,18 @@ static int encode_x509_cert_info(struct sc_context *ctx,
sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr); sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr);
sc_copy_asn1_entry(c_asn1_cert, asn1_cert); sc_copy_asn1_entry(c_asn1_cert, asn1_cert);
sc_format_asn1_entry(asn1_com_cert_attr + 0, (void *) &cert->id, NULL, 1); sc_format_asn1_entry(asn1_com_cert_attr + 0, (void *) &infop->id, NULL, 1);
if (cert->authority) if (infop->authority)
sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &cert->authority, NULL, 1); sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &infop->authority, NULL, 1);
sc_format_asn1_entry(asn1_x509_cert_attr + 0, (void *) &cert->path, NULL, 1); sc_format_asn1_entry(asn1_x509_cert_attr + 0, (void *) &infop->path, NULL, 1);
sc_format_asn1_entry(asn1_type_cert_attr + 0, (void *) asn1_x509_cert_attr, NULL, 1); sc_format_asn1_entry(asn1_type_cert_attr + 0, (void *) asn1_x509_cert_attr, NULL, 1);
sc_format_asn1_entry(asn1_cert + 0, (void *) &cert_obj, NULL, 1); sc_format_asn1_entry(asn1_cert + 0, (void *) &cert_obj, NULL, 1);
r = sc_asn1_encode(ctx, asn1_cert, buf, buflen); r = sc_asn1_encode(p15card->card->ctx, asn1_cert, buf, bufsize);
return r; return r;
} }
int sc_pkcs15_create_cdf(struct sc_pkcs15_card *p15card,
struct sc_file *file,
const struct sc_pkcs15_cert_info **certs)
{
u8 *buf = NULL, *tmp;
size_t bufsize = 0, tmpsize;
int i = 0, r;
const struct sc_pkcs15_cert_info *cert;
char str[10240];
for (i = 0; (cert = certs[i]) != NULL; i++) {
r = encode_x509_cert_info(p15card->card->ctx,
(struct sc_pkcs15_cert_info *) cert,
&tmp, &tmpsize);
if (r) {
free(buf);
return r;
}
buf = realloc(buf, bufsize + tmpsize);
memcpy(buf + bufsize, tmp, tmpsize);
bufsize += tmpsize;
}
sc_hex_dump(p15card->card->ctx, buf, bufsize, str, sizeof(str));
printf("CDF:\n%s\n", str);
return 0;
}
void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert) void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert)
{ {
int i; int i;
@ -408,36 +383,57 @@ void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert)
printf("\n"); printf("\n");
} }
static int get_certs_from_file(struct sc_pkcs15_card *card, static int get_certs_from_file(struct sc_pkcs15_card *p15card,
struct sc_file *file) struct sc_pkcs15_df *df,
int file_nr)
{ {
int r; int r;
size_t bytes_left; size_t bytes_left;
u8 buf[2048]; u8 buf[2048];
const u8 *p = buf; const u8 *p = buf;
struct sc_file *file = df->file[file_nr];
r = sc_select_file(card->card, &file->path, file); r = sc_select_file(p15card->card, &file->path, file);
if (r) if (r)
return r; return r;
if (file->size > sizeof(buf)) if (file->size > sizeof(buf))
return SC_ERROR_BUFFER_TOO_SMALL; return SC_ERROR_BUFFER_TOO_SMALL;
r = sc_read_binary(card->card, 0, buf, file->size, 0); r = sc_read_binary(p15card->card, 0, buf, file->size, 0);
if (r < 0) if (r < 0)
return r; return r;
bytes_left = r; bytes_left = r;
do { do {
struct sc_pkcs15_cert_info tmp; struct sc_pkcs15_cert_info info, *infop;
struct sc_pkcs15_object *objp;
r = parse_x509_cert_info(card->card->ctx, memset(&info, 0, sizeof(info));
&tmp, &p, &bytes_left); r = parse_x509_cert_info(p15card->card->ctx,
&info, &p, &bytes_left);
if (r == SC_ERROR_ASN1_END_OF_CONTENTS) if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
break; break;
if (r) if (r)
return r; return r;
if (card->cert_count >= SC_PKCS15_MAX_CERTS) infop = malloc(sizeof(info));
return SC_ERROR_TOO_MANY_OBJECTS; if (infop == NULL)
card->cert_info[card->cert_count] = tmp; return SC_ERROR_OUT_OF_MEMORY;
card->cert_count++; memcpy(infop, &info, sizeof(info));
objp = malloc(sizeof(struct sc_pkcs15_object));
if (objp == NULL) {
free(infop);
return SC_ERROR_OUT_OF_MEMORY;
}
objp->type = SC_PKCS15_TYPE_CERT_X509;
objp->data = infop;
r = sc_pkcs15_add_object(p15card->card->ctx, df, file_nr, objp);
if (r) {
free(infop);
free(objp);
return r;
}
if (p15card->cert_count >= SC_PKCS15_MAX_PRKEYS)
break;
p15card->cert_info[p15card->cert_count] = info;
p15card->cert_count++;
} while (bytes_left); } while (bytes_left);
return 0; return 0;
@ -461,7 +457,7 @@ int sc_pkcs15_enum_certificates(struct sc_pkcs15_card *card)
type = df_types[j]; type = df_types[j];
for (i = 0; i < card->df[type].count; i++) { for (i = 0; i < card->df[type].count; i++) {
r = get_certs_from_file(card, card->df[type].file[i]); r = get_certs_from_file(card, &card->df[type], i);
if (r != 0) if (r != 0)
break; break;
} }

View File

@ -54,7 +54,7 @@ static int parse_pin_info(struct sc_context *ctx,
{ "pinAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_pin_attr}, { "pinAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, asn1_pin_attr},
{ NULL } { NULL }
}; };
struct sc_pkcs15_object pin_obj = { &pin->com_attr, asn1_com_ao_attr, NULL, struct sc_asn1_pkcs15_object pin_obj = { &pin->com_attr, asn1_com_ao_attr, NULL,
asn1_type_pin_attr }; asn1_type_pin_attr };
struct sc_asn1_entry asn1_pin[] = { struct sc_asn1_entry asn1_pin[] = {
{ "pin", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &pin_obj }, { "pin", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &pin_obj },

View File

@ -77,7 +77,7 @@ static int parse_rsa_prkey_info(struct sc_context *ctx,
{ NULL } { NULL }
}; };
struct sc_pkcs15_object prkey_obj = { &prkey->com_attr, asn1_com_key_attr, struct sc_asn1_pkcs15_object prkey_obj = { &prkey->com_attr, asn1_com_key_attr,
asn1_com_prkey_attr, asn1_type_attr }; asn1_com_prkey_attr, asn1_type_attr };
struct sc_asn1_entry asn1_prkey[] = { struct sc_asn1_entry asn1_prkey[] = {
{ "privateRSAKey", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &prkey_obj }, { "privateRSAKey", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &prkey_obj },

View File

@ -39,6 +39,8 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
senv.key_file_id = prkey->file_id; senv.key_file_id = prkey->file_id;
senv.operation = SC_SEC_OPERATION_DECIPHER; senv.operation = SC_SEC_OPERATION_DECIPHER;
senv.key_ref = 0x0100 | prkey->key_reference; senv.key_ref = 0x0100 | prkey->key_reference;
senv.flags = SC_SEC_ENV_ALG_REF_PRESENT | SC_SEC_ENV_FILE_REF_PRESENT;
senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT;
SC_FUNC_CALLED(ctx, 1); SC_FUNC_CALLED(ctx, 1);
r = sc_select_file(p15card->card, &p15card->file_app.path, r = sc_select_file(p15card->card, &p15card->file_app.path,
@ -49,7 +51,7 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
r = sc_restore_security_env(p15card->card, 0); /* empty SE */ r = sc_restore_security_env(p15card->card, 0); /* empty SE */
SC_TEST_RET(ctx, r, "sc_restore_security_env() failed"); SC_TEST_RET(ctx, r, "sc_restore_security_env() failed");
#endif #endif
r = sc_set_security_env(p15card->card, &senv); r = sc_set_security_env(p15card->card, &senv, 0);
SC_TEST_RET(ctx, r, "sc_set_security_env() failed"); SC_TEST_RET(ctx, r, "sc_set_security_env() failed");
r = sc_decipher(p15card->card, in, inlen, out, outlen); r = sc_decipher(p15card->card, in, inlen, out, outlen);
SC_TEST_RET(ctx, r, "sc_decipher() failed"); SC_TEST_RET(ctx, r, "sc_decipher() failed");
@ -77,6 +79,8 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
senv.key_file_id = prkey->file_id; senv.key_file_id = prkey->file_id;
senv.operation = SC_SEC_OPERATION_SIGN; senv.operation = SC_SEC_OPERATION_SIGN;
senv.key_ref = 0x0100 | prkey->key_reference; senv.key_ref = 0x0100 | prkey->key_reference;
senv.flags = SC_SEC_ENV_ALG_REF_PRESENT | SC_SEC_ENV_FILE_REF_PRESENT;
senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT;
SC_FUNC_CALLED(ctx, 1); SC_FUNC_CALLED(ctx, 1);
r = sc_select_file(p15card->card, &p15card->file_app.path, r = sc_select_file(p15card->card, &p15card->file_app.path,
@ -87,7 +91,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
r = sc_restore_security_env(p15card->card, 0); /* empty SE */ r = sc_restore_security_env(p15card->card, 0); /* empty SE */
SC_TEST_RET(ctx, r, "sc_restore_security_env() failed"); SC_TEST_RET(ctx, r, "sc_restore_security_env() failed");
#endif #endif
r = sc_set_security_env(p15card->card, &senv); r = sc_set_security_env(p15card->card, &senv, 0);
SC_TEST_RET(ctx, r, "sc_set_security_env() failed"); SC_TEST_RET(ctx, r, "sc_set_security_env() failed");
r = sc_compute_signature(p15card->card, in, inlen, out, outlen); r = sc_compute_signature(p15card->card, in, inlen, out, outlen);
SC_TEST_RET(ctx, r, "sc_compute_signature() failed"); SC_TEST_RET(ctx, r, "sc_compute_signature() failed");

View File

@ -128,7 +128,7 @@ err:
return; return;
} }
int encode_tokeninfo(struct sc_pkcs15_card *card, u8 ** buf, size_t *buflen) int encode_tokeninfo(struct sc_context *ctx, struct sc_pkcs15_card *card, u8 ** buf, size_t *buflen)
{ {
int i, r; int i, r;
u8 serial[128]; u8 serial[128];
@ -170,27 +170,27 @@ int encode_tokeninfo(struct sc_pkcs15_card *card, u8 ** buf, size_t *buflen)
} }
sc_format_asn1_entry(asn1_tokeninfo, asn1_toki, NULL, 1); sc_format_asn1_entry(asn1_tokeninfo, asn1_toki, NULL, 1);
r = sc_asn1_encode(card->card->ctx, asn1_tokeninfo, buf, buflen); r = sc_asn1_encode(ctx, asn1_tokeninfo, buf, buflen);
if (r) { if (r) {
error(card->card->ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r)); error(ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r));
return r; return r;
} }
return 0; return 0;
} }
int sc_pkcs15_create_tokeninfo(struct sc_pkcs15_card *card) int sc_pkcs15_create_tokeninfo(struct sc_card *card, struct sc_pkcs15_card *p15card)
{ {
int r; int r;
u8 *buf; u8 *buf;
size_t buflen; size_t buflen;
char line[10240]; char line[10240];
r = encode_tokeninfo(card, &buf, &buflen); r = encode_tokeninfo(card->ctx, p15card, &buf, &buflen);
if (r) { if (r) {
error(card->card->ctx, "Error encoding EF(TokenInfo): %s\n", sc_strerror(r)); error(card->ctx, "Error encoding EF(TokenInfo): %s\n", sc_strerror(r));
return r; return r;
} }
sc_hex_dump(card->card->ctx, buf, buflen, line, sizeof(line)); sc_hex_dump(card->ctx, buf, buflen, line, sizeof(line));
printf("%s\n", line); printf("%s\n", line);
return 0; return 0;
} }
@ -260,10 +260,9 @@ static int parse_dir(const u8 * buf, size_t buflen, struct sc_pkcs15_card *card)
return 0; return 0;
} }
static int encode_dir(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen) static int encode_dir(struct sc_context *ctx, struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
{ {
struct sc_asn1_entry asn1_ddo[5], asn1_dirrecord[5], asn1_dir[2]; struct sc_asn1_entry asn1_ddo[5], asn1_dirrecord[5], asn1_dir[2];
struct sc_context *ctx = card->card->ctx;
int r; int r;
size_t label_len; size_t label_len;
@ -290,20 +289,17 @@ static int encode_dir(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
#endif #endif
r = sc_asn1_encode(ctx, asn1_dir, buf, buflen); r = sc_asn1_encode(ctx, asn1_dir, buf, buflen);
if (r) { if (r) {
error(card->card->ctx, "sc_asn1_encode() failed: %s\n", error(ctx, "sc_asn1_encode() failed: %s\n",
sc_strerror(r)); sc_strerror(r));
return r; return r;
} }
return 0; return 0;
} }
/* FIXME: This should be done using sc_update_binary(), /* FIXME: This should be done using sc_update_binary(),
* and be generally wiser */ * and be generally wiser */
int sc_pkcs15_create_dir(struct sc_pkcs15_card *p15card) int sc_pkcs15_create_dir(struct sc_card *card, struct sc_pkcs15_card *p15card)
{ {
struct sc_card *card = p15card->card;
struct sc_path path; struct sc_path path;
u8 *buf; u8 *buf;
size_t bufsize; size_t bufsize;
@ -314,9 +310,9 @@ int sc_pkcs15_create_dir(struct sc_pkcs15_card *p15card)
sc_format_path("3F00", &path); sc_format_path("3F00", &path);
r = sc_select_file(card, &path, NULL); r = sc_select_file(card, &path, NULL);
SC_TEST_RET(card->ctx, r, "sc_select_file(MF) failed"); SC_TEST_RET(card->ctx, r, "sc_select_file(MF) failed");
r = encode_dir(p15card, &buf, &bufsize); r = encode_dir(card->ctx, p15card, &buf, &bufsize);
SC_TEST_RET(card->ctx, r, "EF(DIR) encoding failed"); SC_TEST_RET(card->ctx, r, "EF(DIR) encoding failed");
sc_hex_dump(p15card->card->ctx, buf, bufsize, line, sizeof(line)); sc_hex_dump(card->ctx, buf, bufsize, line, sizeof(line));
free(buf); free(buf);
printf("%s", line); printf("%s", line);
@ -380,11 +376,13 @@ static int parse_odf(const u8 * buf, int buflen, struct sc_pkcs15_card *card)
return 0; return 0;
} }
static int encode_odf(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen) static int encode_odf(struct sc_context *ctx, struct sc_pkcs15_card *card,
u8 **buf, size_t *buflen)
{ {
struct sc_path path; struct sc_path path;
struct sc_asn1_entry asn1_obj_or_path[] = { struct sc_asn1_entry asn1_obj_or_path[] = {
{ "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, &path }, { "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, &path },
{ NULL }
}; };
struct sc_asn1_entry *asn1_paths = NULL; struct sc_asn1_entry *asn1_paths = NULL;
struct sc_asn1_entry *asn1_odf = NULL; struct sc_asn1_entry *asn1_odf = NULL;
@ -415,7 +413,7 @@ static int encode_odf(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
break; break;
} }
if (type == -1) { if (type == -1) {
error(card->card->ctx, "Unsupported DF type.\n"); error(ctx, "Unsupported DF type.\n");
continue; continue;
} }
for (j = 0; j < df->count; j++) { for (j = 0; j < df->count; j++) {
@ -427,7 +425,7 @@ static int encode_odf(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen)
} }
} }
asn1_odf[df_count].name = NULL; asn1_odf[df_count].name = NULL;
r = sc_asn1_encode(card->card->ctx, asn1_odf, buf, buflen); r = sc_asn1_encode(ctx, asn1_odf, buf, buflen);
err: err:
if (asn1_paths != NULL) if (asn1_paths != NULL)
free(asn1_paths); free(asn1_paths);
@ -436,16 +434,16 @@ err:
return r; return r;
} }
int sc_pkcs15_create_odf(struct sc_pkcs15_card *p15card) int sc_pkcs15_create_odf(struct sc_card *card, struct sc_pkcs15_card *p15card)
{ {
u8 *buf; u8 *buf;
size_t buflen; size_t buflen;
char line[10240]; char line[10240];
int r; int r;
r = encode_odf(p15card, &buf, &buflen); r = encode_odf(card->ctx, p15card, &buf, &buflen);
SC_TEST_RET(p15card->card->ctx, r, "ODF encoding failed"); SC_TEST_RET(card->ctx, r, "ODF encoding failed");
sc_hex_dump(p15card->card->ctx, buf, buflen, line, sizeof(line)); sc_hex_dump(card->ctx, buf, buflen, line, sizeof(line));
printf("ODF:\n%s", line); printf("ODF:\n%s", line);
return 0; return 0;
} }
@ -456,6 +454,44 @@ static const struct sc_pkcs15_defaults * find_defaults(u8 *dir, int dirlen)
return NULL; return NULL;
} }
struct sc_pkcs15_card * sc_pkcs15_card_new()
{
struct sc_pkcs15_card *p15card;
int i;
p15card = malloc(sizeof(struct sc_pkcs15_card));
if (p15card == NULL)
return NULL;
memset(p15card, 0, sizeof(struct sc_pkcs15_card));
for (i = 0; i < SC_PKCS15_DF_TYPE_COUNT; i++)
p15card->df[i].type = i;
return p15card;
}
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card)
{
int i, j;
for (j = 0; j < SC_PKCS15_DF_TYPE_COUNT; j++)
for (i = 0; i < p15card->df[j].count; i++) {
struct sc_pkcs15_object *p;
if (p15card->df[j].file[i])
free(p15card->df[j].file[i]);
p = p15card->df[j].obj[i];
while (p != NULL) {
struct sc_pkcs15_object *p2 = p->next;
if (p->data != NULL)
free(p->data);
free(p);
p = p2;
}
}
free(p15card->label);
free(p15card->serial_number);
free(p15card->manufacturer_id);
free(p15card);
}
int sc_pkcs15_bind(struct sc_card *card, int sc_pkcs15_bind(struct sc_card *card,
struct sc_pkcs15_card **p15card_out) struct sc_pkcs15_card **p15card_out)
{ {
@ -470,10 +506,9 @@ int sc_pkcs15_bind(struct sc_card *card,
assert(sc_card_valid(card) && p15card_out != NULL); assert(sc_card_valid(card) && p15card_out != NULL);
ctx = card->ctx; ctx = card->ctx;
SC_FUNC_CALLED(ctx, 1); SC_FUNC_CALLED(ctx, 1);
p15card = malloc(sizeof(struct sc_pkcs15_card)); p15card = sc_pkcs15_card_new();
if (p15card == NULL) if (p15card == NULL)
return SC_ERROR_OUT_OF_MEMORY; return SC_ERROR_OUT_OF_MEMORY;
memset(p15card, 0, sizeof(struct sc_pkcs15_card));
p15card->card = card; p15card->card = card;
sc_format_path("2F00", &tmppath); sc_format_path("2F00", &tmppath);
@ -577,21 +612,73 @@ int sc_pkcs15_detect(struct sc_card *card)
int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card) int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card)
{ {
int i, j;
assert(p15card != NULL); assert(p15card != NULL);
SC_FUNC_CALLED(p15card->card->ctx, 1); SC_FUNC_CALLED(p15card->card->ctx, 1);
for (j = 0; j < SC_PKCS15_DF_TYPE_COUNT; j++) sc_pkcs15_card_free(p15card);
for (i = 0; i < p15card->df[j].count; i++)
if (p15card->df[j].file[i])
free(p15card->df[j].file[i]);
free(p15card->label);
free(p15card->serial_number);
free(p15card->manufacturer_id);
free(p15card);
return 0; return 0;
} }
int sc_pkcs15_add_object(struct sc_context *ctx, struct sc_pkcs15_df *df,
int file_nr, struct sc_pkcs15_object *obj)
{
struct sc_pkcs15_object *p = df->obj[file_nr];
obj->next = NULL;
if (p == NULL) {
df->obj[file_nr] = obj;
return 0;
}
while (p->next != NULL)
p = p->next;
p->next = obj;
return 0;
}
int sc_pkcs15_encode_df(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_df *df,
int file_no,
u8 **buf_out, size_t *bufsize_out)
{
u8 *buf = NULL, *tmp;
size_t bufsize = 0, tmpsize;
int r;
const struct sc_pkcs15_object *obj = df->obj[file_no];
char str[10240];
int (* func)(struct sc_pkcs15_card *, const struct sc_pkcs15_object *obj,
u8 **buf, size_t *bufsize) = NULL;
switch (df->type) {
case SC_PKCS15_PRKDF:
break;
case SC_PKCS15_CDF:
case SC_PKCS15_CDF_TRUSTED:
case SC_PKCS15_CDF_USEFUL:
func = sc_pkcs15_encode_cdf_entry;
break;
}
if (func == NULL) {
error(p15card->card->ctx, "unknown DF type\n");
return SC_ERROR_INVALID_ARGUMENTS;
}
while (obj != NULL) {
r = func(p15card, obj, &tmp, &tmpsize);
if (r) {
free(buf);
return r;
}
buf = realloc(buf, bufsize + tmpsize);
memcpy(buf + bufsize, tmp, tmpsize);
bufsize += tmpsize;
obj = obj->next;
}
sc_hex_dump(p15card->card->ctx, buf, bufsize, str, sizeof(str));
printf("DF:\n%s\n", str);
*buf_out = buf;
*bufsize_out = bufsize;
return 0;
}
int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1, int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1,
const struct sc_pkcs15_id *id2) const struct sc_pkcs15_id *id2)
{ {

View File

@ -125,6 +125,13 @@ struct sc_pkcs15_cert_info {
#define SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE 0x08 #define SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE 0x08
#define SC_PKCS15_PRKEY_ACCESS_LOCAL 0x10 #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_prkey_info {
struct sc_pkcs15_common_obj_attr com_attr; struct sc_pkcs15_common_obj_attr com_attr;
@ -136,21 +143,31 @@ struct sc_pkcs15_prkey_info {
int modulus_length; int modulus_length;
}; };
#define SC_PKCS15_PRKDF 0 struct sc_pkcs15_object {
#define SC_PKCS15_PUKDF 1 int type;
#define SC_PKCS15_PUKDF_TRUSTED 2 void *data;
#define SC_PKCS15_SKDF 3
#define SC_PKCS15_CDF 4 /* For linked list purposes */
#define SC_PKCS15_CDF_TRUSTED 5 struct sc_pkcs15_object *next;
#define SC_PKCS15_CDF_USEFUL 6 };
#define SC_PKCS15_DODF 7
#define SC_PKCS15_AODF 8
#define SC_PKCS15_DF_TYPE_COUNT 9
#define SC_PKCS15_PRKDF 0
#define SC_PKCS15_PUKDF 1
#define SC_PKCS15_PUKDF_TRUSTED 2
#define SC_PKCS15_SKDF 3
#define SC_PKCS15_CDF 4
#define SC_PKCS15_CDF_TRUSTED 5
#define SC_PKCS15_CDF_USEFUL 6
#define SC_PKCS15_DODF 7
#define SC_PKCS15_AODF 8
#define SC_PKCS15_DF_TYPE_COUNT 9
#define SC_PKCS15_MAX_DFS 4
struct sc_pkcs15_df { struct sc_pkcs15_df {
struct sc_file *file[SC_PKCS15_MAX_DFS]; struct sc_file *file[SC_PKCS15_MAX_DFS];
int count, record_length; struct sc_pkcs15_object *obj[SC_PKCS15_MAX_DFS];
int count, record_length, type;
}; };
struct sc_pkcs15_card { struct sc_pkcs15_card {
@ -199,6 +216,9 @@ int sc_pkcs15_bind(struct sc_card *card,
* memory allocations done on the card object. */ * memory allocations done on the card object. */
int sc_pkcs15_unbind(struct sc_pkcs15_card *card); int sc_pkcs15_unbind(struct sc_pkcs15_card *card);
struct sc_pkcs15_card * sc_pkcs15_card_new();
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card);
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_prkey_info *prkey, const struct sc_pkcs15_prkey_info *prkey,
const u8 *in, int inlen, u8 *out, int outlen); const u8 *in, int inlen, u8 *out, int outlen);
@ -248,11 +268,19 @@ int sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *card,
const struct sc_pkcs15_id *id, const struct sc_pkcs15_id *id,
struct sc_pkcs15_pin_info **out); struct sc_pkcs15_pin_info **out);
int sc_pkcs15_encode_df(struct sc_pkcs15_card *card,
struct sc_pkcs15_df *df, int file_nr,
u8 **buf, size_t *bufsize);
int sc_pkcs15_encode_cdf_entry(struct sc_pkcs15_card *card,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize);
int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1, int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1,
const struct sc_pkcs15_id *id2); const struct sc_pkcs15_id *id2);
void sc_pkcs15_print_id(const struct sc_pkcs15_id *id); void sc_pkcs15_print_id(const struct sc_pkcs15_id *id);
int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out); 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, struct sc_pkcs15_object *new_obj);
extern const struct sc_pkcs15_defaults sc_pkcs15_card_table[]; extern const struct sc_pkcs15_defaults sc_pkcs15_card_table[];
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -33,7 +33,7 @@ struct sc_asn1_entry {
void *arg; void *arg;
}; };
struct sc_pkcs15_object { struct sc_asn1_pkcs15_object {
struct sc_pkcs15_common_obj_attr *com_attr; struct sc_pkcs15_common_obj_attr *com_attr;
struct sc_asn1_entry *asn1_class_attr; struct sc_asn1_entry *asn1_class_attr;
struct sc_asn1_entry *asn1_subclass_attr; struct sc_asn1_entry *asn1_subclass_attr;

View File

@ -66,5 +66,6 @@ void do_log2(struct sc_context *ctx, int facility, const char *file,
void sc_hex_dump(struct sc_context *ctx, const u8 *buf, size_t len, void sc_hex_dump(struct sc_context *ctx, const u8 *buf, size_t len,
char *out, size_t outlen); char *out, size_t outlen);
void sc_perror(struct sc_context *ctx, int error, const char *str);
#endif #endif

View File

@ -33,7 +33,7 @@
#ifdef VERSION #ifdef VERSION
const char *sc_version = VERSION; const char *sc_version = VERSION;
#else #else
#warning FIXME: version info #warning FIXME: version info undefined
const char *sc_version = "(undef)"; const char *sc_version = "(undef)";
#endif #endif

View File

@ -24,74 +24,6 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
int sc_set_security_env(struct sc_card *card,
const struct sc_security_env *env)
{
struct sc_apdu apdu;
u8 sbuf[MAX_BUFFER_SIZE];
u8 *p;
int r;
assert(card != NULL && env != NULL);
SC_FUNC_CALLED(card->ctx, 2);
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
switch (env->operation) {
case SC_SEC_OPERATION_DECIPHER:
apdu.p1 = 0x41;
apdu.p2 = 0xB8;
break;
case SC_SEC_OPERATION_SIGN:
apdu.p1 = 0x81;
apdu.p2 = 0xB6;
break;
default:
return SC_ERROR_INVALID_ARGUMENTS;
}
apdu.le = 0;
p = sbuf;
if (env->algorithm_ref >= 0) {
*p++ = 0x80; /* algorithm reference */
*p++ = env->algorithm_ref >> 8;
*p++ = env->algorithm_ref & 0xFF;
}
if (env->key_file_id.len >= 0) {
*p++ = 0x81;
*p++ = env->key_file_id.len;
memcpy(p, env->key_file_id.value, env->key_file_id.len);
p += env->key_file_id.len;
}
if (env->key_ref >= 0) {
*p++ = 0x84;
*p++ = env->key_ref >> 8;
*p++ = env->key_ref & 0xFF;
}
r = p - sbuf;
apdu.lc = r;
apdu.datalen = r;
apdu.data = sbuf;
apdu.resplen = 0;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
}
int sc_restore_security_env(struct sc_card *card, int num)
{
struct sc_apdu apdu;
int r;
u8 rbuf[MAX_BUFFER_SIZE];
assert(card != NULL);
SC_FUNC_CALLED(card->ctx, 2);
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, num);
apdu.resplen = sizeof(rbuf) > 250 ? 250 : sizeof(rbuf);
apdu.resp = rbuf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
}
int sc_decipher(struct sc_card *card, int sc_decipher(struct sc_card *card,
const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen) const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
{ {
@ -159,6 +91,32 @@ int sc_compute_signature(struct sc_card *card,
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
} }
int sc_set_security_env(struct sc_card *card,
const struct sc_security_env *env,
int se_num)
{
int r;
assert(card != NULL);
SC_FUNC_CALLED(card->ctx, 2);
if (card->ops->set_security_env == NULL)
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
r = card->ops->set_security_env(card, env, se_num);
SC_FUNC_RETURN(card->ctx, 2, r);
}
int sc_restore_security_env(struct sc_card *card, int se_num)
{
int r;
assert(card != NULL);
SC_FUNC_CALLED(card->ctx, 2);
if (card->ops->restore_security_env == NULL)
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
r = card->ops->restore_security_env(card, se_num);
SC_FUNC_RETURN(card->ctx, 2, r);
}
int sc_verify(struct sc_card *card, unsigned int type, int ref, int sc_verify(struct sc_card *card, unsigned int type, int ref,
const u8 *pin, size_t pinlen, int *tries_left) const u8 *pin, size_t pinlen, int *tries_left)
{ {

View File

@ -1,5 +1,6 @@
# Process this file with automake to create Makefile.in # Process this file with automake to create Makefile.in
CC = ccmalloc gcc
INCLUDES = @CFLAGS_PCSC@ @CFLAGS_OPENSC@ INCLUDES = @CFLAGS_PCSC@ @CFLAGS_OPENSC@
LDFLAGS = @LDFLAGS@ @LIBOPENSC@ LDFLAGS = @LDFLAGS@ @LIBOPENSC@

View File

@ -42,7 +42,7 @@ const char *option_help[] = { NULL };
const char *cmds[] = { const char *cmds[] = {
"ls", "cd", "debug", "cat", "info", "create", "delete", "ls", "cd", "debug", "cat", "info", "create", "delete",
"verify", "put", "get" "verify", "put", "get", "mkdir"
}; };
const int nr_cmds = sizeof(cmds)/sizeof(cmds[0]); const int nr_cmds = sizeof(cmds)/sizeof(cmds[0]);
@ -376,12 +376,31 @@ int do_info(const char *arg)
return 0; return 0;
} }
int create_file(const struct sc_file *file)
{
int r;
r = sc_create_file(card, file);
if (r) {
check_ret(r, SC_AC_OP_CREATE, "CREATE FILE failed", &current_file);
return -1;
}
/* Make sure we're back in the parent directory, because on some cards
* CREATE FILE also selects the newly created file. */
r = sc_select_file(card, &current_path, NULL);
if (r) {
printf("unable to select parent file: %s\n", sc_strerror(r));
die(1);
}
return 0;
}
int do_create(const char *arg, const char *arg2) int do_create(const char *arg, const char *arg2)
{ {
struct sc_path path; struct sc_path path;
struct sc_file file; struct sc_file file;
int size; int size;
int i, r; int i;
if (arg_to_path(arg, &path) != 0) if (arg_to_path(arg, &path) != 0)
goto usage; goto usage;
@ -397,24 +416,37 @@ int do_create(const char *arg, const char *arg2)
file.size = (size_t) size; file.size = (size_t) size;
file.status = SC_FILE_STATUS_ACTIVATED; file.status = SC_FILE_STATUS_ACTIVATED;
r = sc_create_file(card, &file); return create_file(&file);
if (r) {
check_ret(r, SC_AC_OP_CREATE, "CREATE FILE failed", &current_file);
return -1;
}
/* Make sure we're back in the parent directory, because on some cards
* CREATE FILE also selects the newly created file. */
r = sc_select_file(card, &current_path, NULL);
if (r) {
printf("unable to select parent file: %s\n", sc_strerror(r));
die(1);
}
return 0;
usage: usage:
printf("Usage: create <file_id> <file_size>\n"); printf("Usage: create <file_id> <file_size>\n");
return -1; return -1;
} }
int do_mkdir(const char *arg, const char *arg2)
{
struct sc_path path;
struct sc_file file;
size_t size;
int i;
if (arg_to_path(arg, &path) != 0)
goto usage;
if (sscanf(arg2, "%d", &size) != 1)
goto usage;
memset(&file, 0, sizeof(file));
file.id = (path.value[0] << 8) | path.value[1];
file.type = SC_FILE_TYPE_DF;
for (i = 0; i < SC_MAX_AC_OPS; i++)
file.acl[i] = SC_AC_NONE;
file.size = size;
file.status = SC_FILE_STATUS_ACTIVATED;
return create_file(&file);
usage:
printf("Usage: mkdir <file_id> <df_size>\n");
return -1;
}
int do_delete(const char *arg) int do_delete(const char *arg)
{ {
struct sc_path path; struct sc_path path;
@ -657,6 +689,8 @@ int handle_cmd(int cmd, const char *arg, const char *arg2)
return do_put(arg, arg2); return do_put(arg, arg2);
case 9: case 9:
return do_get(arg, arg2); return do_get(arg, arg2);
case 10:
return do_mkdir(arg, arg2);
default: default:
printf("Don't know how to handle command.\n"); printf("Don't know how to handle command.\n");
} }

View File

@ -1,5 +1,5 @@
/* /*
* opensc-crypt.c: Tool for cryptography operations with SmartCards * pkcs15-crypt.c: Tool for cryptography operations with SmartCards
* *
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi> * Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
* *
@ -198,7 +198,7 @@ int main(int argc, char * const argv[])
if (c == -1) if (c == -1)
break; break;
if (c == '?') if (c == '?')
print_usage_and_die("opensc-crypt"); print_usage_and_die("pkcs15-crypt");
switch (c) { switch (c) {
case 's': case 's':
do_sign++; do_sign++;
@ -236,7 +236,7 @@ int main(int argc, char * const argv[])
} }
} }
if (action_count == 0) if (action_count == 0)
print_usage_and_die("opensc-crypt"); print_usage_and_die("pkcs15-crypt");
r = sc_establish_context(&ctx); r = sc_establish_context(&ctx);
if (r) { if (r) {
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));