From 20adb4b39c17a9b344e1555eca776a87dd7ec1e2 Mon Sep 17 00:00:00 2001 From: jey Date: Wed, 16 Jan 2002 23:59:18 +0000 Subject: [PATCH] - 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 --- THANKS | 2 +- src/libopensc/asn1.c | 10 +-- src/libopensc/asn1.h | 2 +- src/libopensc/iso7816.c | 100 +++++++++++++++++++++- src/libopensc/log.c | 5 ++ src/libopensc/log.h | 1 + src/libopensc/opensc-pkcs15.h | 52 ++++++++--- src/libopensc/opensc.h | 11 ++- src/libopensc/pkcs15-cert.c | 94 ++++++++++---------- src/libopensc/pkcs15-pin.c | 2 +- src/libopensc/pkcs15-prkey.c | 2 +- src/libopensc/pkcs15-sec.c | 8 +- src/libopensc/pkcs15.c | 157 ++++++++++++++++++++++++++-------- src/libopensc/pkcs15.h | 52 ++++++++--- src/libopensc/sc-asn1.h | 2 +- src/libopensc/sc-log.h | 1 + src/libopensc/sc.c | 2 +- src/libopensc/sec.c | 94 ++++++-------------- src/tools/Makefile.am | 1 + src/tools/opensc-explorer.c | 64 ++++++++++---- src/tools/pkcs15-crypt.c | 6 +- 21 files changed, 455 insertions(+), 213 deletions(-) diff --git a/THANKS b/THANKS index c93af665..70e61ca9 100644 --- a/THANKS +++ b/THANKS @@ -2,4 +2,4 @@ The following people provided inspiration, moral support and/or valuable information during the development of OpenSC: Antti Partanen -Antti Siltanen +David Corcoran diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index eace72d8..d6ecea9c 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -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, - size_t len, struct sc_pkcs15_object *obj, + size_t len, struct sc_asn1_pkcs15_object *obj, int depth) { int r; @@ -729,7 +729,7 @@ static int asn1_decode_p15_object(struct sc_context *ctx, const u8 *in, 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) { int r; @@ -885,7 +885,7 @@ static int asn1_decode_entry(struct sc_context *ctx, struct sc_asn1_entry *entry break; case SC_ASN1_PKCS15_OBJECT: 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; case SC_ASN1_CALLBACK: if (entry->parm != NULL) @@ -1061,7 +1061,7 @@ static int asn1_encode_entry(struct sc_context *ctx, const struct sc_asn1_entry } break; 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; case SC_ASN1_CALLBACK: 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); } 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)); if (buf) free(buf); diff --git a/src/libopensc/asn1.h b/src/libopensc/asn1.h index 620b1b06..77cbcb38 100644 --- a/src/libopensc/asn1.h +++ b/src/libopensc/asn1.h @@ -33,7 +33,7 @@ struct sc_asn1_entry { void *arg; }; -struct sc_pkcs15_object { +struct sc_asn1_pkcs15_object { struct sc_pkcs15_common_obj_attr *com_attr; struct sc_asn1_entry *asn1_class_attr; struct sc_asn1_entry *asn1_subclass_attr; diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 2dbb2802..a2776188 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -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); } +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 = { NULL, }; @@ -566,9 +658,11 @@ const struct sc_card_driver * sc_get_iso7816_driver(void) iso_ops.select_file = iso7816_select_file; iso_ops.get_challenge = iso7816_get_challenge; iso_ops.create_file = iso7816_create_file; - iso_ops.delete_file = iso7816_delete_file; - iso_ops.list_files = iso7816_list_files; - iso_ops.verify = iso7816_verify; + iso_ops.delete_file = iso7816_delete_file; + iso_ops.list_files = iso7816_list_files; + 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; } diff --git a/src/libopensc/log.c b/src/libopensc/log.c index 3dac0f11..b1a97587 100644 --- a/src/libopensc/log.c +++ b/src/libopensc/log.c @@ -173,3 +173,8 @@ void sc_hex_dump(struct sc_context *ctx, const u8 *in, size_t count, lines++; } } + +void sc_perror(struct sc_context *ctx, int error, const char *str) +{ + error(ctx, "%s: %s\n", sc_strerror(error), str); +} diff --git a/src/libopensc/log.h b/src/libopensc/log.h index 8592c43c..a10542c7 100644 --- a/src/libopensc/log.h +++ b/src/libopensc/log.h @@ -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, char *out, size_t outlen); +void sc_perror(struct sc_context *ctx, int error, const char *str); #endif diff --git a/src/libopensc/opensc-pkcs15.h b/src/libopensc/opensc-pkcs15.h index d12b3c30..bd2fa69b 100644 --- a/src/libopensc/opensc-pkcs15.h +++ b/src/libopensc/opensc-pkcs15.h @@ -125,6 +125,13 @@ 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; @@ -136,21 +143,31 @@ struct sc_pkcs15_prkey_info { int modulus_length; }; -#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 +struct sc_pkcs15_object { + int type; + void *data; + + /* For linked list purposes */ + struct sc_pkcs15_object *next; +}; +#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_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 { @@ -199,6 +216,9 @@ int sc_pkcs15_bind(struct sc_card *card, * memory allocations done on the card object. */ 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, const struct sc_pkcs15_prkey_info *prkey, 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, 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, const struct sc_pkcs15_id *id2); 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_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[]; #ifdef __cplusplus diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index e2306c14..989c414d 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -195,12 +195,18 @@ struct sc_file { #define SC_SEC_OPERATION_DECIPHER 0 #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 { int algorithm_ref; struct sc_path key_file_id; int operation; int key_ref; + + int flags; }; /* @@ -291,8 +297,7 @@ struct sc_card_operations { /* restore_security_env: Restores a previously saved security * environment, and stores information about the environment to * , if not NULL. */ - int (*restore_security_env)(struct sc_card *card, int se_num, - struct sc_security_env *env_out); + int (*restore_security_env)(struct sc_card *card, int se_num); /* set_security_env: Initializes the security environment on card * according to , and stores the environment as on the @@ -470,7 +475,7 @@ int sc_get_challenge(struct sc_card *card, u8 * rndout, size_t len); /* ISO 7816-8 related functions */ int sc_restore_security_env(struct sc_card *card, int se_num); 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, u8 * out, size_t outlen); int sc_compute_signature(struct sc_card *card, const u8 * data, diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index 5d5a4493..05623e98 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -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], asn1_x509_cert_attr[2], asn1_type_cert_attr[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 }; u8 id_value[128]; 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; } -static int encode_x509_cert_info(struct sc_context *ctx, - struct sc_pkcs15_cert_info *cert, - u8 ** buf, size_t *buflen) +int sc_pkcs15_encode_cdf_entry(struct sc_pkcs15_card *p15card, + const struct sc_pkcs15_object *obj, + u8 **buf, size_t *bufsize) { 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]; - 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 }; 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_cert, asn1_cert); - sc_format_asn1_entry(asn1_com_cert_attr + 0, (void *) &cert->id, NULL, 1); - if (cert->authority) - sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &cert->authority, NULL, 1); - sc_format_asn1_entry(asn1_x509_cert_attr + 0, (void *) &cert->path, NULL, 1); + sc_format_asn1_entry(asn1_com_cert_attr + 0, (void *) &infop->id, NULL, 1); + if (infop->authority) + sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &infop->authority, 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_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; } -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) { int i; @@ -408,36 +383,57 @@ 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 *card, - struct sc_file *file) +static int get_certs_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(card->card, &file->path, file); + 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(card->card, 0, buf, file->size, 0); + 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 tmp; + struct sc_pkcs15_cert_info info, *infop; + struct sc_pkcs15_object *objp; - r = parse_x509_cert_info(card->card->ctx, - &tmp, &p, &bytes_left); + 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; - if (card->cert_count >= SC_PKCS15_MAX_CERTS) - return SC_ERROR_TOO_MANY_OBJECTS; - card->cert_info[card->cert_count] = tmp; - card->cert_count++; + infop = malloc(sizeof(info)); + if (infop == NULL) + return SC_ERROR_OUT_OF_MEMORY; + 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); return 0; @@ -461,7 +457,7 @@ int sc_pkcs15_enum_certificates(struct sc_pkcs15_card *card) type = df_types[j]; 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) break; } diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c index bc715cd6..42807cff 100644 --- a/src/libopensc/pkcs15-pin.c +++ b/src/libopensc/pkcs15-pin.c @@ -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}, { 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 }; struct sc_asn1_entry asn1_pin[] = { { "pin", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &pin_obj }, diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 955c96e7..c8edfa77 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -77,7 +77,7 @@ static int parse_rsa_prkey_info(struct sc_context *ctx, { 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 }; struct sc_asn1_entry asn1_prkey[] = { { "privateRSAKey", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, &prkey_obj }, diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index bbd25f70..8e99db57 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -39,6 +39,8 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, senv.key_file_id = prkey->file_id; senv.operation = SC_SEC_OPERATION_DECIPHER; 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); 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 */ SC_TEST_RET(ctx, r, "sc_restore_security_env() failed"); #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"); r = sc_decipher(p15card->card, in, inlen, out, outlen); 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.operation = SC_SEC_OPERATION_SIGN; 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); 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 */ SC_TEST_RET(ctx, r, "sc_restore_security_env() failed"); #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"); r = sc_compute_signature(p15card->card, in, inlen, out, outlen); SC_TEST_RET(ctx, r, "sc_compute_signature() failed"); diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index bd32ad63..08c8a4ea 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -128,7 +128,7 @@ err: 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; 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); - r = sc_asn1_encode(card->card->ctx, asn1_tokeninfo, buf, buflen); + r = sc_asn1_encode(ctx, asn1_tokeninfo, buf, buflen); 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 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; u8 *buf; size_t buflen; char line[10240]; - r = encode_tokeninfo(card, &buf, &buflen); + r = encode_tokeninfo(card->ctx, p15card, &buf, &buflen); 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; } - 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); return 0; } @@ -260,10 +260,9 @@ static int parse_dir(const u8 * buf, size_t buflen, struct sc_pkcs15_card *card) 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_context *ctx = card->card->ctx; int r; size_t label_len; @@ -290,20 +289,17 @@ static int encode_dir(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen) #endif r = sc_asn1_encode(ctx, asn1_dir, buf, buflen); if (r) { - error(card->card->ctx, "sc_asn1_encode() failed: %s\n", + error(ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r)); return r; } return 0; } - - /* FIXME: This should be done using sc_update_binary(), * 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; u8 *buf; size_t bufsize; @@ -314,9 +310,9 @@ int sc_pkcs15_create_dir(struct sc_pkcs15_card *p15card) sc_format_path("3F00", &path); r = sc_select_file(card, &path, NULL); 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_hex_dump(p15card->card->ctx, buf, bufsize, line, sizeof(line)); + sc_hex_dump(card->ctx, buf, bufsize, line, sizeof(line)); free(buf); printf("%s", line); @@ -380,11 +376,13 @@ static int parse_odf(const u8 * buf, int buflen, struct sc_pkcs15_card *card) 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_asn1_entry asn1_obj_or_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_odf = NULL; @@ -415,7 +413,7 @@ static int encode_odf(struct sc_pkcs15_card *card, u8 **buf, size_t *buflen) break; } if (type == -1) { - error(card->card->ctx, "Unsupported DF type.\n"); + error(ctx, "Unsupported DF type.\n"); continue; } 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; - r = sc_asn1_encode(card->card->ctx, asn1_odf, buf, buflen); + r = sc_asn1_encode(ctx, asn1_odf, buf, buflen); err: if (asn1_paths != NULL) free(asn1_paths); @@ -436,16 +434,16 @@ err: 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; size_t buflen; char line[10240]; int r; - r = encode_odf(p15card, &buf, &buflen); - SC_TEST_RET(p15card->card->ctx, r, "ODF encoding failed"); - sc_hex_dump(p15card->card->ctx, buf, buflen, line, sizeof(line)); + r = encode_odf(card->ctx, p15card, &buf, &buflen); + SC_TEST_RET(card->ctx, r, "ODF encoding failed"); + sc_hex_dump(card->ctx, buf, buflen, line, sizeof(line)); printf("ODF:\n%s", line); return 0; } @@ -456,6 +454,44 @@ static const struct sc_pkcs15_defaults * find_defaults(u8 *dir, int dirlen) 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, 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); ctx = card->ctx; SC_FUNC_CALLED(ctx, 1); - p15card = malloc(sizeof(struct sc_pkcs15_card)); + p15card = sc_pkcs15_card_new(); if (p15card == NULL) return SC_ERROR_OUT_OF_MEMORY; - memset(p15card, 0, sizeof(struct sc_pkcs15_card)); p15card->card = card; 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 i, j; - assert(p15card != NULL); SC_FUNC_CALLED(p15card->card->ctx, 1); - for (j = 0; j < SC_PKCS15_DF_TYPE_COUNT; j++) - 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); + sc_pkcs15_card_free(p15card); 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, const struct sc_pkcs15_id *id2) { diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index d12b3c30..bd2fa69b 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -125,6 +125,13 @@ 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; @@ -136,21 +143,31 @@ struct sc_pkcs15_prkey_info { int modulus_length; }; -#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 +struct sc_pkcs15_object { + int type; + void *data; + + /* For linked list purposes */ + struct sc_pkcs15_object *next; +}; +#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_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 { @@ -199,6 +216,9 @@ int sc_pkcs15_bind(struct sc_card *card, * memory allocations done on the card object. */ 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, const struct sc_pkcs15_prkey_info *prkey, 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, 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, const struct sc_pkcs15_id *id2); 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_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[]; #ifdef __cplusplus diff --git a/src/libopensc/sc-asn1.h b/src/libopensc/sc-asn1.h index 620b1b06..77cbcb38 100644 --- a/src/libopensc/sc-asn1.h +++ b/src/libopensc/sc-asn1.h @@ -33,7 +33,7 @@ struct sc_asn1_entry { void *arg; }; -struct sc_pkcs15_object { +struct sc_asn1_pkcs15_object { struct sc_pkcs15_common_obj_attr *com_attr; struct sc_asn1_entry *asn1_class_attr; struct sc_asn1_entry *asn1_subclass_attr; diff --git a/src/libopensc/sc-log.h b/src/libopensc/sc-log.h index 8592c43c..a10542c7 100644 --- a/src/libopensc/sc-log.h +++ b/src/libopensc/sc-log.h @@ -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, char *out, size_t outlen); +void sc_perror(struct sc_context *ctx, int error, const char *str); #endif diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 20b65807..c22e0cff 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -33,7 +33,7 @@ #ifdef VERSION const char *sc_version = VERSION; #else -#warning FIXME: version info +#warning FIXME: version info undefined const char *sc_version = "(undef)"; #endif diff --git a/src/libopensc/sec.c b/src/libopensc/sec.c index 465a0d04..f4d2ffe4 100644 --- a/src/libopensc/sec.c +++ b/src/libopensc/sec.c @@ -24,74 +24,6 @@ #include #include -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, 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)); } +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, const u8 *pin, size_t pinlen, int *tries_left) { diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 5676a13d..af2e1e17 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -1,5 +1,6 @@ # Process this file with automake to create Makefile.in +CC = ccmalloc gcc INCLUDES = @CFLAGS_PCSC@ @CFLAGS_OPENSC@ LDFLAGS = @LDFLAGS@ @LIBOPENSC@ diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index eab2a034..6034890e 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -42,7 +42,7 @@ const char *option_help[] = { NULL }; const char *cmds[] = { "ls", "cd", "debug", "cat", "info", "create", "delete", - "verify", "put", "get" + "verify", "put", "get", "mkdir" }; const int nr_cmds = sizeof(cmds)/sizeof(cmds[0]); @@ -376,12 +376,31 @@ int do_info(const char *arg) 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", ¤t_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, ¤t_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) { struct sc_path path; struct sc_file file; int size; - int i, r; + int i; if (arg_to_path(arg, &path) != 0) goto usage; @@ -397,24 +416,37 @@ int do_create(const char *arg, const char *arg2) file.size = (size_t) size; file.status = SC_FILE_STATUS_ACTIVATED; - r = sc_create_file(card, &file); - if (r) { - check_ret(r, SC_AC_OP_CREATE, "CREATE FILE failed", ¤t_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, ¤t_path, NULL); - if (r) { - printf("unable to select parent file: %s\n", sc_strerror(r)); - die(1); - } - return 0; + return create_file(&file); usage: printf("Usage: create \n"); 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 \n"); + return -1; +} + int do_delete(const char *arg) { struct sc_path path; @@ -657,6 +689,8 @@ int handle_cmd(int cmd, const char *arg, const char *arg2) return do_put(arg, arg2); case 9: return do_get(arg, arg2); + case 10: + return do_mkdir(arg, arg2); default: printf("Don't know how to handle command.\n"); } diff --git a/src/tools/pkcs15-crypt.c b/src/tools/pkcs15-crypt.c index c85de360..ae4d9506 100644 --- a/src/tools/pkcs15-crypt.c +++ b/src/tools/pkcs15-crypt.c @@ -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ä * @@ -198,7 +198,7 @@ int main(int argc, char * const argv[]) if (c == -1) break; if (c == '?') - print_usage_and_die("opensc-crypt"); + print_usage_and_die("pkcs15-crypt"); switch (c) { case 's': do_sign++; @@ -236,7 +236,7 @@ int main(int argc, char * const argv[]) } } if (action_count == 0) - print_usage_and_die("opensc-crypt"); + print_usage_and_die("pkcs15-crypt"); r = sc_establish_context(&ctx); if (r) { fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));