[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