[pkg-opensc-commit] [opensc] 282/295: pkcs15init: add support for secret key upload and generation

Eric Dorland eric at moszumanska.debian.org
Sat Jun 24 21:11:40 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 3d8cf274ff87c626ba86bd2a16c70253ebfb871d
Author: Timo Teräs <timo.teras at iki.fi>
Date:   Fri Apr 14 10:39:26 2017 +0300

    pkcs15init: add support for secret key upload and generation
---
 src/libopensc/libopensc.exports |   2 +
 src/pkcs15init/pkcs15-init.h    |   9 ++
 src/pkcs15init/pkcs15-lib.c     | 217 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 228 insertions(+)

diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports
index 69af2ca..7931a26 100644
--- a/src/libopensc/libopensc.exports
+++ b/src/libopensc/libopensc.exports
@@ -285,6 +285,7 @@ sc_pkcs15init_erase_card_recursively
 sc_pkcs15init_finalize_card
 sc_pkcs15init_fixup_file
 sc_pkcs15init_generate_key
+sc_pkcs15init_generate_secret_key
 sc_pkcs15init_get_asepcos_ops
 sc_pkcs15init_get_cardos_ops
 sc_pkcs15init_get_cryptoflex_ops
@@ -313,6 +314,7 @@ sc_pkcs15init_store_data_object
 sc_pkcs15init_store_pin
 sc_pkcs15init_store_private_key
 sc_pkcs15init_store_public_key
+sc_pkcs15init_store_secret_key
 sc_pkcs15init_unbind
 sc_pkcs15init_update_any_df
 sc_pkcs15init_update_certificate
