diff --git a/src/tools/gpk-rw.profile b/src/tools/gpk.profile similarity index 56% rename from src/tools/gpk-rw.profile rename to src/tools/gpk.profile index 08cbfc42..6ed535a2 100644 --- a/src/tools/gpk-rw.profile +++ b/src/tools/gpk.profile @@ -14,12 +14,6 @@ CardInfo # creating files in the MF Key PRO 0x0001 "=TEST KEYTEST KEY" -# This is the application DF -DF - Path 3F005015 - AID A0:00:00:00:63:50:4B:43:53:2D:31:35 - ACL *=NONE - # Note: many commands use the short file ID (i.e. the lower 5 bits # of the FID) so you must be careful when picking FIDs for the # public key and PIN files. @@ -27,83 +21,37 @@ DF # Currently we do not support PIN files that can be updated # by CHV2. Far too messy. EF pinfile - Path 3F0050150000 + FileID 0000 Structure 0x21 # GPK specific RecordLength 8 Size 32 ACL *=NEVER -EF PKCS15-DIR - Path 3F002F00 - ACL *=NONE - -EF PKCS15-ODF - Path 3F0050155031 - ACL *=NONE - -EF PKCS15-TokenInfo - Path 3F0050155032 - ACL *=NONE - -EF PKCS15-AODF - Path 3F0050154401 - ACL *=NEVER READ=NONE UPDATE=CHV2 - -EF PKCS15-PrKDF - Path 3F0050154402 - ACL *=NEVER READ=NONE UPDATE=CHV2 - -EF PKCS15-PuKDF - Path 3F0050154403 - ACL *=NEVER READ=NONE UPDATE=CHV2 - -EF PKCS15-CDF - Path 3F0050154404 - ACL *=NEVER READ=NONE UPDATE=CHV2 - # Private key files. # GPK private key files will never let you read the private key # part, so it's okay to set READ=NONE. What's more, we need # read access so we're able to update the file. -EF pk1 - Path 3F005015000E +EF template-private-key + FileID 0006 # This is the base FileID Structure 0x2C # GPK specific ACL *=NEVER READ=NONE UPDATE=CHV2 WRITE=CHV2 -EF pk2 - Path 3F005015000F - Structure 0x2C # GPK specific - ACL *=NEVER READ=NONE UPDATE=CHV2 WRITE=CHV2 +EF template-public-key + FileID 8000 + Structure transparent + ACL *=NONE # CVH1. 7 attempts for the PIN, and 3 for the PUK # Reference 0x8 means "PIN0 in the local EFsc" in GPK parlance PIN CHV1 File pinfile - Label "Authentication PIN" Reference 0x8 Attempts 7 3 - AuthID 01 # CVH2. 7 attempts for the PIN, and 3 for the PUK # Reference 0xA means "PIN2 in the local EFsc" in GPK parlance PIN CHV2 File pinfile - Label "Non-repudiation PIN" Reference 0xA Attempts 7 3 Offset 16 - AuthID 02 - -PrivateKey AuthKey - Label "Authentication Key" - File pk1 - ID 45 - AuthID 01 # Requires CHV1 - KeyUsage sign - -PrivateKey SignKey - Label "Non-repudiation Key" - File pk2 - ID 46 - AuthID 02 # Requires CHV2 - KeyUsage NonRepudiation diff --git a/src/tools/pkcs15-gpk.c b/src/tools/pkcs15-gpk.c index cc6440f8..cda11bf1 100644 --- a/src/tools/pkcs15-gpk.c +++ b/src/tools/pkcs15-gpk.c @@ -97,11 +97,7 @@ gpk_update_pins(struct sc_card *card, struct pin_info *info) blk[3] = ~cks; } - /* FIXME: we shouldn't have to know about the offset shift - * here. Implement a gpk_update_binary function that just - * shifts the offset if required. - */ - r = sc_update_binary(card, info->file_offset/4, buffer, npins * 8, 0); + r = sc_update_binary(card, info->file_offset, buffer, npins * 8, 0); return r < 0; } @@ -139,13 +135,13 @@ gpk_store_pin(struct sc_profile *profile, struct sc_card *card, } /* Now create the file */ - if ((r = do_create_file(profile, pinfile)) < 0) + if ((r = sc_pkcs15init_create_file(profile, pinfile)) < 0) goto out; /* If messing with the PIN file requires any sort of * authentication, send it to the card now */ if ((r = sc_select_file(card, &pinfile->path, NULL)) < 0 - || (r = do_verify_authinfo(profile, pinfile, SC_AC_OP_UPDATE)) < 0) + || (r = sc_pkcs15init_authenticate(profile, pinfile, SC_AC_OP_UPDATE)) < 0) goto out; r = gpk_update_pins(card, info); @@ -158,16 +154,24 @@ static int gpk_lock_pinfile(struct sc_profile *profile, struct sc_card *card, struct sc_file *pinfile) { + struct sc_path path; struct sc_file *parent = NULL; int r; - /* If the UPDATE AC should be NEVER, set the AC now */ - if ((r = do_select_parent(profile, pinfile, &parent)) != 0 - || (r = do_verify_authinfo(profile, parent, SC_AC_OP_LOCK)) != 0) - goto out; - r = gpk_lock(card, pinfile, SC_AC_OP_UPDATE); -out: if (parent) - sc_file_free(parent); + /* Select the parent DF */ + path = pinfile->path; + if (path.len >= 2) + path.len -= 2; + if (path.len == 0) + sc_format_path("3F00", &path); + if ((r = sc_select_file(card, &path, &parent)) < 0) + return r; + + /* Present PINs etc as necessary */ + if (!(r = sc_pkcs15init_authenticate(profile, parent, SC_AC_OP_LOCK))) + r = gpk_lock(card, pinfile, SC_AC_OP_UPDATE); + + sc_file_free(parent); return r; } @@ -220,7 +224,7 @@ gpk_init_app(struct sc_profile *profile, struct sc_card *card) * in the application DF, create that file first */ /* Create the application DF */ - if (do_create_file(profile, profile->df_info.file)) + if (sc_pkcs15init_create_file(profile, profile->df_info.file)) return 1; /* Store CHV2 */ @@ -247,6 +251,82 @@ gpk_init_app(struct sc_profile *profile, struct sc_card *card) return 0; } +/* + * Allocate a file + */ +static int +gpk_allocate_file(struct sc_profile *profile, struct sc_card *card, + unsigned int type, unsigned int num, + struct sc_file **out) +{ + struct file_info *templ; + struct sc_file *file; + struct sc_path *p; + char name[64], *tag, *desc; + + desc = tag = NULL; + while (1) { + switch (type) { + case SC_PKCS15_TYPE_PRKEY_RSA: + desc = "RSA private key"; + tag = "private-key"; + break; + case SC_PKCS15_TYPE_PUBKEY_RSA: + desc = "RSA public key"; + tag = "public-key"; + break; +#ifdef SC_PKCS15_TYPE_PRKEY_DSA + case SC_PKCS15_TYPE_PRKEY_RSA: + desc = "RSA private key"; + tag = "data"; + break; + case SC_PKCS15_TYPE_PUBKEY_RSA: + desc = "RSA public key"; + tag = "data"; + break; +#endif + case SC_PKCS15_TYPE_CERT: + desc = "certificate"; + tag = "data"; + break; + case SC_PKCS15_TYPE_DATA_OBJECT: + desc = "data object"; + tag = "data"; + break; + } + if (tag) + break; + /* If this is a specific type such as + * SC_PKCS15_TYPE_CERT_FOOBAR, fall back to + * the generic class (SC_PKCS15_TYPE_CERT) + */ + if (!(type & ~SC_PKCS15_TYPE_CLASS_MASK)) { + error("File type not supported by card driver"); + return SC_ERROR_INVALID_ARGUMENTS; + } + type &= SC_PKCS15_TYPE_CLASS_MASK; + } + + snprintf(name, sizeof(name), "template-%s", tag); + if (!(templ = sc_profile_find_file(profile, name))) { + error("Profile doesn't define %s template (%s)\n", + desc, name); + return SC_ERROR_NOT_SUPPORTED; + } + + /* Now construct file from template */ + sc_file_dup(&file, templ->file); + file->id += num; + + p = &file->path; + *p = profile->df_info.file->path; + p->value[p->len++] = file->id >> 8; + p->value[p->len++] = file->id; + + *out = file; + return 0; +} + /* * GPK public/private key file handling is hideous. * 600 lines of coke sweat and tears... @@ -282,7 +362,7 @@ gpk_pkfile_create(struct sc_profile *profile, struct sc_card *card, r = sc_select_file(card, &file->path, &found); card->ctx->log_errors = 1; if (r == SC_ERROR_FILE_NOT_FOUND) { - r = do_create_file(profile, file); + r = sc_pkcs15init_create_file(profile, file); if (r >= 0) r = sc_select_file(card, &file->path, &found); } else { @@ -290,7 +370,7 @@ gpk_pkfile_create(struct sc_profile *profile, struct sc_card *card, } if (r >= 0) - r = do_verify_authinfo(profile, file, SC_AC_OP_UPDATE); + r = sc_pkcs15init_authenticate(profile, file, SC_AC_OP_UPDATE); if (found) sc_file_free(found); @@ -761,14 +841,14 @@ gpk_store_pk(struct sc_profile *profile, struct sc_card *card, */ static int gpk_store_rsa_key(struct sc_profile *profile, struct sc_card *card, - struct prkey_info *info, RSA *rsa) + struct sc_key_template *info, RSA *rsa) { struct pkdata data; int r; - if ((r = gpk_encode_rsa_key(rsa, &data, info->pkcs15.usage)) < 0) + if ((r = gpk_encode_rsa_key(rsa, &data, info->pkcs15.priv.usage)) < 0) return r; - return gpk_store_pk(profile, card, info->file->file, &data, info->key_acl); + return gpk_store_pk(profile, card, info->file, &data, info->key_acl); } /* @@ -776,14 +856,14 @@ gpk_store_rsa_key(struct sc_profile *profile, struct sc_card *card, */ static int gpk_store_dsa_key(struct sc_profile *profile, struct sc_card *card, - struct prkey_info *info, DSA *dsa) + struct sc_key_template *info, DSA *dsa) { struct pkdata data; int r; - if ((r = gpk_encode_dsa_key(dsa, &data, info->pkcs15.usage)) < 0) + if ((r = gpk_encode_dsa_key(dsa, &data, info->pkcs15.priv.usage)) < 0) return r; - return gpk_store_pk(profile, card, info->file->file, &data, info->key_acl); + return gpk_store_pk(profile, card, info->file, &data, info->key_acl); } #ifdef notdef @@ -810,6 +890,7 @@ bind_gpk_operations(struct pkcs15_init_operations *ops) { ops->erase_card = gpk_erase_card; ops->init_app = gpk_init_app; + ops->allocate_file = gpk_allocate_file; ops->store_rsa = gpk_store_rsa_key; ops->store_dsa = gpk_store_dsa_key; } diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index c32b0927..44b0c35f 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "opensc-pkcs15.h" #include "util.h" #include "profile.h" @@ -51,21 +52,41 @@ typedef int (*pkcs15_encoder)(struct sc_context *, /* Local functions */ static int connect(int); static void bind_operations(struct pkcs15_init_operations *, const char *); -static int pkcs15_init(struct sc_profile *); -static int pkcs15_generate_key(struct sc_profile *); -static int pkcs15_generate_key_soft(struct sc_profile *, - unsigned int, unsigned int); -static int pkcs15_store_key(struct sc_profile *, EVP_PKEY *); -static int pkcs15_store_private_key(struct sc_profile *, EVP_PKEY *, - struct sc_pkcs15_id *); -static int pkcs15_store_public_key(struct sc_profile *, EVP_PKEY *, - struct sc_pkcs15_id *); -static int pkcs15_write(struct sc_profile *, - const char *name, pkcs15_encoder, int); -static int pkcs15_write_df(struct sc_profile *, - struct sc_pkcs15_df *, unsigned int); +static int do_generate_key(struct sc_profile *, const char *); +static int do_store_private_key(struct sc_profile *profile); +static int do_store_public_key(struct sc_profile *profile); + +static int sc_pkcs15init_generate_key_soft(struct sc_pkcs15_card *, + struct sc_profile *, struct sc_pkcs15init_keyargs *); +struct sc_pkcs15_object * + sc_pkcs15init_find_key(struct sc_pkcs15_card *p15card, + unsigned int type, + struct sc_pkcs15_id *id); +int sc_pkcs15init_new_private_key(struct sc_profile *profile, + unsigned int type, + struct sc_pkcs15init_keyargs *keyargs, + struct sc_key_template *out); +int sc_pkcs15init_new_public_key(struct sc_profile *profile, + unsigned int type, + struct sc_pkcs15init_keyargs *keyargs, + struct sc_key_template *out); + +static int sc_pkcs15init_store_private_key(struct sc_pkcs15_card *, + struct sc_profile *, struct sc_pkcs15init_keyargs *); +static int sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, + struct sc_profile *profile, + struct sc_pkcs15init_keyargs *keyargs); +static int sc_pkcs15init_update_tokeninfo(struct sc_pkcs15_card *, + struct sc_profile *profile); +static int sc_pkcs15init_update_odf(struct sc_pkcs15_card *, + struct sc_profile *profile); +static int sc_pkcs15init_update_df(struct sc_pkcs15_card *, + struct sc_profile *profile, + unsigned int df_type); +static int do_select_parent(struct sc_profile *, struct sc_file *, + struct sc_file **); static int do_read_pins(struct sc_profile *); -static int do_set_pins(struct sc_profile *); +static int set_pins_from_args(struct sc_profile *); static int do_read_private_key(const char *, const char *, EVP_PKEY **); static int do_write_public_key(const char *, const char *, EVP_PKEY *); static void parse_commandline(int argc, char **argv); @@ -126,30 +147,35 @@ enum { ACTION_NONE = 0, ACTION_INIT, ACTION_GENERATE_KEY, - ACTION_STORE_KEY, + ACTION_STORE_PRIVKEY, + ACTION_STORE_PUBKEY, ACTION_STORE_CERT }; static struct sc_context * ctx = NULL; static struct sc_card * card = NULL; +static struct sc_pkcs15_card * p15card = NULL; static int opt_debug = 0, opt_quiet = 0, opt_action = 0, opt_erase = 0; -static char * opt_profile = 0; +static char * opt_driver = 0; +static char * opt_profile = "pkcs15"; static char * opt_keyfile = 0; static char * opt_format = 0; static char * opt_objectid = 0; +static char * opt_objectlabel = 0; static char * opt_pins[4]; static char * opt_passphrase = 0; static char * opt_newkey = 0; static char * opt_outkey = 0; static struct pkcs15_init_operations ops; +#include + int main(int argc, char **argv) { - struct sc_pkcs15_card *p15card; struct sc_profile profile; int opt_reader = 0; int r = 0; @@ -171,34 +197,35 @@ main(int argc, char **argv) print_usage_and_die("pkcs15-init"); } - /* When asked to init the card, read the profile first. - * This makes people writing new profiles happier because - * they don't have to wait for the card to come around */ - sc_profile_init(&profile); - if (sc_profile_load(&profile, opt_profile) - || sc_profile_finish(&profile)) - return 1; - - /* Assemble the PKCS15 structure */ - if (sc_profile_build_pkcs15(&profile)) - return 1; - - /* Associate all PINs given on the command line with the - * CHVs used by the profile */ - do_set_pins(&profile); - /* Connect to the card */ if (!connect(opt_reader)) return 1; /* Now bind the card specific operations */ - bind_operations(&ops, profile.driver); + bind_operations(&ops, opt_driver); + + /* Now load the profile */ + /* When asked to init the card, read the profile first. + * This makes people writing new profiles happier because + * they don't have to wait for the card to come around */ + sc_profile_init(&profile); + if (sc_profile_load(&profile, opt_profile) + || sc_profile_load(&profile, card->driver->short_name) + || sc_profile_finish(&profile)) + return 1; + + /* XXX lousy style */ + profile.ops = &ops; + + /* Associate all PINs given on the command line with the + * CHVs used by the profile */ + set_pins_from_args(&profile); if (opt_action == ACTION_INIT) { if (opt_erase) r = ops.erase_card(&profile, card); if (r >= 0) - r = pkcs15_init(&profile); + r = sc_pkcs15init_add_app(card, &profile); goto done; } @@ -218,10 +245,12 @@ main(int argc, char **argv) /* XXX: should compare card to profile here to make sure * we're not messing things up */ - if (opt_action == ACTION_STORE_KEY) - r = pkcs15_store_key(&profile, NULL); + if (opt_action == ACTION_STORE_PRIVKEY) + r = do_store_private_key(&profile); + else if (opt_action == ACTION_STORE_PUBKEY) + r = do_store_public_key(&profile); else if (opt_action == ACTION_GENERATE_KEY) - r = pkcs15_generate_key(&profile); + r = do_generate_key(&profile, opt_newkey); else fatal("Action not yet implemented\n"); @@ -292,17 +321,168 @@ connect(int reader) return 1; } +/* + * Store a private key + */ static int -pkcs15_init(struct sc_profile *pro) +do_store_private_key(struct sc_profile *profile) { - int i, j, r; + struct sc_pkcs15init_keyargs args; + int r; + + memset(&args, 0, sizeof(args)); + if (opt_objectid) + sc_pkcs15_format_id(opt_objectid, &args.id); + if (opt_objectlabel) + args.label = opt_objectlabel; + + r = do_read_private_key(opt_keyfile, opt_format, &args.pkey); + if (r) + return r; + + r = sc_pkcs15init_store_private_key(p15card, profile, &args); + if (r) + return r; + + /* XXX: store public key as well */ + return 0; +} + +/* + * Store a public key + */ +static int +do_store_public_key(struct sc_profile *profile) +{ + struct sc_pkcs15init_keyargs args; + + memset(&args, 0, sizeof(args)); + if (opt_objectid) + sc_pkcs15_format_id(opt_objectid, &args.id); + if (opt_objectlabel) + args.label = opt_objectlabel; + +#ifdef notyet + r = do_read_public_key(opt_keyfile, opt_format, &args.pkey); + if (r) + return r; +#endif + + return sc_pkcs15init_store_public_key(p15card, profile, &args); +} + +/* + * Generate a new private key + */ +static int +do_generate_key(struct sc_profile *profile, const char *spec) +{ + struct sc_pkcs15init_keyargs keyargs; + const char *reason; + int r; + + /* Parse the key spec given on the command line */ + memset(&keyargs, 0, sizeof(keyargs)); + if (!strncasecmp(spec, "rsa", 3)) { + keyargs.algorithm = SC_ALGORITHM_RSA; + spec += 3; + } else if (!strncasecmp(spec, "dsa", 3)) { + keyargs.algorithm = SC_ALGORITHM_DSA; + spec += 3; + } else { + reason = "algorithm not supported\n"; + goto failed; + } + + if (*spec == '/' || *spec == '-') + spec++; + if (*spec) { + keyargs.keybits = strtoul(spec, (char **) &spec, 10); + if (*spec) { + reason = "invalid bit number"; + goto failed; + } + } + + if (opt_objectid) + sc_pkcs15_format_id(opt_objectid, &keyargs.id); + + while (1) { + r = sc_pkcs15init_generate_key(p15card, profile, + &keyargs); + if (r != SC_ERROR_NOT_SUPPORTED || !keyargs.onboard_keygen) + break; + if (!opt_quiet) + printf("Warning: card doesn't support on-board " + "key generation; using software generation\n"); + keyargs.onboard_keygen = 0; + } + if (r != 0) + goto sc_failed; + + /* Store public key portion on card */ + r = sc_pkcs15init_store_public_key(p15card, profile, &keyargs); + + if (opt_outkey) { + if (!opt_quiet) + printf("Writing public key to %s\n", opt_outkey); + r = do_write_public_key(opt_outkey, opt_format, keyargs.pkey); + } + if (r) + goto sc_failed; + return 0; + +sc_failed: + reason = sc_strerror(r); +failed: error("Unable to generate %s key: %s\n", spec, reason); + return -1; +} + +/* + * Generic funcions go here. + * I would like to move these into a separate lib one day (soonishly). + */ +static int +sc_pkcs15init_build_aodf(struct sc_profile *profile) +{ + struct sc_pkcs15_card *p15card; + struct pin_info *pi; + int r; + + p15card = profile->p15_card; + + /* Loop over all PINs and make sure they're sane */ + for (pi = profile->pin_list; pi; pi = pi->next) { + r = sc_pkcs15_add_object(p15card, + &p15card->df[SC_PKCS15_AODF], + 0, &pi->pkcs15_obj); + if (r) { + error("Failed to add PIN to AODF: %s\n", + sc_strerror(r)); + return -1; + } + } + return 0; +} + +int +sc_pkcs15init_add_app(struct sc_card *card, struct sc_profile *profile) +{ + struct sc_pkcs15_card *p15card = profile->p15_card; + int r; + + p15card->card = card; /* Get all necessary PINs from user */ - if (do_read_pins(pro)) + if (do_read_pins(profile)) + return 1; + + /* Build the AODF */ + if (sc_pkcs15init_build_aodf(profile)) return 1; /* Create the application DF and store the PINs */ - if (ops.init_app(pro, card)) + if (ops.init_app(profile, card)) return 1; /* Store the PKCS15 information on the card @@ -314,27 +494,15 @@ pkcs15_init(struct sc_profile *pro) /* Create the file (what size?) */ r = ... /* Update DIR */ - r = sc_update_dir(pro->p15_card); + r = sc_update_dir(p15card); #else r = 0; #endif if (r >= 0) - r = pkcs15_write(pro, "PKCS15-TokenInfo", - sc_pkcs15_encode_tokeninfo, 0); + r = sc_pkcs15init_update_tokeninfo(p15card, profile); if (r >= 0) - r = pkcs15_write(pro, "PKCS15-ODF", sc_pkcs15_encode_odf, 0); - - /* XXX Note we need to fill in the modulus length of PrKEY - * objects at some point (is this info optional?). - * Now would be a good time. */ - - /* Encode all DFs */ - for (i = 0; r >= 0 && i < SC_PKCS15_DF_TYPE_COUNT; i++) { - struct sc_pkcs15_df *df = &pro->p15_card->df[i]; - - for (j = 0; r >= 0 && j < df->count; j++) - r = pkcs15_write_df(pro, df, j); - } + r = sc_pkcs15init_update_df(p15card, profile, + SC_PKCS15_AODF); if (r < 0) { fprintf(stderr, @@ -350,322 +518,478 @@ pkcs15_init(struct sc_profile *pro) /* * Generate a new private key */ -static int -pkcs15_generate_key(struct sc_profile *profile) +int +sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, + struct sc_profile *profile, + struct sc_pkcs15init_keyargs *keyargs) { - char *spec, *reason; - unsigned int algo, bits = 0; + if (keyargs->onboard_keygen) + return SC_ERROR_NOT_SUPPORTED; - /* Parse the key spec given on the command line */ - spec = opt_newkey; - if (!strncasecmp(spec, "rsa", 3)) { - algo = SC_ALGORITHM_RSA; - spec += 3; - } else if (!strncasecmp(spec, "dsa", 3)) { - algo = SC_ALGORITHM_DSA; - spec += 3; - } else { - reason = "algorithm not supported\n"; - goto failed; - } - - if (*spec == '/' || *spec == '-') - spec++; - if (*spec) { - bits = strtoul(spec, &spec, 10); - if (*spec) { - reason = "invalid bit number"; - goto failed; - } - } - - /* XXX: support on-card key generation */ /* Fall back to software generated keys */ - return pkcs15_generate_key_soft(profile, algo, bits); - -failed: error("Unable to generate %s key: %s\n", opt_newkey, reason); - return -1; + return sc_pkcs15init_generate_key_soft(p15card, profile, keyargs); } static int -pkcs15_generate_key_soft(struct sc_profile *profile, - unsigned int algo, unsigned int bits) +sc_pkcs15init_generate_key_soft(struct sc_pkcs15_card *p15card, + struct sc_profile *profile, + struct sc_pkcs15init_keyargs *keyargs) { - EVP_PKEY *pkey; - int r; - - if (!opt_quiet) - printf("Warning: card doesn't support on-board " - "key generation; using software generation\n"); + int r; ossl_seed_random(); - pkey = EVP_PKEY_new(); - if (algo == SC_ALGORITHM_RSA) { - RSA *rsa; - BIO *err; + keyargs->pkey = EVP_PKEY_new(); + switch (keyargs->algorithm) { + case SC_ALGORITHM_RSA: { + RSA *rsa; + BIO *err; - err = BIO_new(BIO_s_mem()); - rsa = RSA_generate_key(bits, 0x10001, NULL, err); - BIO_free(err); - if (rsa == 0) { - error("RSA key generation error"); - return -1; + err = BIO_new(BIO_s_mem()); + rsa = RSA_generate_key(keyargs->keybits, + 0x10001, NULL, err); + BIO_free(err); + if (rsa == 0) { + error("RSA key generation error"); + return -1; + } + EVP_PKEY_assign_RSA(keyargs->pkey, rsa); + break; } - EVP_PKEY_assign_RSA(pkey, rsa); - } else if (algo == SC_ALGORITHM_DSA) { - DSA *dsa; - int r = 0; + case SC_ALGORITHM_DSA: { + DSA *dsa; + int r = 0; - dsa = DSA_generate_parameters(bits, NULL, 0, NULL, - NULL, NULL, NULL); - if (dsa) - r = DSA_generate_key(dsa); - if (r == 0 || dsa == 0) { - error("DSA key generation error"); - return -1; + dsa = DSA_generate_parameters(keyargs->keybits, + NULL, 0, NULL, + NULL, NULL, NULL); + if (dsa) + r = DSA_generate_key(dsa); + if (r == 0 || dsa == 0) { + error("DSA key generation error"); + return -1; + } + EVP_PKEY_assign_DSA(keyargs->pkey, dsa); + break; } - EVP_PKEY_assign_DSA(pkey, dsa); + default: + return SC_ERROR_NOT_SUPPORTED; } - r = pkcs15_store_key(profile, pkey); + r = sc_pkcs15init_store_private_key(p15card, profile, keyargs); if (r < 0) return r; - if (opt_outkey) { - if (!opt_quiet) - printf("Writing public key to %s\n", opt_outkey); - r = do_write_public_key(opt_outkey, opt_format, pkey); + return 0; +} + +/* + * See if there's a PrKDF or PuKDF entry matching this keyinfo. + * If not, allocate a file and create a corresponding DF entry. + */ +static int +sc_pkcs15init_setup_key(struct sc_pkcs15_card *p15card, + struct sc_profile *profile, + struct sc_pkcs15init_keyargs *keyargs, int is_private, + struct sc_key_template *out) +{ + struct sc_pkcs15_object *found; + int r, type; + + memset(out, 0, sizeof(*out)); + switch (keyargs->algorithm | (is_private << 16)) { + case SC_ALGORITHM_RSA | 0x10000: + type = SC_PKCS15_TYPE_PRKEY_RSA; break; +#ifdef SC_PKCS15_TYPE_PRKEY_DSA + case SC_ALGORITHM_DSA | 0x10000: + type = SC_PKCS15_TYPE_PRKEY_DSA; break; +#endif + case SC_ALGORITHM_RSA: + type = SC_PKCS15_TYPE_PUBKEY_RSA; break; +#ifdef SC_PKCS15_TYPE_PRKEY_DSA + case SC_ALGORITHM_DSA: + type = SC_PKCS15_TYPE_PUBKEY_DSA; break; +#endif + default: + return SC_ERROR_NOT_SUPPORTED; } + + + /* If a key ID has been given, try to locate the key. */ + found = sc_pkcs15init_find_key(p15card, type, &keyargs->id); + + if (found) { + /* XXX: TBD set up out */ + r = SC_ERROR_NOT_SUPPORTED; /* we don't support updates yet */ + } else { + /* If there's no such key on the card yet, allocate an ID, + * and a file. + */ + switch (type & SC_PKCS15_TYPE_CLASS_MASK) { + case SC_PKCS15_TYPE_PRKEY: + r = sc_pkcs15init_new_private_key(profile, + type, keyargs, out); + break; + case SC_PKCS15_TYPE_PUBKEY: + r = sc_pkcs15init_new_public_key(profile, + type, keyargs, out); + break; + default: + r = SC_ERROR_NOT_SUPPORTED; + } + + } + return r; } + +int +sc_pkcs15init_new_private_key(struct sc_profile *profile, + unsigned int type, + struct sc_pkcs15init_keyargs *keyargs, + struct sc_key_template *out) +{ + struct sc_key_template *template; + struct sc_pkcs15_object *obj; + int index, r; + + index = sc_pkcs15_get_objects(p15card, type, NULL, 0); + + if (keyargs->template_name) + template = sc_profile_find_private_key(profile, + keyargs->template_name); + else + template = profile->prkey_list; + if (template == NULL) + return SC_ERROR_OBJECT_NOT_FOUND; + + *out = *template; + + if (keyargs->label) + strcpy(out->pkcs15_obj.label, keyargs->label); + else if (!out->pkcs15_obj.label[0]) + strcpy(out->pkcs15_obj.label, "Private Key"); + + if (keyargs->id.len) + out->pkcs15.priv.id = keyargs->id; + else { + struct sc_pkcs15_id *ip = &out->pkcs15.priv.id; + + if (!ip->len) + sc_pkcs15_format_id("45", ip); + ip->value[ip->len-1] += index; + } + + /* Find the PIN used to protect this key */ + if (out->pkcs15_obj.auth_id.len) { + r = sc_pkcs15_find_pin_by_auth_id(p15card, + &out->pkcs15_obj.auth_id, &obj); + if (r < 0) { + /* error("No PIN matching auth_id of private key"); */ + return SC_ERROR_OBJECT_NOT_FOUND; + } + out->key_acl = calloc(1, sizeof(struct sc_acl_entry)); + out->key_acl->method = SC_AC_CHV; + out->key_acl->key_ref = + ((struct sc_pkcs15_pin_info *) obj->data)->reference; + } else { + /* XXX flag this as error/warning? */ + } + + /* Sanity checks */ + if (!out->pkcs15.priv.id.len) { + /* error("No ID set for private key object"); */ + return SC_ERROR_INVALID_ARGUMENTS; + } + if (!out->pkcs15.priv.usage) { + /* error("No keyUsage defined for private key"); */ + return SC_ERROR_INVALID_ARGUMENTS; + } + + /* Now allocate a file */ + r = profile->ops->allocate_file(profile, + p15card->card, type, index, + &out->file); + if (r < 0) { + /* error("Unable to allocate private key file"); */ + return r; + } + out->pkcs15.priv.path = out->file->path; + out->pkcs15_obj.data = &out->pkcs15; + out->pkcs15_obj.type = type; + + r = sc_pkcs15_add_object(p15card, &p15card->df[SC_PKCS15_PRKDF], + 0, &out->pkcs15_obj); + if (r) { + /* error("failed to add object to PrKDF"); */ + return r; + } + + /* Return the ID we selected, for reference + * (in case the caller wants to know the ID, so he + * can store public key/certificate with a corresponding + * ID. */ + keyargs->id = out->pkcs15.priv.id; + return 0; +} + +int +sc_pkcs15init_new_public_key(struct sc_profile *profile, + unsigned int type, + struct sc_pkcs15init_keyargs *keyargs, + struct sc_key_template *out) +{ + struct sc_key_template *template; + int index, r; + + index = sc_pkcs15_get_objects(p15card, type, NULL, 0); + + if (keyargs->template_name) + template = sc_profile_find_public_key(profile, + keyargs->template_name); + else + template = profile->pubkey_list; + if (template == NULL) + return SC_ERROR_OBJECT_NOT_FOUND; + + *out = *template; + + if (keyargs->label) + strcpy(out->pkcs15_obj.label, keyargs->label); + else if (!out->pkcs15_obj.label[0]) + strcpy(out->pkcs15_obj.label, "Public Key"); + + if (keyargs->id.len) + out->pkcs15.pub.id = keyargs->id; + else { + struct sc_pkcs15_id *ip = &out->pkcs15.pub.id; + + if (!ip->len) + sc_pkcs15_format_id("45", ip); + ip->value[ip->len-1] += index; + } + + /* Sanity checks */ + if (!out->pkcs15.pub.id.len) { + /* error("No ID set for public key object"); */ + return SC_ERROR_INVALID_ARGUMENTS; + } + if (!out->pkcs15.pub.usage) { + /* error("No keyUsage defined for public key"); */ + return SC_ERROR_INVALID_ARGUMENTS; + } + + /* Now allocate a file */ + r = profile->ops->allocate_file(profile, + p15card->card, type, index, + &out->file); + if (r < 0) { + /* error("Unable to allocate public key file"); */ + return r; + } + out->pkcs15.pub.path = out->file->path; + out->pkcs15_obj.data = &out->pkcs15; + out->pkcs15_obj.type = type; + + r = sc_pkcs15_add_object(p15card, &p15card->df[SC_PKCS15_PUKDF], + 0, &out->pkcs15_obj); + if (r) { + /* error("failed to add object to PuKDF"); */ + return r; + } + + /* Return the ID we selected, for reference */ + keyargs->id = out->pkcs15.pub.id; + return 0; +} + +/* + * Find a key given its ID + */ +static int +compare_id(struct sc_pkcs15_object *obj, void *arg) +{ + struct sc_pkcs15_id *ida, *idb = (struct sc_pkcs15_id *) arg; + + switch (obj->type) { + case SC_PKCS15_TYPE_PRKEY_RSA: + ida = &((struct sc_pkcs15_prkey_info *) obj->data)->id; + break; + case SC_PKCS15_TYPE_PUBKEY_RSA: + ida = &((struct sc_pkcs15_pubkey_info *) obj->data)->id; + break; + default: + return 0; + } + return sc_pkcs15_compare_id(ida, idb); +} + +struct sc_pkcs15_object * +sc_pkcs15init_find_key(struct sc_pkcs15_card *p15card, + unsigned int type, + struct sc_pkcs15_id *id) +{ + struct sc_pkcs15_object *ret = NULL; + + if (sc_pkcs15_get_objects_cond(p15card, type, + compare_id, id, &ret, 1) <= 0) + return NULL; + return ret; +} -static int -pkcs15_store_key(struct sc_profile *profile, EVP_PKEY *pkey) +/* + * Store private key + */ +int +sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card, + struct sc_profile *profile, + struct sc_pkcs15init_keyargs *keyargs) { - struct sc_pkcs15_id id; - - if (pkcs15_store_private_key(profile, pkey, &id) < 0) - return -1; - /* XXX store public key */ - return pkcs15_store_public_key(profile, pkey, &id); -} - -static int -pkcs15_store_private_key(struct sc_profile *profile, EVP_PKEY *pkey, - struct sc_pkcs15_id *id) -{ - struct sc_pkcs15_df *df; - struct prkey_info *pinfo; - unsigned int j; + struct sc_key_template info; int r; - if (opt_objectid == NULL) - fatal("No key ID specified; please use --id"); + r = sc_pkcs15init_setup_key(p15card, profile, keyargs, 1, &info); + if (r < 0) + return r; - /* XXX: support special ID "new" to assign a new ID and - * create PK file info from template */ - - /* Find the private key file matching the given ID */ - sc_pkcs15_format_id(opt_objectid, id); - for (pinfo = profile->prkey_list; pinfo; pinfo = pinfo->next) { - if (!strcasecmp(pinfo->ident, opt_objectid) - || sc_pkcs15_compare_id(id, &pinfo->pkcs15.id) == 1) - break; - } - if (pinfo == NULL) { - error("Unable to find private key file (id=%s)\n", - opt_objectid); - return -1; - } - - if (pkey == NULL) - do_read_private_key(opt_keyfile, opt_format, &pkey); + /* XXX: If the card doesn't have support for native keys of + * this type, store this key non-natively */ r = SC_ERROR_NOT_SUPPORTED; - switch (pkey->type) { + switch (keyargs->pkey->type) { case EVP_PKEY_RSA: if (ops.store_rsa) { - RSA *rsa = EVP_PKEY_get1_RSA(pkey); + RSA *rsa = EVP_PKEY_get1_RSA(keyargs->pkey); - r = ops.store_rsa(profile, card, pinfo, rsa); - pinfo->pkcs15.modulus_length = RSA_size(rsa) * 8; + r = ops.store_rsa(profile, card, &info, rsa); + info.pkcs15.pub.modulus_length = RSA_size(rsa) * 8; } break; case EVP_PKEY_DSA: if (ops.store_dsa) { - DSA *dsa = EVP_PKEY_get1_DSA(pkey); + DSA *dsa = EVP_PKEY_get1_DSA(keyargs->pkey); - r = ops.store_dsa(profile, card, pinfo, dsa); - pinfo->pkcs15.modulus_length = DSA_size(dsa) * 8; + r = ops.store_dsa(profile, card, &info, dsa); + info.pkcs15.pub.modulus_length = DSA_size(dsa) * 8; } break; } - if (r < 0) { - error("Failed to store private key: %s", - sc_strerror(r)); + if (r < 0) return r; - } /* Now update the PrKDF */ - df = &profile->p15_card->df[SC_PKCS15_PRKDF]; - for (j = 0; r >= 0 && j < df->count; j++) - r = pkcs15_write_df(profile, df, j); - - if (r >= 0) - printf("Successfully stored private key\n"); - return r; + return sc_pkcs15init_update_df(p15card, profile, SC_PKCS15_PRKDF); } static int -pkcs15_store_public_key(struct sc_profile *profile, EVP_PKEY *pkey, - struct sc_pkcs15_id *id) +sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, + struct sc_profile *profile, + struct sc_pkcs15init_keyargs *keyargs) { - struct pubkey_info *pinfo; - struct sc_pkcs15_df *df; + struct sc_key_template info; unsigned char *data, *p; size_t size; RSA *rsa; - int r, j; + int r; - /* Find the private key file matching the given ID */ - for (pinfo = profile->pubkey_list; pinfo; pinfo = pinfo->next) { - if (!strcasecmp(pinfo->ident, opt_objectid) - || sc_pkcs15_compare_id(id, &pinfo->pkcs15.id) == 1) - break; - } - if (pinfo == NULL) { - error("Unable to find public key file\n"); - return -1; - } + r = sc_pkcs15init_setup_key(p15card, profile, keyargs, 0, &info); + if (r < 0) + return r; -#ifdef notyet - if (pkey == NULL) - do_read_public_key(opt_keyfile, opt_format, &pkey); -#endif - - r = SC_ERROR_NOT_SUPPORTED; - switch (pkey->type) { + switch (keyargs->pkey->type) { case EVP_PKEY_RSA: - rsa = EVP_PKEY_get1_RSA(pkey); + rsa = EVP_PKEY_get1_RSA(keyargs->pkey); size = i2d_RSAPublicKey(rsa, NULL); data = p = malloc(size); i2d_RSAPublicKey(rsa, &p); break; - } - if (r < 0) { - error("Failed to store public key: %s", sc_strerror(r)); - return r; + default: + return SC_ERROR_NOT_SUPPORTED; } - r = do_create_and_update_file(profile, pinfo->file->file, data, size); + r = sc_pkcs15init_update_file(profile, info.file, data, size); free(data); - /* Now update the PrKDF */ - df = &profile->p15_card->df[SC_PKCS15_PUKDF]; - for (j = 0; r >= 0 && j < df->count; j++) - r = pkcs15_write_df(profile, df, j); - - if (r >= 0) - printf("Successfully stored public key\n"); - return r; + if (r < 0) + return r; + + /* Now update the PuKDF */ + return sc_pkcs15init_update_df(p15card, profile, SC_PKCS15_PUKDF); } static int -pkcs15_write(struct sc_profile *pro, const char *name, - pkcs15_encoder encode, int required) +sc_pkcs15init_update_tokeninfo(struct sc_pkcs15_card *p15card, + struct sc_profile *profile) { - struct sc_pkcs15_card *p15card = pro->p15_card; - struct file_info *info; - struct sc_file *file; + struct sc_context *ctx = p15card->card->ctx; u8 *buf = NULL; - size_t bufsize; + size_t size; int r; - info = sc_profile_find_file(pro, name); - if (info == NULL) { - if (required) - fatal("No %s file defined; abort.", name); - fprintf(stderr, "No %s file defined; not written\n", name); - return 0; - } - file = info->file; - - printf("Creating %s\n", name); - r = encode(card->ctx, p15card, &buf, &bufsize); + r = sc_pkcs15_encode_tokeninfo(ctx, p15card, &buf, &size); if (r >= 0) - r = do_create_and_update_file(pro, file, buf, bufsize); - if (r < 0) { - fprintf(stderr, - "Error creating %s: %s\n", name, sc_strerror(r)); - } - + r = sc_pkcs15init_update_file(profile, + p15card->file_tokeninfo, buf, size); if (buf) free(buf); return r; } static int -pkcs15_write_df(struct sc_profile *pro, struct sc_pkcs15_df *df, - unsigned int fileno) +sc_pkcs15init_update_odf(struct sc_pkcs15_card *p15card, + struct sc_profile *profile) { - struct sc_file *file = df->file[fileno]; - struct file_info *info; - const char *ident; - u8 *buf; - size_t bufsize; + struct sc_context *ctx = p15card->card->ctx; + u8 *buf = NULL; + size_t size; int r; - info = sc_profile_file_info(pro, file); - ident = info? info->ident : "unknown PKCS15 xDF"; - - printf("Creating %s\n", ident); - r = sc_pkcs15_encode_df(card->ctx, df, fileno, &buf, &bufsize); - if (r < 0) - goto out; - if (buf == 0) { - fprintf(stderr, - "Profile doesn't define %s objects, skipped\n", - ident); - return 0; - } - - r = do_create_and_update_file(pro, df->file[fileno], buf, bufsize); - free(buf); - -out: if (r < 0) { - fprintf(stderr, "Error creating %s: %s\n", - info? info->ident : "unknown PKCS15 xDF", - sc_strerror(r)); - } + r = sc_pkcs15_encode_odf(ctx, p15card, &buf, &size); + if (r >= 0) + r = sc_pkcs15init_update_file(profile, + p15card->file_odf, buf, size); + if (buf) + free(buf); return r; } -/* - * Find PIN info given the "name" or the reference - */ -static struct pin_info * -do_get_pin_by_name(struct sc_profile *pro, const char *name, int warn) +static int +sc_pkcs15init_update_df(struct sc_pkcs15_card *p15card, + struct sc_profile *profile, + unsigned int df_type) { - struct pin_info *info; + struct sc_pkcs15_df *df; + struct sc_file *file; + u8 *buf = NULL; + size_t bufsize; + unsigned int j; + int r = 0; - info = sc_profile_find_pin(pro, name); - if (info == NULL && warn) - error("No PIN info for %s", name); - return info; -} - -static struct pin_info * -do_get_pin_by_reference(struct sc_profile *pro, unsigned int reference) -{ - struct pin_info *info; - - for (info = pro->pin_list; info; info = info->next) { - if (info->pkcs15.reference == reference) - return info; + df = &p15card->df[df_type]; + if (df->count == 0) { + file = profile->df[df_type]; + if (file == NULL) { + /* error("Profile doesn't define a DF file %u", + df_type); */ + return SC_ERROR_NOT_SUPPORTED; + } + df->file[df->count++] = file; + if ((r = sc_pkcs15init_update_odf(p15card, profile)) < 0) + return r; } - return NULL; + + for (j = 0; r >= 0 && j < df->count; j++) { + r = sc_pkcs15_encode_df(card->ctx, df, j, &buf, &bufsize); + if (r >= 0) { + r = sc_pkcs15init_update_file(profile, + df->file[j], + buf, bufsize); + free(buf); + } + } + + return r; } /* @@ -673,14 +997,14 @@ do_get_pin_by_reference(struct sc_profile *pro, unsigned int reference) * CHVs used by the profile */ static int -do_set_pins(struct sc_profile *pro) +set_pins_from_args(struct sc_profile *pro) { static char *types[2] = { "CHV1", "CHV2" }; struct pin_info *info; int n, i; for (n = 0; n < 2; n++) { - if (!(info = do_get_pin_by_name(pro, types[n], 0))) + if (!(info = sc_profile_find_pin(pro, types[n]))) continue; for (i = 0; i < 2; i++) @@ -699,7 +1023,14 @@ read_one_pin(struct pin_info *info, unsigned int n) char prompt[64], *pass; int passlen; - sprintf(prompt, "Please enter %s for %s:", names[n], info->ident); + if (info->pkcs15_obj.label[0]) { + sprintf(prompt, "Please enter %s for %s (%s):", + names[n], info->ident, + info->pkcs15_obj.label); + } else { + sprintf(prompt, "Please enter %s for %s:", + names[n], info->ident); + } while (info->secret[n] == NULL) { pass = getpass(prompt); @@ -734,7 +1065,7 @@ do_read_pins(struct sc_profile *pro) struct sc_file *file; int i, npins = 2; - if (!(info = do_get_pin_by_name(pro, types[n], 0))) + if (!(info = sc_profile_find_pin(pro, types[n]))) continue; /* If the PIN file already exists, read just the PIN */ @@ -788,21 +1119,33 @@ do_verify_pin(struct sc_profile *pro, unsigned int type, unsigned int reference) return 0; } - info = NULL; - if (type == SC_AC_CHV) - info = do_get_pin_by_reference(pro, reference); - if (!info || !(pin = info->secret[0])) { - if ((r = read_one_pin(info, 0)) < 0) - return r; - pin = info->secret[0]; - } + if (type != SC_AC_CHV) + goto no_secret; + for (info = pro->pin_list; info; info = info->next) { + if (info->pkcs15.reference == reference) + break; + } + if (info == NULL) + goto no_secret; + + if (!info->secret[0] && (r = read_one_pin(info, 0)) < 0) + return r; + + pin = info->secret[0]; return sc_verify(card, SC_AC_CHV, reference, (u8 *) pin, strlen(pin), NULL); + +no_secret: + /* No secret found that we could present. + * XXX: Should we flag an error here, or let the + * operation proceed and then fail? */ + return 0; } int -do_verify_authinfo(struct sc_profile *pro, struct sc_file *file, int op) +sc_pkcs15init_authenticate(struct sc_profile *pro, + struct sc_file *file, int op) { const struct sc_acl_entry *acl; int r = 0; @@ -836,14 +1179,14 @@ do_select_parent(struct sc_profile *pro, struct sc_file *file, } int -do_create_file(struct sc_profile *pro, struct sc_file *file) +sc_pkcs15init_create_file(struct sc_profile *pro, struct sc_file *file) { struct sc_file *parent = NULL; int r; /* Select parent DF and verify PINs/key as necessary */ if ((r = do_select_parent(pro, file, &parent)) < 0 - || (r = do_verify_authinfo(pro, parent, SC_AC_OP_CREATE)) < 0) + || (r = sc_pkcs15init_authenticate(pro, parent, SC_AC_OP_CREATE)) < 0) goto out; r = sc_create_file(card, file); @@ -854,24 +1197,27 @@ out: if (parent) } int -do_create_and_update_file(struct sc_profile *pro, struct sc_file *file, - void *data, unsigned int datalen) +sc_pkcs15init_update_file(struct sc_profile *profile, + struct sc_file *file, void *data, unsigned int datalen) { - struct sc_file copy = *file; int r; - copy.size += datalen; - file = © + if ((r = sc_select_file(card, &file->path, NULL)) < 0) { + /* Create file if it doesn't exist */ + if (file->size < datalen) + file->size = datalen; + if (r != SC_ERROR_FILE_NOT_FOUND + || (r = sc_pkcs15init_create_file(profile, file)) < 0 + || (r = sc_select_file(card, &file->path, NULL)) < 0) + return r; + } - if ((r = do_create_file(pro, file)) < 0) - return r; + /* Present authentication info needed */ + r = sc_pkcs15init_authenticate(profile, file, SC_AC_OP_UPDATE); + if (r >= 0) + r = sc_update_binary(card, 0, data, datalen, 0); - /* Select file and present any authentication info needed */ - if ((r = sc_select_file(card, &file->path, NULL)) < 0 - || (r = do_verify_authinfo(pro, file, SC_AC_OP_UPDATE)) < 0) - return r; - - return sc_update_binary(card, 0, data, datalen, 0); + return r; } /* @@ -979,7 +1325,7 @@ handle_option(int c) opt_newkey = optarg; break; case 'S': - opt_action = ACTION_STORE_KEY; + opt_action = ACTION_STORE_PRIVKEY; opt_keyfile = optarg; break; case 'd': diff --git a/src/tools/pkcs15-init.h b/src/tools/pkcs15-init.h index d346de69..dfcc70e4 100644 --- a/src/tools/pkcs15-init.h +++ b/src/tools/pkcs15-init.h @@ -7,23 +7,44 @@ #ifndef PKCS15_INIT_H #define PKCS15_INIT_H +#include #include "profile.h" struct pkcs15_init_operations { int (*erase_card)(struct sc_profile *, struct sc_card *); int (*init_app)(struct sc_profile *, struct sc_card *); + int (*allocate_file)(struct sc_profile *, struct sc_card *, + unsigned int, unsigned int, struct sc_file **out); int (*store_rsa)(struct sc_profile *, struct sc_card *, - struct prkey_info *, RSA *); + struct sc_key_template *, RSA *); int (*store_dsa)(struct sc_profile *, struct sc_card *, - struct prkey_info *, DSA *); + struct sc_key_template *, DSA *); }; -extern int do_create_file(struct sc_profile *, struct sc_file *); -extern int do_create_and_update_file(struct sc_profile *, +struct sc_pkcs15init_keyargs { + struct sc_pkcs15_id id; + const char * label; + const char * template_name; + + /* For key generation */ + unsigned char onboard_keygen; + unsigned int algorithm; + unsigned int keybits; + + EVP_PKEY * pkey; +}; + +extern int sc_pkcs15init_add_app(struct sc_card *, + struct sc_profile *); +extern int sc_pkcs15init_generate_key(struct sc_pkcs15_card *, + struct sc_profile *, + struct sc_pkcs15init_keyargs *); +extern int sc_pkcs15init_create_file(struct sc_profile *, + struct sc_file *); +extern int sc_pkcs15init_update_file(struct sc_profile *, struct sc_file *, void *, unsigned int); -extern int do_select_parent(struct sc_profile *, struct sc_file *, - struct sc_file **); -extern int do_verify_authinfo(struct sc_profile *, struct sc_file *, int); +extern int sc_pkcs15init_authenticate(struct sc_profile *, + struct sc_file *, int); /* Card specific stuff */ extern void bind_gpk_operations(struct pkcs15_init_operations *); diff --git a/src/tools/pkcs15-miocos.c b/src/tools/pkcs15-miocos.c index 6bbb4163..1fcb8a24 100644 --- a/src/tools/pkcs15-miocos.c +++ b/src/tools/pkcs15-miocos.c @@ -82,7 +82,8 @@ static int miocos_init_app(struct sc_profile *profile, struct sc_card *card) */ static int miocos_store_rsa_key(struct sc_profile *profile, struct sc_card *card, - struct prkey_info *info, RSA *rsa) + struct sc_key_template *info, + RSA *rsa) { return 0; } diff --git a/src/tools/pkcs15.profile b/src/tools/pkcs15.profile new file mode 100644 index 00000000..d8fcb36c --- /dev/null +++ b/src/tools/pkcs15.profile @@ -0,0 +1,76 @@ +# +# PKCS15 profile, generic information. +# This profile is loaded before any card specific profile. +# + +# This is the DIR file +EF PKCS15-DIR + Path 3F002F00 + Size 128 + ACL *=NONE + +# This is the application DF +DF + Path 3F005015 + AID A0:00:00:00:63:50:4B:43:53:2D:31:35 + ACL *=NONE + +EF PKCS15-ODF + FileID 5031 + Size 256 + ACL *=NONE + +EF PKCS15-TokenInfo + FileID 5032 + ACL *=NONE + +EF PKCS15-AODF + FileID 4401 + Size 256 + ACL *=NEVER READ=NONE UPDATE=CHV2 + +EF PKCS15-PrKDF + FileID 4402 + Size 512 + ACL *=NEVER READ=NONE UPDATE=CHV2 + +EF PKCS15-PuKDF + FileID 4403 + Size 512 + ACL *=NEVER READ=NONE UPDATE=CHV2 + +EF PKCS15-CDF + FileID 4404 + Size 512 + ACL *=NEVER READ=NONE UPDATE=CHV2 + +# Generic PIN information +PIN CHV1 + Label "Authentication PIN" + AuthID 01 + +PIN CHV2 + Label "Non-repudiation PIN" + AuthID 02 + +PrivateKey AuthKey + Label "Authentication Key" + ID 45 + AuthID 01 # Requires CHV1 + KeyUsage sign + +PrivateKey SignKey + Label "Non-repudiation Key" + ID 46 + AuthID 02 # Requires CHV2 + KeyUsage NonRepudiation + +PublicKey AuthKey + Label "Authentication Key" + ID 45 + KeyUsage sign + +PublicKey SignKey + Label "Non-repudiation Key" + ID 46 + KeyUsage NonRepudiation diff --git a/src/tools/profile.c b/src/tools/profile.c index 5f238ef7..707c6cf1 100644 --- a/src/tools/profile.c +++ b/src/tools/profile.c @@ -27,6 +27,10 @@ #include "util.h" #include "profile.h" +#define DEF_PRKEY_RSA_ACCESS 0x1D +#define DEF_PRKEY_DSA_ACCESS 0x12 +#define DEF_PUBKEY_ACCESS 0x12 + struct command { const char * name; int section; @@ -42,17 +46,18 @@ enum { PARSE_PRKEY, PARSE_PUBKEY }; + static struct parser_info { const char * filename; unsigned int lineno; struct sc_profile * profile; int section; - struct file_info * cur_file; - struct pin_info * cur_pin; - struct prkey_info * cur_prkey; - struct pubkey_info * cur_pubkey; } parser; +static struct file_info * cur_file; +static struct pin_info * cur_pin; +static struct sc_key_template * cur_key; + struct map { const char * name; unsigned int val; @@ -147,6 +152,7 @@ static struct map keyAccessFlags[] = { { 0, 0 } }; +static const char *sc_profile_locate(const char *); static int process(int, char **); static char * next_word(char **p); static int get_authid(const char *, unsigned int *, unsigned int *); @@ -207,8 +213,8 @@ sc_profile_init(struct sc_profile *pro) } /* Assume card does RSA natively, but no DSA */ - pro->rsa_access_flags = 0x1D; - pro->dsa_access_flags = 0x12; + pro->rsa_access_flags = DEF_PRKEY_RSA_ACCESS; + pro->dsa_access_flags = DEF_PRKEY_DSA_ACCESS; pro->pin_encoding = 0x01; pro->pin_minlen = 4; pro->pin_maxlen = 8; @@ -221,6 +227,8 @@ sc_profile_load(struct sc_profile *pro, const char *filename) int res = 0; FILE *fp; + if (!(filename = sc_profile_locate(filename))) + return 1; if ((fp = fopen(filename, "r")) == NULL) { perror(filename); exit(1); @@ -249,6 +257,40 @@ sc_profile_load(struct sc_profile *pro, const char *filename) return res; } +static const char * +sc_profile_locate(const char *name) +{ + static char path[1024]; + + /* Unchanged name? */ + if (access(name, R_OK) == 0) + return name; + + /* Name with suffix tagged onto it? */ + snprintf(path, sizeof(path), "%s.%s", name, SC_PKCS15_PROFILE_SUFFIX); + if (access(path, R_OK) == 0) + return path; + + /* If it's got slashes, don't mess with it any further */ + if (strchr(path, '/')) + return path; + + /* Try directory */ + snprintf(path, sizeof(path), "%s/%s", + SC_PKCS15_PROFILE_DIRECTORY, name); + if (access(path, R_OK) == 0) + return path; + + snprintf(path, sizeof(path), "%s/%s.%s", + SC_PKCS15_PROFILE_DIRECTORY, name, + SC_PKCS15_PROFILE_SUFFIX); + if (access(path, R_OK) == 0) + return path; + + error("profile \"%s\" not found\n", name); + return NULL; +} + /* * Fix up a file's ACL references */ @@ -314,7 +356,6 @@ sc_profile_finish(struct sc_profile *pro) { struct file_info *fi; struct pin_info *pi; - struct prkey_info *pk; int res = 0; /* Loop over all PINs and make sure they're sane */ @@ -337,55 +378,17 @@ sc_profile_finish(struct sc_profile *pro) fix_file_acls(pro, pro->mf_info.file); fix_file_acls(pro, pro->df_info.file); - /* Make sure all private keys are sane */ - for (pk = pro->prkey_list; pk; pk = pk->next) { - struct sc_pkcs15_id *id; - - if (!pk->file) { - error("No File given for private key %s", pk->ident); - res = 1; - } - if (!pk->pkcs15_obj.auth_id.len) { - error("No auth_id set for private key %s", pk->ident); - res = 1; - } - if (!pk->pkcs15.id.len) { - error("No key ID set for private key %s", pk->ident); - res = 1; - } - if (!pk->pkcs15.usage) { - error("No keyUsage specified for private key %s", - pk->ident); - res = 1; - } - pk->pkcs15.path = pk->file->file->path; - - /* Set up the key ACL */ - id = &pk->pkcs15_obj.auth_id; - for (pi = pro->pin_list; pi; pi = pi->next) { - if (sc_pkcs15_compare_id(&pi->pkcs15.auth_id, id) == 1) - break; - } - if (pi == NULL) { - error("Invalid or no AuthID on private key %s", - pk->ident); - res = 1; - } - pk->key_acl = calloc(1, sizeof(struct sc_acl_entry)); - pk->key_acl->method = SC_AC_CHV; - pk->key_acl->key_ref = pi->pkcs15.reference; - } - return res; } +#if 0 int sc_profile_build_pkcs15(struct sc_profile *pro) { struct sc_pkcs15_card *p15card; struct pin_info *pi; - struct prkey_info *prk; - struct pubkey_info *puk; + struct sc_key_template *prk; + struct sc_key_template *puk; int res = 0; p15card = pro->p15_card; @@ -434,12 +437,13 @@ sc_profile_build_pkcs15(struct sc_profile *pro) return res; } +#endif static int do_cardinfo(int argc, char **argv) { parser.section = PARSE_CARDINFO; - parser.cur_file = NULL; + cur_file = NULL; return 0; } @@ -546,8 +550,8 @@ static int do_mf(int argc, char **argv) { parser.section = PARSE_FILE; - parser.cur_file = &parser.profile->mf_info; - parser.cur_file->ident = strdup("MF"); + cur_file = &parser.profile->mf_info; + cur_file->ident = strdup("MF"); return 0; } @@ -555,8 +559,8 @@ static int do_df(int argc, char **argv) { parser.section = PARSE_FILE; - parser.cur_file = &parser.profile->df_info; - parser.cur_file->ident = strdup("App DF"); + cur_file = &parser.profile->df_info; + cur_file->ident = strdup("App DF"); return 0; } @@ -594,20 +598,11 @@ do_ef(int argc, char **argv) file = init_file(SC_FILE_TYPE_WORKING_EF); #endif } else { - struct sc_pkcs15_df *df; - if (map_str2int(name+7, &df_type, pkcs15DfNames)) return 1; - df = &pro->p15_card->df[df_type]; - if (df->count >= SC_PKCS15_MAX_DFS) { - parse_error("Too many EF(%s) files\n", name + 7); - return 1; - } - info->pkcs15.type = df_type; - info->pkcs15.fileno = df->count; file = (struct sc_file *) calloc(1, sizeof(*file)); - df->file[df->count++] = file; + pro->df[df_type] = file; } assert(file); @@ -619,14 +614,14 @@ do_ef(int argc, char **argv) info->next = parser.profile->ef_list; parser.profile->ef_list = info; -out: parser.cur_file = info; +out: cur_file = info; return 0; } static int do_path(int argc, char **argv) { - struct sc_file *file = parser.cur_file->file; + struct sc_file *file = cur_file->file; struct sc_path *path = &file->path; /* sc_format_path doesn't return an error indication @@ -641,6 +636,38 @@ do_path(int argc, char **argv) return 0; } +static int +do_fileid(int argc, char **argv) +{ + struct sc_profile *profile = parser.profile; + struct sc_file *file = cur_file->file, + *df = profile->df_info.file; + struct sc_path temp, *path = &file->path; + + /* sc_format_path doesn't return an error indication + * when it's unable to parse the path */ + sc_format_path(argv[0], &temp); + if (temp.len != 2) { + parse_error("Invalid file ID length\n"); + return 1; + } + if (df->path.len == 0) { + parse_error("No path set for Application DF\n"); + return 1; + } + if (df->path.len + 2 > sizeof(df->path)) { + parse_error("File path too long\n"); + return 1; + } + *path = df->path; + memcpy(path->value + path->len, temp.value, 2); + path->len += 2; + + file->id = (path->value[path->len-2] << 8) + | path->value[path->len-1]; + return 0; +} + static int do_structure(int argc, char **argv) { @@ -648,7 +675,7 @@ do_structure(int argc, char **argv) if (map_str2int(argv[0], &ef_structure, efTypeNames)) return 1; - parser.cur_file->file->ef_structure = ef_structure; + cur_file->file->ef_structure = ef_structure; return 0; } @@ -659,7 +686,7 @@ do_size(int argc, char **argv) if (get_uint(argv[0], &size)) return 1; - parser.cur_file->file->size = size; + cur_file->file->size = size; return 0; } @@ -670,14 +697,14 @@ do_reclength(int argc, char **argv) if (get_uint(argv[0], &reclength)) return 1; - parser.cur_file->file->record_length = reclength; + cur_file->file->record_length = reclength; return 0; } static int do_aid(int argc, char **argv) { - struct sc_file *file = parser.cur_file->file; + struct sc_file *file = cur_file->file; const char *name = argv[0]; unsigned int len; int res = 0; @@ -708,7 +735,7 @@ do_aid(int argc, char **argv) static int do_acl(int argc, char **argv) { - struct sc_file *file = parser.cur_file->file; + struct sc_file *file = cur_file->file; char *oper = 0, *what = 0; while (argc--) { @@ -765,8 +792,7 @@ do_pin(int argc, char **argv) return 1; } - pi = (struct pin_info *) malloc(sizeof(*pi)); - memset(pi, 0, sizeof(*pi)); + pi = (struct pin_info *) calloc(1, sizeof(*pi)); pi->ident = strdup(name); pi->id = id; pi->attempt[0] = 2; @@ -785,7 +811,7 @@ do_pin(int argc, char **argv) ; *tail = pi; -out: parser.cur_pin = pi; +out: cur_pin = pi; return 0; } @@ -799,20 +825,20 @@ do_pin_file(int argc, char **argv) parse_error("unknown PIN file \"%s\"\n", name); return 1; } - parser.cur_pin->file = fi; + cur_pin->file = fi; return 0; } static int do_pin_offset(int argc, char **argv) { - return get_uint(argv[0], &parser.cur_pin->file_offset); + return get_uint(argv[0], &cur_pin->file_offset); } static int do_pin_attempts(int argc, char **argv) { - struct pin_info *pi = parser.cur_pin; + struct pin_info *pi = cur_pin; int i; memset(pi->attempt, 0, sizeof(pi->attempt)); @@ -830,7 +856,7 @@ do_pin_type(int argc, char **argv) if (map_str2int(argv[0], &type, pinTypeNames)) return 1; - parser.cur_pin->pkcs15.type = type; + cur_pin->pkcs15.type = type; return 0; } @@ -841,21 +867,21 @@ do_pin_reference(int argc, char **argv) if (get_uint(argv[0], &reference)) return 1; - parser.cur_pin->pkcs15.reference = reference; + cur_pin->pkcs15.reference = reference; return 0; } static int do_pin_authid(int argc, char **argv) { - sc_pkcs15_format_id(argv[0], &parser.cur_pin->pkcs15.auth_id); + sc_pkcs15_format_id(argv[0], &cur_pin->pkcs15.auth_id); return 0; } static int do_pin_label(int argc, char **argv) { - strcpy(parser.cur_pin->pkcs15_obj.label, argv[0]); + strcpy(cur_pin->pkcs15_obj.label, argv[0]); return 0; } @@ -863,9 +889,9 @@ static int do_prkey(int argc, char **argv) { struct sc_profile *pro = parser.profile; - struct prkey_info *ki, **tail; + struct sc_key_template *ki, **tail; - if ((ki = sc_profile_find_prkey(pro, argv[0])) != NULL) + if ((ki = sc_profile_find_private_key(pro, argv[0])) != NULL) goto out; ki = calloc(1, sizeof(*ki)); @@ -875,8 +901,8 @@ do_prkey(int argc, char **argv) * the PrKDF is big enough. * This value will be overwritten later when the keys are * loaded into the card. */ - ki->pkcs15.modulus_length = 1024; - ki->pkcs15.access_flags = pro->rsa_access_flags; + ki->pkcs15.priv.modulus_length = 1024; + ki->pkcs15.priv.access_flags = pro->rsa_access_flags; ki->pkcs15_obj.type = SC_PKCS15_TYPE_PRKEY_RSA; ki->pkcs15_obj.data = &ki->pkcs15; @@ -885,8 +911,8 @@ do_prkey(int argc, char **argv) ; *tail = ki; -out: parser.cur_prkey = ki; - parser.section = PARSE_PRKEY; +out: parser.section = PARSE_PRKEY; + cur_key = ki; return 0; } @@ -900,30 +926,30 @@ do_prkey_file(int argc, char **argv) parse_error("unknown private key file \"%s\"\n", name); return 1; } - parser.cur_prkey->file = fi; + cur_key->file = fi->file; return 0; } static int do_prkey_index(int argc, char **argv) { - return get_uint(argv[0], &parser.cur_prkey->index); + return get_uint(argv[0], &cur_key->index); } static int do_prkey_algorithm(int argc, char **argv) { - struct prkey_info *ki = parser.cur_prkey; + struct sc_key_template *ki = cur_key; if (map_str2int(argv[0], &ki->pkcs15_obj.type, algorithmNames)) return 1; switch (ki->pkcs15_obj.type) { case SC_PKCS15_TYPE_PRKEY_RSA: - ki->pkcs15.access_flags = parser.profile->rsa_access_flags; + ki->pkcs15.priv.access_flags = parser.profile->rsa_access_flags; break; #ifdef SC_PKCS15_TYPE_PRKEY_DSA case SC_PKCS15_TYPE_PRKEY_DSA: - ki->pkcs15.access_flags = parser.profile->dsa_access_flags; + ki->pkcs15.priv.access_flags = parser.profile->dsa_access_flags; break; #endif } @@ -933,28 +959,28 @@ do_prkey_algorithm(int argc, char **argv) static int do_prkey_label(int argc, char **argv) { - strcpy(parser.cur_prkey->pkcs15_obj.label, argv[0]); + strcpy(cur_key->pkcs15_obj.label, argv[0]); return 0; } static int do_prkey_id(int argc, char **argv) { - sc_pkcs15_format_id(argv[0], &parser.cur_prkey->pkcs15.id); + sc_pkcs15_format_id(argv[0], &cur_key->pkcs15.priv.id); return 0; } static int do_prkey_authid(int argc, char **argv) { - sc_pkcs15_format_id(argv[0], &parser.cur_prkey->pkcs15_obj.auth_id); + sc_pkcs15_format_id(argv[0], &cur_key->pkcs15_obj.auth_id); return 0; } static int do_prkey_usage(int argc, char **argv) { - struct sc_pkcs15_prkey_info *ki = &parser.cur_prkey->pkcs15; + struct sc_pkcs15_prkey_info *ki = &cur_key->pkcs15.priv; if (map_str2int(argv[0], &ki->usage, keyUsageNames)) { parse_error("Bad key usage \"%s\"", argv[0]); @@ -966,7 +992,7 @@ do_prkey_usage(int argc, char **argv) static int do_prkey_access_flags(int argc, char **argv) { - struct sc_pkcs15_prkey_info *ki = &parser.cur_prkey->pkcs15; + struct sc_pkcs15_prkey_info *ki = &cur_key->pkcs15.priv; unsigned int access; ki->access_flags = 0; @@ -981,7 +1007,7 @@ do_prkey_access_flags(int argc, char **argv) static int do_prkey_reference(int argc, char **argv) { - struct sc_pkcs15_prkey_info *ki = &parser.cur_prkey->pkcs15; + struct sc_pkcs15_prkey_info *ki = &cur_key->pkcs15.priv; return get_uint(argv[0], (unsigned int *) &ki->key_reference); } @@ -990,9 +1016,9 @@ static int do_pubkey(int argc, char **argv) { struct sc_profile *pro = parser.profile; - struct pubkey_info *ki, **tail; + struct sc_key_template *ki, **tail; - if ((ki = sc_profile_find_pubkey(pro, argv[0])) != NULL) + if ((ki = sc_profile_find_public_key(pro, argv[0])) != NULL) goto out; ki = calloc(1, sizeof(*ki)); @@ -1002,8 +1028,8 @@ do_pubkey(int argc, char **argv) * the PrKDF is big enough. * This value will be overwritten later when the keys are * loaded into the card. */ - ki->pkcs15.modulus_length = 1024; - ki->pkcs15.access_flags = pro->rsa_access_flags; + ki->pkcs15.pub.modulus_length = 1024; + ki->pkcs15.pub.access_flags = pro->rsa_access_flags; ki->pkcs15_obj.type = SC_PKCS15_TYPE_PRKEY_RSA; ki->pkcs15_obj.data = &ki->pkcs15; @@ -1012,7 +1038,7 @@ do_pubkey(int argc, char **argv) ; *tail = ki; -out: parser.cur_pubkey = ki; +out: cur_key = ki; parser.section = PARSE_PUBKEY; return 0; } @@ -1027,61 +1053,52 @@ do_pubkey_file(int argc, char **argv) parse_error("unknown private key file \"%s\"\n", name); return 1; } - parser.cur_pubkey->file = fi; + cur_key->file = fi->file; return 0; } static int do_pubkey_index(int argc, char **argv) { - return get_uint(argv[0], &parser.cur_pubkey->index); + return get_uint(argv[0], &cur_key->index); } static int do_pubkey_algorithm(int argc, char **argv) { - struct pubkey_info *ki = parser.cur_pubkey; + struct sc_key_template *ki = cur_key; if (map_str2int(argv[0], &ki->pkcs15_obj.type, algorithmNames)) return 1; - switch (ki->pkcs15_obj.type) { - case SC_PKCS15_TYPE_PRKEY_RSA: - ki->pkcs15.access_flags = parser.profile->rsa_access_flags; - break; -#ifdef SC_PKCS15_TYPE_PRKEY_DSA - case SC_PKCS15_TYPE_PRKEY_DSA: - ki->pkcs15.access_flags = parser.profile->dsa_access_flags; - break; -#endif - } + ki->pkcs15.pub.access_flags = DEF_PUBKEY_ACCESS; return 0; } static int do_pubkey_label(int argc, char **argv) { - strcpy(parser.cur_pubkey->pkcs15_obj.label, argv[0]); + strcpy(cur_key->pkcs15_obj.label, argv[0]); return 0; } static int do_pubkey_id(int argc, char **argv) { - sc_pkcs15_format_id(argv[0], &parser.cur_pubkey->pkcs15.id); + sc_pkcs15_format_id(argv[0], &cur_key->pkcs15.pub.id); return 0; } static int do_pubkey_authid(int argc, char **argv) { - sc_pkcs15_format_id(argv[0], &parser.cur_pubkey->pkcs15_obj.auth_id); + sc_pkcs15_format_id(argv[0], &cur_key->pkcs15_obj.auth_id); return 0; } static int do_pubkey_usage(int argc, char **argv) { - struct sc_pkcs15_pubkey_info *ki = &parser.cur_pubkey->pkcs15; + struct sc_pkcs15_pubkey_info *ki = &cur_key->pkcs15.pub; if (map_str2int(argv[0], &ki->usage, keyUsageNames)) { parse_error("Bad key usage \"%s\"", argv[0]); @@ -1093,7 +1110,7 @@ do_pubkey_usage(int argc, char **argv) static int do_pubkey_access_flags(int argc, char **argv) { - struct sc_pkcs15_pubkey_info *ki = &parser.cur_pubkey->pkcs15; + struct sc_pkcs15_pubkey_info *ki = &cur_key->pkcs15.pub; unsigned int access; ki->access_flags = 0; @@ -1108,7 +1125,7 @@ do_pubkey_access_flags(int argc, char **argv) static int do_pubkey_reference(int argc, char **argv) { - struct sc_pkcs15_pubkey_info *ki = &parser.cur_pubkey->pkcs15; + struct sc_pkcs15_pubkey_info *ki = &cur_key->pkcs15.pub; return get_uint(argv[0], (unsigned int *) &ki->key_reference); } @@ -1127,6 +1144,7 @@ static struct command commands[] = { { "DF", -1, 0, 0, do_df }, { "EF", -1, 1, 1, do_ef }, { "Path", PARSE_FILE, 1, 1, do_path }, + { "FileID", PARSE_FILE, 1, 1, do_fileid }, { "Structure", PARSE_FILE, 1, 1, do_structure }, { "Size", PARSE_FILE, 1, 1, do_size }, { "RecordLength", PARSE_FILE, 1, 1, do_reclength }, @@ -1256,10 +1274,10 @@ sc_profile_find_key(struct sc_profile *pro, return NULL; } -struct prkey_info * -sc_profile_find_prkey(struct sc_profile *pro, const char *ident) +struct sc_key_template * +sc_profile_find_private_key(struct sc_profile *pro, const char *ident) { - struct prkey_info *ki; + struct sc_key_template *ki; for (ki = pro->prkey_list; ki; ki = ki->next) { if (!strcasecmp(ki->ident, ident)) @@ -1268,10 +1286,10 @@ sc_profile_find_prkey(struct sc_profile *pro, const char *ident) return NULL; } -struct pubkey_info * -sc_profile_find_pubkey(struct sc_profile *pro, const char *ident) +struct sc_key_template * +sc_profile_find_public_key(struct sc_profile *pro, const char *ident) { - struct pubkey_info *ki; + struct sc_key_template *ki; for (ki = pro->pubkey_list; ki; ki = ki->next) { if (!strcasecmp(ki->ident, ident)) diff --git a/src/tools/profile.h b/src/tools/profile.h index 072e7920..27f84105 100644 --- a/src/tools/profile.h +++ b/src/tools/profile.h @@ -11,6 +11,13 @@ #include #include "opensc-pkcs15.h" +#ifndef SC_PKCS15_PROFILE_DIRECTORY +#define SC_PKCS15_PROFILE_DIRECTORY "/usr/lib/opensc/profiles" +#endif +#ifndef SC_PKCS15_PROFILE_SUFFIX +#define SC_PKCS15_PROFILE_SUFFIX "profile" +#endif + struct auth_info { struct auth_info * next; unsigned int type; /* CHV, AUT, PRO */ @@ -26,10 +33,12 @@ struct file_info { struct sc_file * file; /* PKCS15 book-keeping info */ + /* struct { unsigned int fileno; unsigned int type; } pkcs15; + */ }; /* For now, we assume the PUK always resides @@ -50,37 +59,34 @@ struct pin_info { char * secret[2]; }; -struct prkey_info { +struct sc_key_template { char * ident; - struct prkey_info * next; - struct file_info * file; + struct sc_key_template *next; + //struct file_info * file; + struct sc_file * file; unsigned int index; /* translates to file offset */ struct sc_acl_entry * key_acl;/* PINs for key usage */ struct sc_pkcs15_object pkcs15_obj; - struct sc_pkcs15_prkey_info pkcs15; -}; - -struct pubkey_info { - char * ident; - struct pubkey_info * next; - struct file_info * file; - unsigned int index; /* translates to file offset */ - - struct sc_pkcs15_object pkcs15_obj; - struct sc_pkcs15_pubkey_info pkcs15; + union { + struct sc_pkcs15_prkey_info priv; + struct sc_pkcs15_pubkey_info pub; + } pkcs15; }; struct sc_profile { char * driver; + struct pkcs15_init_operations *ops; struct file_info mf_info; struct file_info df_info; struct file_info * ef_list; + struct sc_file * df[SC_PKCS15_DF_TYPE_COUNT]; + struct pin_info * pin_list; struct auth_info * auth_list; - struct prkey_info * prkey_list; - struct pubkey_info * pubkey_list; + struct sc_key_template *prkey_list; + struct sc_key_template *pubkey_list; unsigned int pin_maxlen; unsigned int pin_minlen; @@ -103,8 +109,9 @@ int sc_profile_build_pkcs15(struct sc_profile *); struct file_info *sc_profile_find_file(struct sc_profile *, const char *); struct file_info *sc_profile_file_info(struct sc_profile *, struct sc_file *); struct pin_info *sc_profile_find_pin(struct sc_profile *, const char *); -struct prkey_info *sc_profile_find_prkey(struct sc_profile *, const char *); -struct pubkey_info *sc_profile_find_pubkey(struct sc_profile *, const char *); +struct sc_key_template *sc_profile_find_private_key(struct sc_profile *, + const char *); +struct sc_key_template *sc_profile_find_public_key(struct sc_profile *, const char *); struct auth_info *sc_profile_find_key(struct sc_profile *, unsigned int, unsigned int);