From bfd5b494364d8a9b2e18e5ed2651834abdf9b27e Mon Sep 17 00:00:00 2001 From: nils Date: Mon, 26 Jul 2004 18:47:23 +0000 Subject: [PATCH] pkcs15-init etc. support for pkcs15 data objects patch supplied by Victor Tarasov git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1877 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/pkcs11/framework-pkcs15.c | 200 +++++++++++++++++++++++++++++++++- src/pkcs11/pkcs11-global.c | 4 + src/pkcs15init/pkcs15-lib.c | 7 +- src/tools/pkcs11-tool.c | 196 ++++++++++++++++++++++++++++++++- src/tools/pkcs15-init.c | 10 ++ src/tools/util.c | 21 ++++ src/tools/util.h | 1 + 7 files changed, 431 insertions(+), 8 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 8b3decf9..2f81a005 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -106,9 +106,20 @@ struct pkcs15_pubkey_object { #define is_pubkey(obj) (__p15_type(obj) == SC_PKCS15_TYPE_PUBKEY_RSA) #define is_cert(obj) (__p15_type(obj) == SC_PKCS15_TYPE_CERT_X509) +struct pkcs15_data_object { + struct pkcs15_any_object base; + + struct sc_pkcs15_data_info *info; + struct sc_pkcs15_data *value; +}; +#define data_flags base.base.flags +#define data_p15obj base.p15_object +#define is_data(obj) (__p15_type(obj) == SC_PKCS15_TYPE_DATA_OBJECT) + extern struct sc_pkcs11_object_ops pkcs15_cert_ops; extern struct sc_pkcs11_object_ops pkcs15_prkey_ops; extern struct sc_pkcs11_object_ops pkcs15_pubkey_ops; +extern struct sc_pkcs11_object_ops pkcs15_dobj_ops; static int __pkcs15_release_object(struct pkcs15_any_object *); @@ -321,6 +332,28 @@ __pkcs15_create_prkey_object(struct pkcs15_fw_data *fw_data, return 0; } +static int +__pkcs15_create_data_object(struct pkcs15_fw_data *fw_data, + struct sc_pkcs15_object *object, struct pkcs15_any_object **data_object) +{ + struct pkcs15_data_object *dobj = NULL; + int rv; + + rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &dobj, + object, &pkcs15_dobj_ops, + sizeof(struct pkcs15_data_object)); + if (rv >= 0) { + dobj->info = (struct sc_pkcs15_data_info *) object->data; + dobj->value = NULL; + } + + if (data_object != NULL) + *data_object = (struct pkcs15_any_object *) dobj; + + return 0; +} + + static int pkcs15_create_pkcs11_objects(struct pkcs15_fw_data *fw_data, int p15_type, const char *name, @@ -590,6 +623,13 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card) if (rv < 0) return sc_to_cryptoki_error(rv, reader); + rv = pkcs15_create_pkcs11_objects(fw_data, + SC_PKCS15_TYPE_DATA_OBJECT, + "data object", + __pkcs15_create_data_object); + if (rv < 0) + return sc_to_cryptoki_error(rv, reader); + /* Match up related keys and certificates */ pkcs15_bind_related_objects(fw_data); @@ -610,14 +650,21 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card) for (j=0; j < fw_data->num_objects; j++) { struct pkcs15_any_object *obj = fw_data->objects[j]; - if (!is_privkey(obj) - || !sc_pkcs15_compare_id(&pin_info->auth_id, + if (__p15_type(obj) == -1) + continue; + else if (!sc_pkcs15_compare_id(&pin_info->auth_id, &obj->p15_object->auth_id)) continue; + if (is_privkey(obj)) { sc_debug(context, "Adding private key %d to PIN %d\n", j, i); pkcs15_add_object(slot, obj, NULL); } + else if (is_data(obj)) { + sc_debug(context, "Adding data object %d to PIN %d\n", j, i); + pkcs15_add_object(slot, obj, NULL); + } + } } /* Add all public objects to a virtual slot without pin protection */ @@ -1329,7 +1376,7 @@ CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card, struct sc_pkcs11_slot * rc = __pkcs15_create_prkey_object(fw_data, priv_key_obj, &priv_any_obj); if (rc == 0) - __pkcs15_create_pubkey_object(fw_data, pub_key_obj, &pub_any_obj); + rc = __pkcs15_create_pubkey_object(fw_data, pub_key_obj, &pub_any_obj); if (rc != 0) { sc_debug(context, "__pkcs15_create_pr/pubkey_object returned %d\n", rc); rv = sc_to_cryptoki_error(rc, p11card->reader); @@ -2008,6 +2055,148 @@ struct sc_pkcs11_object_ops pkcs15_pubkey_ops = { NULL }; + +/* PKCS#15 Data Object*/ + +void pkcs15_dobj_release(void *object) +{ + __pkcs15_release_object((struct pkcs15_any_object *) object); +} + +CK_RV pkcs15_dobj_set_attribute(struct sc_pkcs11_session *session, + void *object, CK_ATTRIBUTE_PTR attr) +{ + struct pkcs15_data_object *dobj = (struct pkcs15_data_object*) object; + + return pkcs15_set_attrib(session, dobj->base.p15_object, attr); +} + + +int pkcs15_dobj_get_value(struct sc_pkcs11_session *session, + struct pkcs15_data_object *dobj, + struct sc_pkcs15_data **out_data) +{ + int rv; + struct pkcs15_fw_data *fw_data = + (struct pkcs15_fw_data *) session->slot->card->fw_data; + struct pkcs15_slot_data *data = slot_data(session->slot->fw_data); + struct sc_card *card = session->slot->card->card; + int reader = session->slot->card->reader; + + if (!out_data) + return SC_ERROR_INVALID_ARGUMENTS; + + rv = sc_lock(card); + if (rv < 0) + return sc_to_cryptoki_error(rv, reader); + + if (slot_data_pin_info(data)) { + rv = revalidate_pin(data, session); + if (rv < 0) + goto done; + } + + if ((rv = sc_pkcs15_read_data_object(fw_data->p15_card, dobj->info, out_data)) < 0) + goto done; + +done: + sc_unlock(card); + if (rv < 0) + return sc_to_cryptoki_error(rv, reader); + + return rv; +} + + + +CK_RV pkcs15_dobj_get_attribute(struct sc_pkcs11_session *session, + void *object, + CK_ATTRIBUTE_PTR attr) +{ + struct pkcs15_data_object *dobj = (struct pkcs15_data_object*) object; + size_t len; + + switch (attr->type) { + case CKA_CLASS: + check_attribute_buffer(attr, sizeof(CK_OBJECT_CLASS)); + *(CK_OBJECT_CLASS*)attr->pValue = CKO_DATA; + break; + case CKA_TOKEN: + check_attribute_buffer(attr, sizeof(CK_BBOOL)); + *(CK_BBOOL*)attr->pValue = TRUE; + break; + case CKA_PRIVATE: + check_attribute_buffer(attr, sizeof(CK_BBOOL)); + *(CK_BBOOL*)attr->pValue = + (dobj->base.p15_object->flags & 0x01) != 0; + break; + case CKA_MODIFIABLE: + check_attribute_buffer(attr, sizeof(CK_BBOOL)); + *(CK_BBOOL*)attr->pValue = + (dobj->base.p15_object->flags & 0x02) != 0; + break; + case CKA_LABEL: + len = strlen(dobj->base.p15_object->label); + check_attribute_buffer(attr, len); + memcpy(attr->pValue, dobj->base.p15_object->label, len); + break; + case CKA_APPLICATION: + len = strlen(dobj->info->app_label); + check_attribute_buffer(attr, len); + memcpy(attr->pValue, dobj->info->app_label, len); + break; +#if 0 + case CKA_ID: + check_attribute_buffer(attr, dobj->info->id.len); + memcpy(attr->pValue, dobj->info->id.value, dobj->info->id.len); + break; +#endif + case CKA_OBJECT_ID: + { + int len = sizeof(dobj->info->app_oid); + + check_attribute_buffer(attr, len); + memcpy(attr->pValue, dobj->info->app_oid.value, len); + } + break; + case CKA_VALUE: + { + CK_RV rv; + struct sc_pkcs15_data *data = NULL; + + rv = pkcs15_dobj_get_value(session, dobj, &data); + if (rv!=CKR_OK) + return rv; + else if (!data) + return CKR_ATTRIBUTE_VALUE_INVALID; + + sc_debug(context, "data %p\n", data); + sc_debug(context, "data_len %i\n", data->data_len); + check_attribute_buffer(attr, data->data_len); + memcpy(attr->pValue, data->data, data->data_len); + } + break; + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + } + + return CKR_OK; +} + +struct sc_pkcs11_object_ops pkcs15_dobj_ops = { + pkcs15_dobj_release, + pkcs15_dobj_set_attribute, + pkcs15_dobj_get_attribute, + sc_pkcs11_any_cmp_attribute, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + + + /* * get_attribute helpers */ @@ -2218,14 +2407,15 @@ register_mechanisms(struct sc_pkcs11_card *p11card) num = card->algorithm_count; alg_info = card->algorithms; while (num--) { - if (alg_info->algorithm != SC_ALGORITHM_RSA) - continue; + if (alg_info->algorithm == SC_ALGORITHM_RSA) { if (alg_info->key_length < mech_info.ulMinKeySize) mech_info.ulMinKeySize = alg_info->key_length; if (alg_info->key_length > mech_info.ulMaxKeySize) mech_info.ulMaxKeySize = alg_info->key_length; flags |= alg_info->flags; + } + alg_info++; } diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index 68d7bba8..0b7b1230 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -58,6 +58,10 @@ CK_RV C_Initialize(CK_VOID_PTR pReserved) __card_detect_all(0); rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pReserved); + if (rv != CKR_OK) { + sc_release_context(context); + context = NULL; + } out: if (context != NULL) sc_debug(context, "C_Initialize: result = %d\n", rv); diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 265f1cf1..d46b349c 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -70,7 +70,7 @@ #define DEFAULT_PRKEY_FLAGS 0x03 #define DEFAULT_PUBKEY_FLAGS 0x02 #define DEFAULT_CERT_FLAGS 0x02 -#define DEFAULT_DATA_FLAGS 0x03 +#define DEFAULT_DATA_FLAGS 0x02 /* Handle encoding of PKCS15 on the card */ typedef int (*pkcs15_encoder)(struct sc_context *, @@ -2496,13 +2496,16 @@ set_user_pin_from_authid(struct sc_pkcs15_card *p15card, * Possible fix: store all file info from the profile on the card */ if (pin->path.len != 0) { - sc_file_t *df; + sc_file_t *df = NULL; r = sc_profile_get_file_by_path(profile, &pin->path, &df); if (r == SC_ERROR_FILE_NOT_FOUND && (r = sc_select_file(p15card->card, &pin->path, &df)) == 0) { sc_profile_add_file(profile, "pin-dir (auto)", df); } + + if (df) + sc_file_free(df); } return sc_keycache_set_pin_name(&pin->path, diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index c7adcdb0..92a92c93 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -41,6 +41,7 @@ enum { OPT_MODULE = 0x100, OPT_SLOT, OPT_SLOT_LABEL, + OPT_APPLICATION_ID, }; const struct option options[] = { @@ -58,6 +59,8 @@ const struct option options[] = { { "change-pin", 0, 0, 'c' }, { "keypairgen", 0, 0, 'k' }, { "write-object", 1, 0, 'w' }, + { "read-object", 0, 0, 'r' }, + { "application-id", 1, 0, OPT_APPLICATION_ID }, { "type", 1, 0, 'y' }, { "id", 1, 0, 'd' }, { "label", 1, 0, 'a' }, @@ -88,6 +91,8 @@ const char *option_help[] = { "Change your (user) PIN", "Key pair generation", "Write an object (key, cert) to the card", + "Get object's CKA_VALUE attribute (use with --type)", + "Specify the application id of the data object (use with --type data)", "Specify the type of object (e.g. cert, privkey, pubkey)", "Specify the id of the object", "Specify the label of the object", @@ -119,6 +124,7 @@ static CK_BYTE opt_object_id[100], new_object_id[100]; static size_t opt_object_id_len = 0, new_object_id_len = 0; static char * opt_object_label = NULL; static char * opt_pin = NULL; +static char * opt_application_id = NULL; static void *module = NULL; static CK_FUNCTION_LIST_PTR p11 = NULL; @@ -145,12 +151,14 @@ static int change_pin(CK_SLOT_ID, CK_SESSION_HANDLE); static void show_object(CK_SESSION_HANDLE, CK_OBJECT_HANDLE); static void show_key(CK_SESSION_HANDLE, CK_OBJECT_HANDLE, int); static void show_cert(CK_SESSION_HANDLE, CK_OBJECT_HANDLE); +static void show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj); static void sign_data(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE); static void hash_data(CK_SLOT_ID, CK_SESSION_HANDLE); static int gen_keypair(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE *, CK_OBJECT_HANDLE *); static int write_object(CK_SLOT_ID slot, CK_SESSION_HANDLE session); +static int read_object(CK_SLOT_ID slot, CK_SESSION_HANDLE session); static void set_id_attr(CK_SLOT_ID slot, CK_SESSION_HANDLE session); static int find_object(CK_SESSION_HANDLE, CK_OBJECT_CLASS, CK_OBJECT_HANDLE_PTR, @@ -173,6 +181,10 @@ static const char * CKR2Str(CK_ULONG res); static int p11_test(CK_SLOT_ID slot, CK_SESSION_HANDLE session); static int hex_to_bin(const char *in, CK_BYTE *out, size_t *outlen); static void test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE session); +static CK_RV find_object_with_attributes( + CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *out, + CK_ATTRIBUTE *attrs, CK_ULONG attrsLen, + CK_ULONG obj_index); /* win32 needs this in open(2) */ #ifndef O_BINARY @@ -193,6 +205,7 @@ main(int argc, char * const argv[]) int do_hash = 0; int do_gen_keypair = 0; int do_write_object = 0; + int do_read_object = 0; int do_set_id = 0; int do_test = 0; int do_test_kpgen_certwrite = 0; @@ -203,7 +216,7 @@ main(int argc, char * const argv[]) CK_RV rv; while (1) { - c = getopt_long(argc, argv, "ILMOa:d:e:hi:klm:o:p:scvty:w:z:", + c = getopt_long(argc, argv, "ILMOa:d:e:hi:klm:o:p:scvty:w:z:r", options, &long_optind); if (c == -1) break; @@ -241,6 +254,11 @@ main(int argc, char * const argv[]) opt_file_to_write = optarg; action_count++; break; + case 'r': + need_session |= NEED_SESSION_RO; + do_read_object = 1; + action_count++; + break; case 'e': need_session |= NEED_SESSION_RW; do_set_id = 1; @@ -259,6 +277,8 @@ main(int argc, char * const argv[]) opt_object_class = CKO_PRIVATE_KEY; else if (strcmp(optarg, "pubkey") == 0) opt_object_class = CKO_PUBLIC_KEY; + else if (strcmp(optarg, "data") == 0) + opt_object_class = CKO_DATA; else { printf("Unsupported object type \"%s\"\n", optarg); print_usage_and_die(); @@ -323,6 +343,9 @@ main(int argc, char * const argv[]) case OPT_MODULE: opt_module = optarg; break; + case OPT_APPLICATION_ID: + opt_application_id = optarg; + break; default: print_usage_and_die(); } @@ -448,6 +471,15 @@ main(int argc, char * const argv[]) write_object(opt_slot, session); } + if (do_read_object) { + if (opt_object_class_str == NULL) + fatal("You should specify type of the object to read"); + if (opt_object_id_len == 0 && opt_object_label == NULL && + opt_application_id == NULL) + fatal("You should specify at least one of the " + "object ID, object label or application ID\n"); + read_object(opt_slot, session); + } if (do_set_id) { if (opt_object_class_str == NULL) fatal("You should specify the object type with the -y option\n"); @@ -1041,6 +1073,43 @@ done: if (count == 0) return count; } +CK_RV find_object_with_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *out, + CK_ATTRIBUTE *attrs, CK_ULONG attrsLen, + CK_ULONG obj_index) +{ + CK_ULONG count, ii; + CK_OBJECT_HANDLE ret; + CK_RV rv; + + if (!out || !attrs || !attrsLen) + return CKR_ARGUMENTS_BAD; + else + *out = CK_INVALID_HANDLE; + + rv = p11->C_FindObjectsInit(session, attrs, attrsLen); + if (rv != CKR_OK) + return rv; + + for (ii = 0; ii < obj_index; ii++) { + rv = p11->C_FindObjects(session, &ret, 1, &count); + if (rv != CKR_OK) + return rv; + else if (!count) + goto done; + } + + rv = p11->C_FindObjects(session, &ret, 1, &count); + if (rv != CKR_OK) + return rv; + else if (count) + *out = ret; + +done: + p11->C_FindObjectsFinal(session); + return CKR_OK; +} + + CK_MECHANISM_TYPE find_mechanism(CK_SLOT_ID slot, CK_FLAGS flags, int stop_if_not_found) { @@ -1120,7 +1189,9 @@ ATTR_METHOD(KEY_TYPE, CK_KEY_TYPE); ATTR_METHOD(CERTIFICATE_TYPE, CK_CERTIFICATE_TYPE); ATTR_METHOD(MODULUS_BITS, CK_ULONG); VARATTR_METHOD(LABEL, char); +VARATTR_METHOD(APPLICATION, char); VARATTR_METHOD(ID, unsigned char); +VARATTR_METHOD(OBJECT_ID, unsigned char); VARATTR_METHOD(MODULUS, unsigned char); VARATTR_METHOD(VALUE, unsigned char); @@ -1139,6 +1210,9 @@ show_object(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) case CKO_CERTIFICATE: show_cert(sess, obj); break; + case CKO_DATA: + show_dobj(sess, obj); + break; default: printf("Object %u, type %u\n", (unsigned int) obj, @@ -1250,6 +1324,59 @@ show_cert(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) } } +void +show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) +{ + int *app_oid; + char *label; + CK_ULONG size; + + printf("Data object %u\n", (unsigned int) obj); + printf(" label: "); + if ((label = getLABEL(sess, obj, NULL)) != NULL) { + printf("'%s'\n", label); + free(label); + } + else { + printf("\n"); + } + + printf(" application: "); + if ((label = getAPPLICATION(sess, obj, NULL)) != NULL) { + printf("'%s'\n", label); + free(label); + } + else { + printf("\n"); + } + + printf(" app_id: "); + app_oid = (int *)getOBJECT_ID(sess, obj, &size); + if (app_oid != NULL && size) { + unsigned int n; + + size /= sizeof(int); + printf("%i", app_oid[0]); + if (app_oid[0] >= 0) + for (n = 1; (n < size) && (app_oid[n] >= 0); n++) + printf(".%i", app_oid[n]); + + printf("\n"); + free(app_oid); + } + else { + printf("\n"); + } + + printf(" flags: "); + if (getMODIFIABLE(sess, obj)) + printf(" modifiable"); + if (getPRIVATE(sess, obj)) + printf(" private"); + printf ("\n"); + +} + void get_token_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info) { @@ -1294,6 +1421,73 @@ get_mechanisms(CK_SLOT_ID slot, return ulCount; } +/* + * Read object CKA_VALUE attribute's value. + */ +int +read_object(CK_SLOT_ID slot, CK_SESSION_HANDLE session) +{ + CK_RV rv; + CK_ATTRIBUTE attrs[20]; + CK_OBJECT_CLASS clazz = opt_object_class; + CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE; + int nn_attrs = 0; + unsigned char *value = NULL; + CK_ULONG len; + FILE *out; + struct sc_object_id oid; + + if (opt_object_class_str != NULL) { + FILL_ATTR(attrs[nn_attrs], CKA_CLASS, + &clazz, sizeof(clazz)); + nn_attrs++; + } + + if (opt_object_id_len != 0) { + FILL_ATTR(attrs[nn_attrs], CKA_ID, + opt_object_id, opt_object_id_len); + nn_attrs++; + } + + if (opt_object_label != NULL) { + FILL_ATTR(attrs[nn_attrs], CKA_LABEL, + opt_object_label, strlen(opt_object_label)); + nn_attrs++; + } + + if (opt_application_id != NULL) { + parse_application_id(&oid, opt_application_id); + FILL_ATTR(attrs[nn_attrs], CKA_OBJECT_ID, + (unsigned char *)oid.value, sizeof(oid.value)); + nn_attrs++; + } + + rv = find_object_with_attributes(session, &obj, attrs, nn_attrs, 0); + if (rv != CKR_OK) + p11_fatal("find_object_with_attributes()", rv); + else if (obj==CK_INVALID_HANDLE) + fatal("object not found\n"); + + value = getVALUE(session, obj, &len); + if (value == NULL) + fatal("get CKA_VALUE failed\n"); + + if (opt_output) { + out = fopen(opt_output, "wb"); + if (out==NULL) + fatal("cannot open '%s'\n", opt_output); + } + else + out = stdout; + + if (fwrite(value, 1, len, out) != len) + fatal("cannot write to '%s'\n", opt_output); + if (opt_output) + fclose(out); + return 1; +} + + static int test_digest(CK_SLOT_ID slot) { diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index d41a2f47..175e9cda 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -114,6 +114,7 @@ enum { OPT_SECRET, OPT_PUBKEY_LABEL, OPT_CERT_LABEL, + OPT_APPLICATION_ID, OPT_PIN1 = 0x10000, /* don't touch these values */ OPT_PUK1 = 0x10001, @@ -146,6 +147,7 @@ const struct option options[] = { { "label", required_argument, 0, 'l' }, { "public-key-label", required_argument, 0, OPT_PUBKEY_LABEL }, { "cert-label", required_argument, 0, OPT_CERT_LABEL }, + { "application-id", required_argument, 0, OPT_APPLICATION_ID }, { "output-file", required_argument, 0, 'o' }, { "format", required_argument, 0, 'f' }, { "passphrase", required_argument, 0, OPT_PASSPHRASE }, @@ -195,6 +197,7 @@ const char * option_help[] = { "Specify label of PIN/key", "Specify public key label (use with --generate-key)", "Specify user cert label (use with --store-private-key)", + "Specify application id of data object (use with --store-data-object)", "Output public portion of generated key to file", "Specify key file format (default PEM)", "Specify passphrase for unlocking secret key", @@ -287,6 +290,7 @@ static char * opt_serial = 0; static char * opt_passphrase = 0; static char * opt_newkey = 0; static char * opt_outkey = 0; +static char * opt_application_id = 0; static unsigned int opt_x509_usage = 0; static int ignore_cmdline_pins = 0; static struct secret opt_secrets[MAX_SECRETS]; @@ -872,6 +876,9 @@ do_store_data_object(struct sc_profile *profile) if (opt_authid) sc_pkcs15_format_id(opt_authid, &args.auth_id); args.label = opt_label; + args.app_label = "pkcs15-init"; + + parse_application_id(&args.app_oid, opt_application_id); r = do_read_data_object(opt_infile, &data, &datalen); if (r >= 0) { @@ -1913,6 +1920,9 @@ handle_option(const struct option *opt) case OPT_SOFT_KEYGEN: opt_softkeygen = 1; break; + case OPT_APPLICATION_ID: + opt_application_id = optarg; + break; case 'T': opt_use_defkeys = 1; break; diff --git a/src/tools/util.c b/src/tools/util.c index 47ba42f5..5944ae7f 100644 --- a/src/tools/util.c +++ b/src/tools/util.c @@ -270,3 +270,24 @@ warn(const char *fmt, ...) fprintf(stderr, "\n"); va_end(ap); } + + +void parse_application_id(struct sc_object_id *oid, char *oid_str) +{ + int ii; + char *nb; + + if (!oid) + return; + + for (ii=0; iivalue[ii] = -1; + + nb = strtok(oid_str, "."); + for (ii=0; nb && ii < SC_MAX_OBJECT_ID_OCTETS; ii++) { + oid->value[ii] = strtol(nb, NULL, 10); + nb = strtok(NULL, "."); + } +} + + diff --git a/src/tools/util.h b/src/tools/util.h index 53907b5a..d5df5709 100644 --- a/src/tools/util.h +++ b/src/tools/util.h @@ -40,6 +40,7 @@ void fatal(const char *fmt, ...); /* All singing all dancing card connect routine */ int connect_card(struct sc_context *, struct sc_card **, int reader_id, int slot_id, int wait, int verbose); +void parse_application_id(struct sc_object_id *oid, char *oid_str); #ifdef __cplusplus }