diff --git a/src/pkcs15init/pkcs15-init.h b/src/pkcs15init/pkcs15-init.h
index 950c743..44ab635 100644
--- a/src/pkcs15init/pkcs15-init.h
+++ b/src/pkcs15init/pkcs15-init.h
@@ -28,6 +28,7 @@ extern "C" {
 #include "libopensc/pkcs15.h"
 
 #define DEFAULT_PRIVATE_KEY_LABEL "Private Key"
+#define DEFAULT_SECRET_KEY_LABEL  "Secret Key"
 
 #define SC_PKCS15INIT_X509_DIGITAL_SIGNATURE     0x0080UL
 #define SC_PKCS15INIT_X509_NON_REPUDIATION       0x0040UL
@@ -317,6 +318,10 @@ extern int	sc_pkcs15init_generate_key(struct sc_pkcs15_card *,
 				struct sc_pkcs15init_keygen_args *,
 				unsigned int keybits,
 				struct sc_pkcs15_object **);
+extern int	sc_pkcs15init_generate_secret_key(struct sc_pkcs15_card *,
+				struct sc_profile *,
+				struct sc_pkcs15init_skeyargs *,
+				struct sc_pkcs15_object **);
 extern int	sc_pkcs15init_store_private_key(struct sc_pkcs15_card *,
 				struct sc_profile *,
 				struct sc_pkcs15init_prkeyargs *,
@@ -330,6 +335,10 @@ extern int	sc_pkcs15init_store_public_key(struct sc_pkcs15_card *,
 				struct sc_profile *,
 				struct sc_pkcs15init_pubkeyargs *,
 				struct sc_pkcs15_object **);
+extern int	sc_pkcs15init_store_secret_key(struct sc_pkcs15_card *,
+				struct sc_profile *,
+				struct sc_pkcs15init_skeyargs *,
+				struct sc_pkcs15_object **);
 extern int	sc_pkcs15init_store_certificate(struct sc_pkcs15_card *,
 				struct sc_profile *,
 				struct sc_pkcs15init_certargs *,
diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c
index 70a27f1..ec71919 100644
--- a/src/pkcs15init/pkcs15-lib.c
+++ b/src/pkcs15init/pkcs15-lib.c
@@ -1276,6 +1276,83 @@ err:
 	LOG_FUNC_RETURN(ctx, r);
 }
 
+/*
+ * Prepare secret key download, and initialize a skdf entry
+ */
+static int
+sc_pkcs15init_init_skdf(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
+		struct sc_pkcs15init_skeyargs *keyargs, struct sc_pkcs15_object **res_obj)
+{
+	struct sc_context *ctx = p15card->card->ctx;
+	struct sc_pkcs15_skey_info *key_info;
+	struct sc_pkcs15_object *object = NULL;
+	const char	*label;
+	unsigned int	usage;
+	unsigned int	keybits = keyargs->value_len;
+	int		r = 0, key_type;
+
+	LOG_FUNC_CALLED(ctx);
+	if (!res_obj || !keybits) {
+		r = SC_ERROR_INVALID_ARGUMENTS;
+		LOG_TEST_GOTO_ERR(ctx, r, "Initialize SKDF entry failed");
+	}
+
+	*res_obj = NULL;
+
+	if ((usage = keyargs->usage) == 0) {
+		usage = SC_PKCS15_PRKEY_USAGE_ENCRYPT|SC_PKCS15_PRKEY_USAGE_DECRYPT;
+	}
+
+	if ((label = keyargs->label) == NULL)
+		label = DEFAULT_SECRET_KEY_LABEL;
+
+	/* Create the skey object now.
+	 * If we find out below that we're better off reusing an
+	 * existing object, we'll ditch this one */
+	key_type = key_pkcs15_algo(p15card, keyargs->algorithm);
+	r = key_type;
+	LOG_TEST_GOTO_ERR(ctx, r, "Unsupported key type");
+
+	object = sc_pkcs15init_new_object(key_type, label, &keyargs->auth_id, NULL);
+	if (object == NULL)
+		LOG_TEST_GOTO_ERR(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate new SKey object");
+
+	key_info = (struct sc_pkcs15_skey_info *) object->data;
+	key_info->usage = usage;
+	key_info->native = 1;
+	key_info->key_reference = 0;
+	key_info->value_len = keybits;
+	key_info->access_flags = keyargs->access_flags;
+	/* Path is selected below */
+
+	if (keyargs->access_flags & SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE) {
+		key_info->access_flags &= ~SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE;
+		key_info->native = 0;
+	}
+
+	/* Select a Key ID if the user didn't specify one,
+	 * otherwise make sure it's compatible with our intended use */
+	r = select_id(p15card, SC_PKCS15_TYPE_SKEY, &keyargs->id);
+	LOG_TEST_GOTO_ERR(ctx, r, "Cannot select ID for SKey object");
+
+	key_info->id = keyargs->id;
+
+	r = select_object_path(p15card, profile, object, &key_info->path);
+	LOG_TEST_GOTO_ERR(ctx, r, "Failed to select secret key object path");
+
+	/* See if we need to select a key reference for this object */
+	if (profile->ops->select_key_reference)
+		LOG_TEST_GOTO_ERR(ctx, SC_ERROR_NOT_SUPPORTED, "SKey keyreference selection not supported");
+
+	*res_obj = object;
+	object = NULL;
+	r = SC_SUCCESS;
+
+err:
+	if (object)
+		sc_pkcs15init_free_object(object);
+	LOG_FUNC_RETURN(ctx, r);
+}
 
 static int
 _pkcd15init_set_aux_md_data(struct sc_pkcs15_card *p15card, struct sc_auxiliary_data **aux_data,
@@ -1463,6 +1540,68 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr
 	LOG_FUNC_RETURN(ctx, r);
 }
 
+/*
+ * Generate a new secret key
+ */
+int
+sc_pkcs15init_generate_secret_key(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
+		struct sc_pkcs15init_skeyargs *skey_args, struct sc_pkcs15_object **res_obj)
+{
+	struct sc_context *ctx = p15card->card->ctx;
+	struct sc_pkcs15_object *object = NULL;
+	unsigned int keybits = skey_args->value_len;
+	int r;
+
+	LOG_FUNC_CALLED(ctx);
+	/* check supported key size */
+	r = check_keygen_params_consistency(p15card->card, skey_args->algorithm, NULL, &keybits);
+	LOG_TEST_RET(ctx, r, "Invalid key size");
+
+	if (check_key_compatibility(p15card, skey_args->algorithm, NULL, 0,
+			keybits, SC_ALGORITHM_ONBOARD_KEY_GEN))
+		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Cannot generate key with the given parameters");
+
+	if (profile->ops->generate_key == NULL)
+		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key generation not supported");
+
+	if (skey_args->id.len)   {
+		/* Make sure that secret key's ID is the unique inside the PKCS#15 application */
+		r = sc_pkcs15_find_skey_by_id(p15card, &skey_args->id, NULL);
+		if (!r)
+			LOG_TEST_RET(ctx, SC_ERROR_NON_UNIQUE_ID, "Non unique ID of the private key object");
+		else if (r != SC_ERROR_OBJECT_NOT_FOUND)
+			LOG_TEST_RET(ctx, r, "Find private key error");
+	}
+
+	/* Set up the SKDF object */
+	r = sc_pkcs15init_init_skdf(p15card, profile, skey_args, &object);
+	LOG_TEST_RET(ctx, r, "Set up secret key object error");
+
+	/* Generate the secret key on card */
+	r = profile->ops->create_key(profile, p15card, object);
+	LOG_TEST_RET(ctx, r, "Cannot generate key: create key failed");
+
+	r = profile->ops->generate_key(profile, p15card, object, NULL);
+	LOG_TEST_RET(ctx, r, "Failed to generate key");
+
+	r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_SKDF, object);
+	LOG_TEST_RET(ctx, r, "Failed to add generated secret key object");
+
+	if (!r && profile->ops->emu_store_data)   {
+		r = profile->ops->emu_store_data(p15card, profile, object, NULL, NULL);
+		if (r == SC_ERROR_NOT_IMPLEMENTED)
+			r = SC_SUCCESS;
+		LOG_TEST_RET(ctx, r, "Card specific 'store data' failed");
+	}
+
+	if (res_obj)
+		*res_obj = object;
+
+	profile->dirty = 1;
+
+	LOG_FUNC_RETURN(ctx, r);
+}
+
 
 /*
  * Store private key
@@ -1708,6 +1847,78 @@ err:
 
 
 /*
+ * Store secret key
+ */
+int
+sc_pkcs15init_store_secret_key(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
+		struct sc_pkcs15init_skeyargs *keyargs, struct sc_pkcs15_object **res_obj)
+{
+	struct sc_context *ctx = p15card->card->ctx;
+	struct sc_pkcs15_object *object = NULL;
+	int r = 0;
+
+	LOG_FUNC_CALLED(ctx);
+
+	/* Now check whether the card is able to handle this key */
+	if (check_key_compatibility(p15card, keyargs->algorithm, NULL, 0, keyargs->key.data_len * 8, 0)) {
+		/* Make sure the caller explicitly tells us to store
+		 * the key as extractable. */
+		if (!(keyargs->access_flags & SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE))
+			LOG_TEST_RET(ctx, SC_ERROR_INCOMPATIBLE_KEY, "Card does not support this key.");
+	}
+
+	/* Select a intrinsic Key ID if user didn't specify one */
+	r = sc_pkcs15init_select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_SKEY,
+			&keyargs->id, &keyargs->key);
+	LOG_TEST_RET(ctx, r, "Get intrinsic ID error");
+
+	/* Make sure that private key's ID is the unique inside the PKCS#15 application */
+	r = sc_pkcs15_find_skey_by_id(p15card, &keyargs->id, NULL);
+	if (!r)
+		LOG_TEST_RET(ctx, SC_ERROR_NON_UNIQUE_ID, "Non unique ID of the secret key object");
+	else if (r != SC_ERROR_OBJECT_NOT_FOUND)
+		LOG_TEST_RET(ctx, r, "Find secret key error");
+
+	/* Set up the SKDF object */
+	r = sc_pkcs15init_init_skdf(p15card, profile, keyargs, &object);
+	LOG_TEST_RET(ctx, r, "Failed to initialize secret key object");
+
+	if (profile->ops->create_key)
+		r = profile->ops->create_key(profile, p15card, object);
+	LOG_TEST_RET(ctx, r, "Card specific 'create key' failed");
+
+	if (profile->ops->store_key) {
+		struct sc_pkcs15_prkey key;
+		memset(&key, 0, sizeof(key));
+		key.algorithm = keyargs->algorithm;
+		key.u.secret = keyargs->key;
+		r = profile->ops->store_key(profile, p15card, object, &key);
+	}
+	LOG_TEST_RET(ctx, r, "Card specific 'store key' failed");
+
+	sc_pkcs15_free_object_content(object);
+
+	/* Now update the SKDF */
+	r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_SKDF, object);
+	LOG_TEST_RET(ctx, r, "Failed to add new secret key PKCS#15 object");
+
+	if (!r && profile->ops->emu_store_data)   {
+		r = profile->ops->emu_store_data(p15card, profile, object, NULL, NULL);
+		if (r == SC_ERROR_NOT_IMPLEMENTED)
+			r = SC_SUCCESS;
+		LOG_TEST_RET(ctx, r, "Card specific 'store data' failed");
+	}
+
+	if (r >= 0 && res_obj)
+		*res_obj = object;
+
+	profile->dirty = 1;
+
+	LOG_FUNC_RETURN(ctx, r);
+}
+
+
+/*
  * Store a certificate
  */
 int
@@ -2336,6 +2547,12 @@ key_pkcs15_algo(struct sc_pkcs15_card *p15card, unsigned int algorithm)
 		return SC_PKCS15_TYPE_PRKEY_GOSTR3410;
 	case SC_ALGORITHM_EC:
 		return SC_PKCS15_TYPE_PRKEY_EC;
+	case SC_ALGORITHM_DES:
+		return SC_PKCS15_TYPE_SKEY_DES;
+	case SC_ALGORITHM_3DES:
+		return SC_PKCS15_TYPE_SKEY_3DES;
+	case SC_ALGORITHM_AES:
+		return SC_PKCS15_TYPE_SKEY_GENERIC;
 	}
 	sc_log(ctx, "Unsupported key algorithm.");
 	return SC_ERROR_NOT_SUPPORTED;

-- 
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