[pkg-opensc-commit] [opensc] 284/295: pkcs15-init: support secret key upload and generation
Eric Dorland
eric at moszumanska.debian.org
Sat Jun 24 21:11:41 UTC 2017
This is an automated email from the git hooks/post-receive script.
eric pushed a commit to branch master
in repository opensc.
commit e23190d0b5b80362bfb21fc5f66b780ade9a1c08
Author: Timo Teräs <timo.teras at iki.fi>
Date: Fri Apr 14 10:44:07 2017 +0300
pkcs15-init: support secret key upload and generation
---
src/tools/pkcs15-init.c | 239 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 194 insertions(+), 45 deletions(-)
diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c
index 2038c27..38a40b9 100644
--- a/src/tools/pkcs15-init.c
+++ b/src/tools/pkcs15-init.c
@@ -88,19 +88,22 @@ static int do_change_attributes(struct sc_profile *, unsigned int myopt_type);
static int do_init_app(struct sc_profile *);
static int do_store_pin(struct sc_profile *);
static int do_generate_key(struct sc_profile *, const char *);
+static int do_generate_skey(struct sc_profile *, const char *);
static int do_store_private_key(struct sc_profile *);
static int do_store_public_key(struct sc_profile *, EVP_PKEY *);
+static int do_store_secret_key(struct sc_profile *);
static int do_store_certificate(struct sc_profile *);
static int do_update_certificate(struct sc_profile *);
static int do_convert_cert(sc_pkcs15_der_t *, X509 *);
static int is_cacert_already_present(struct sc_pkcs15init_certargs *);
static int do_finalize_card(sc_card_t *, struct sc_profile *);
-static int do_read_data_object(const char *name, u8 **out, size_t *outlen);
+static int do_read_data_object(const char *name, u8 **out, size_t *outlen, size_t expected);
static int do_store_data_object(struct sc_profile *profile);
static int do_sanity_check(struct sc_profile *profile);
-static int init_keyargs(struct sc_pkcs15init_prkeyargs *);
+static int init_prkeyargs(struct sc_pkcs15init_prkeyargs *);
+static int init_skeyargs(struct sc_pkcs15init_skeyargs *);
static void init_gost_params(struct sc_pkcs15init_keyarg_gost_params *, EVP_PKEY *);
static int get_pin_callback(struct sc_profile *profile,
int id, const struct sc_pkcs15_auth_info *info,
@@ -123,11 +126,13 @@ enum {
OPT_OPTIONS = 0x100,
OPT_PASSPHRASE,
OPT_PUBKEY,
+ OPT_SECRKEY,
OPT_EXTRACTABLE,
OPT_INSECURE,
OPT_AUTHORITY,
OPT_ASSERT_PRISTINE,
OPT_SECRET,
+ OPT_SECRKEY_ALGO,
OPT_PUBKEY_LABEL,
OPT_CERT_LABEL,
OPT_APPLICATION_NAME,
@@ -162,6 +167,7 @@ const struct option options[] = {
{ "generate-key", required_argument, NULL, 'G' },
{ "store-private-key", required_argument, NULL, 'S' },
{ "store-public-key", required_argument, NULL, OPT_PUBKEY },
+ { "store-secret-key", required_argument, NULL, OPT_SECRKEY },
{ "store-certificate", required_argument, NULL, 'X' },
{ "update-certificate", required_argument, NULL, 'U' },
{ "store-data", required_argument, NULL, 'W' },
@@ -183,6 +189,7 @@ const struct option options[] = {
{ "id", required_argument, NULL, 'i' },
{ "label", required_argument, NULL, 'l' },
{ "puk-label", required_argument, NULL, OPT_PUK_LABEL },
+ { "secret-key-algorithm", required_argument, NULL, OPT_SECRKEY_ALGO },
{ "public-key-label", required_argument, NULL, OPT_PUBKEY_LABEL },
{ "cert-label", required_argument, NULL, OPT_CERT_LABEL },
{ "application-name", required_argument, NULL, OPT_APPLICATION_NAME },
@@ -226,6 +233,7 @@ static const char * option_help[] = {
"Generate a new key and store it on the card",
"Store private key",
"Store public key",
+ "Store secret key",
"Store an X.509 certificate",
"Update an X.509 certificate (carefull with mail decryption certs!!)",
"Store a data object",
@@ -247,6 +255,7 @@ static const char * option_help[] = {
"Specify ID of key/certificate",
"Specify label of PIN/key",
"Specify label of PUK",
+ "Specify secret key algorithm (use with --store-secret-key)",
"Specify public key label (use with --generate-key)",
"Specify user cert label (use with --store-private-key)",
"Specify application name of data object (use with --store-data-object)",
@@ -290,6 +299,7 @@ enum {
ACTION_GENERATE_KEY,
ACTION_STORE_PRIVKEY,
ACTION_STORE_PUBKEY,
+ ACTION_STORE_SECRKEY,
ACTION_STORE_CERT,
ACTION_UPDATE_CERT,
ACTION_STORE_DATA,
@@ -312,6 +322,7 @@ static const char *action_names[] = {
"generate key",
"store private key",
"store public key",
+ "store secret key",
"store certificate",
"update certificate",
"store data object",
@@ -362,6 +373,7 @@ static char * opt_objectid = NULL;
static char * opt_label = NULL;
static char * opt_puk_label = NULL;
static char * opt_pubkey_label = NULL;
+static char * opt_secrkey_algo = NULL;
static char * opt_cert_label = NULL;
static const char * opt_pins[4];
static char * pins[4];
@@ -572,6 +584,9 @@ main(int argc, char **argv)
case ACTION_STORE_PUBKEY:
r = do_store_public_key(profile, NULL);
break;
+ case ACTION_STORE_SECRKEY:
+ r = do_store_secret_key(profile);
+ break;
case ACTION_STORE_CERT:
r = do_store_certificate(profile);
break;
@@ -589,6 +604,8 @@ main(int argc, char **argv)
break;
case ACTION_GENERATE_KEY:
r = do_generate_key(profile, opt_newkey);
+ if (r == SC_ERROR_INVALID_ARGUMENTS)
+ r = do_generate_skey(profile, opt_newkey);
break;
case ACTION_FINALIZE_CARD:
r = do_finalize_card(card, profile);
@@ -702,6 +719,65 @@ end:
return ok ? 0 : -1;
}
+/* algorithm spec parsing */
+struct alg_spec {
+ const char *spec;
+ int algorithm;
+ unsigned int keybits;
+};
+
+static const struct alg_spec alg_types_sym[] = {
+ { "des", SC_ALGORITHM_DES, 56 },
+ { "3des", SC_ALGORITHM_3DES, 192 },
+ { "aes", SC_ALGORITHM_AES, 128 },
+ { NULL, -1, 0 }
+};
+
+static const struct alg_spec alg_types_asym[] = {
+ { "rsa", SC_ALGORITHM_RSA, 1024 },
+ { "dsa", SC_ALGORITHM_DSA, 1024 },
+ { "gost2001", SC_ALGORITHM_GOSTR3410, SC_PKCS15_GOSTR3410_KEYSIZE },
+ { "ec", SC_ALGORITHM_EC, 0 },
+ { NULL, -1, 0 }
+};
+
+static int
+parse_alg_spec(const struct alg_spec *types, const char *spec, unsigned int *keybits, struct sc_pkcs15_prkey *prkey)
+{
+ int i, algorithm = -1;
+ char *end;
+
+ for (i = 0; types[i].spec; i++) {
+ if (!strncasecmp(spec, types[i].spec, strlen(types[i].spec))) {
+ algorithm = types[i].algorithm;
+ *keybits = types[i].keybits;
+ spec += strlen(types[i].spec);
+ break;
+ }
+ }
+ if (algorithm < 0) {
+ util_error("Unknown algorithm \"%s\"", spec);
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
+
+ if (*spec == '/' || *spec == '-' || *spec == ':')
+ spec++;
+
+ if (*spec) {
+ if (isalpha(*spec) && algorithm == SC_ALGORITHM_EC && prkey) {
+ prkey->u.ec.params.named_curve = strdup(spec);
+ } else {
+ *keybits = strtoul(spec, &end, 10);
+ if (*end) {
+ util_error("Invalid number of key bits \"%s\"", spec);
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
+ }
+ }
+
+ return algorithm;
+}
+
/*
* Erase card
*/
@@ -936,7 +1012,7 @@ do_store_private_key(struct sc_profile *profile)
X509 *cert[MAX_CERTS];
int r, i, ncerts;
- if ((r = init_keyargs(&args)) < 0)
+ if ((r = init_prkeyargs(&args)) < 0)
return r;
r = do_read_private_key(opt_infile, opt_format, &pkey, cert, MAX_CERTS);
@@ -1130,6 +1206,49 @@ do_store_public_key(struct sc_profile *profile, EVP_PKEY *pkey)
}
/*
+ * Store a secret key
+ */
+static int
+do_store_secret_key(struct sc_profile *profile)
+{
+ struct sc_pkcs15init_skeyargs args;
+ unsigned int keybits;
+ int r, algorithm = -1;
+
+ if (!opt_secrkey_algo) {
+ util_error("Specify secret key algorithm with --secret-key-algorithm");
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
+
+ if ((r = init_skeyargs(&args)) < 0)
+ return r;
+
+ algorithm = parse_alg_spec(alg_types_sym, opt_secrkey_algo, &keybits, 0);
+ if (algorithm < 0) {
+ util_error("Invalid symmetric key spec: \"%s\"", opt_secrkey_algo);
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
+
+ r = do_read_data_object(opt_infile, &args.key.data, &args.key.data_len, (keybits+7) / 8);
+ if (r < 0)
+ return r;
+
+ args.algorithm = algorithm;
+ args.value_len = keybits;
+ args.access_flags |=
+ SC_PKCS15_PRKEY_ACCESS_SENSITIVE
+ | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
+ | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE;
+
+ r = sc_lock(p15card->card);
+ if (r < 0)
+ return r;
+ r = sc_pkcs15init_store_secret_key(p15card, profile, &args, NULL);
+ sc_unlock(p15card->card);
+ return r;
+}
+
+/*
* Download certificate to card
*/
static int
@@ -1313,7 +1432,7 @@ do_store_data_object(struct sc_profile *profile)
return SC_ERROR_INVALID_ARGUMENTS;
}
- r = do_read_data_object(opt_infile, &data, &datalen);
+ r = do_read_data_object(opt_infile, &data, &datalen, 0);
if (r >= 0) {
/* der_encoded contains the plain data, nothing DER encoded */
args.der_encoded.value = data;
@@ -1610,68 +1729,71 @@ static int
do_generate_key(struct sc_profile *profile, const char *spec)
{
struct sc_pkcs15init_keygen_args keygen_args;
- unsigned int keybits = 1024;
- int r;
+ unsigned int keybits = 0;
+ int r, algorithm = -1;
memset(&keygen_args, 0, sizeof(keygen_args));
keygen_args.pubkey_label = opt_pubkey_label;
- if ((r = init_keyargs(&keygen_args.prkey_args)) < 0)
+ if ((r = init_prkeyargs(&keygen_args.prkey_args)) < 0)
return r;
+
+ algorithm = parse_alg_spec(alg_types_asym, spec, &keybits, &keygen_args.prkey_args.key);
+ if (algorithm < 0) {
+ util_error("Invalid key spec: \"%s\"", spec);
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
+
+ keygen_args.prkey_args.key.algorithm = algorithm;
keygen_args.prkey_args.access_flags |=
SC_PKCS15_PRKEY_ACCESS_SENSITIVE
| SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
| SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
| SC_PKCS15_PRKEY_ACCESS_LOCAL;
- /* Parse the key spec given on the command line */
- if (!strncasecmp(spec, "rsa", 3)) {
- keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA;
- spec += 3;
- } else if (!strncasecmp(spec, "dsa", 3)) {
- keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_DSA;
- spec += 3;
- } else if (!strncasecmp(spec, "gost2001", strlen("gost2001"))) {
- keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_GOSTR3410;
- keybits = SC_PKCS15_GOSTR3410_KEYSIZE;
+ switch (algorithm) {
+ case SC_ALGORITHM_GOSTR3410:
/* FIXME: now only SC_PKCS15_PARAMSET_GOSTR3410_A */
keygen_args.prkey_args.params.gost.gostr3410 = SC_PKCS15_PARAMSET_GOSTR3410_A;
- spec += strlen("gost2001");
- } else if (!strncasecmp(spec, "ec", 2)) {
- keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EC;
- spec += 2;
- } else {
- util_error("Unknown algorithm \"%s\"", spec);
- return SC_ERROR_INVALID_ARGUMENTS;
+ break;
}
- if (*spec == '/' || *spec == '-' || *spec == ':')
- spec++;
+ r = sc_lock(p15card->card);
+ if (r == 0)
+ r = sc_pkcs15init_generate_key(p15card, profile, &keygen_args, keybits, NULL);
+ sc_unlock(p15card->card);
+ return r;
+}
- if (*spec) {
- if (isalpha(*spec) && keygen_args.prkey_args.key.algorithm == SC_ALGORITHM_EC) {
- keygen_args.prkey_args.key.u.ec.params.named_curve = strdup(spec);
- keybits = 0;
- }
- else {
- char *end;
+/*
+ * Generate a new secret key
+ */
+static int
+do_generate_skey(struct sc_profile *profile, const char *spec)
+{
+ struct sc_pkcs15init_skeyargs skey_args;
+ unsigned int keybits;
+ int r, algorithm = -1;
- keybits = strtoul(spec, &end, 10);
- if (*end) {
- util_error("Invalid number of key bits \"%s\"", spec);
- return SC_ERROR_INVALID_ARGUMENTS;
- }
- }
+ if ((r = init_skeyargs(&skey_args)) < 0)
+ return r;
+ skey_args.algorithm = algorithm;
+
+ algorithm = parse_alg_spec(alg_types_sym, spec, &keybits, 0);
+ if (algorithm < 0) {
+ util_error("Invalid symmetric key spec: \"%s\"", spec);
+ return SC_ERROR_INVALID_ARGUMENTS;
}
+ skey_args.value_len = keybits;
+
r = sc_lock(p15card->card);
- if (r < 0)
- return r;
- r = sc_pkcs15init_generate_key(p15card, profile, &keygen_args, keybits, NULL);
+ if (r == 0)
+ r = sc_pkcs15init_generate_secret_key(p15card, profile, &skey_args, NULL);
sc_unlock(p15card->card);
return r;
}
-static int init_keyargs(struct sc_pkcs15init_prkeyargs *args)
+static int init_prkeyargs(struct sc_pkcs15init_prkeyargs *args)
{
memset(args, 0, sizeof(*args));
if (opt_objectid)
@@ -1697,6 +1819,26 @@ static int init_keyargs(struct sc_pkcs15init_prkeyargs *args)
return 0;
}
+static int init_skeyargs(struct sc_pkcs15init_skeyargs *args)
+{
+ memset(args, 0, sizeof(*args));
+ if (opt_objectid)
+ sc_pkcs15_format_id(opt_objectid, &args->id);
+ if (opt_authid) {
+ sc_pkcs15_format_id(opt_authid, &args->auth_id);
+ } else if (!opt_insecure) {
+ util_error("no PIN given for key - either use --insecure or \n"
+ "specify a PIN using --auth-id");
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
+ if (opt_extractable) {
+ args->access_flags |= SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
+ }
+ args->label = opt_label;
+
+ return 0;
+}
+
static void
init_gost_params(struct sc_pkcs15init_keyarg_gost_params *params, EVP_PKEY *pkey)
{
@@ -2310,10 +2452,10 @@ static size_t determine_filesize(const char *filename)
}
static int
-do_read_data_object(const char *name, u8 **out, size_t *outlen)
+do_read_data_object(const char *name, u8 **out, size_t *outlen, size_t expected)
{
FILE *inf;
- size_t filesize = determine_filesize(name);
+ size_t filesize = expected ? expected : determine_filesize(name);
int c;
*out = malloc(filesize);
@@ -2615,6 +2757,10 @@ handle_option(const struct option *opt)
this_action = ACTION_STORE_PUBKEY;
opt_infile = optarg;
break;
+ case OPT_SECRKEY:
+ this_action = ACTION_STORE_SECRKEY;
+ opt_infile = optarg;
+ break;
case OPT_INSECURE:
opt_insecure = 1;
break;
@@ -2657,6 +2803,9 @@ handle_option(const struct option *opt)
parse_secret(&opt_secrets[opt_secret_count], optarg);
opt_secret_count++;
break;
+ case OPT_SECRKEY_ALGO:
+ opt_secrkey_algo = optarg;
+ break;
case OPT_PUBKEY_LABEL:
opt_pubkey_label = optarg;
break;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/opensc.git
More information about the pkg-opensc-commit
mailing list