pkcs15init: add support for secret key upload and generation
This commit is contained in:
parent
576e70b70f
commit
3d8cf274ff
|
@ -285,6 +285,7 @@ sc_pkcs15init_erase_card_recursively
|
||||||
sc_pkcs15init_finalize_card
|
sc_pkcs15init_finalize_card
|
||||||
sc_pkcs15init_fixup_file
|
sc_pkcs15init_fixup_file
|
||||||
sc_pkcs15init_generate_key
|
sc_pkcs15init_generate_key
|
||||||
|
sc_pkcs15init_generate_secret_key
|
||||||
sc_pkcs15init_get_asepcos_ops
|
sc_pkcs15init_get_asepcos_ops
|
||||||
sc_pkcs15init_get_cardos_ops
|
sc_pkcs15init_get_cardos_ops
|
||||||
sc_pkcs15init_get_cryptoflex_ops
|
sc_pkcs15init_get_cryptoflex_ops
|
||||||
|
@ -313,6 +314,7 @@ sc_pkcs15init_store_data_object
|
||||||
sc_pkcs15init_store_pin
|
sc_pkcs15init_store_pin
|
||||||
sc_pkcs15init_store_private_key
|
sc_pkcs15init_store_private_key
|
||||||
sc_pkcs15init_store_public_key
|
sc_pkcs15init_store_public_key
|
||||||
|
sc_pkcs15init_store_secret_key
|
||||||
sc_pkcs15init_unbind
|
sc_pkcs15init_unbind
|
||||||
sc_pkcs15init_update_any_df
|
sc_pkcs15init_update_any_df
|
||||||
sc_pkcs15init_update_certificate
|
sc_pkcs15init_update_certificate
|
||||||
|
|
|
@ -28,6 +28,7 @@ extern "C" {
|
||||||
#include "libopensc/pkcs15.h"
|
#include "libopensc/pkcs15.h"
|
||||||
|
|
||||||
#define DEFAULT_PRIVATE_KEY_LABEL "Private Key"
|
#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_DIGITAL_SIGNATURE 0x0080UL
|
||||||
#define SC_PKCS15INIT_X509_NON_REPUDIATION 0x0040UL
|
#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 *,
|
struct sc_pkcs15init_keygen_args *,
|
||||||
unsigned int keybits,
|
unsigned int keybits,
|
||||||
struct sc_pkcs15_object **);
|
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 *,
|
extern int sc_pkcs15init_store_private_key(struct sc_pkcs15_card *,
|
||||||
struct sc_profile *,
|
struct sc_profile *,
|
||||||
struct sc_pkcs15init_prkeyargs *,
|
struct sc_pkcs15init_prkeyargs *,
|
||||||
|
@ -330,6 +335,10 @@ extern int sc_pkcs15init_store_public_key(struct sc_pkcs15_card *,
|
||||||
struct sc_profile *,
|
struct sc_profile *,
|
||||||
struct sc_pkcs15init_pubkeyargs *,
|
struct sc_pkcs15init_pubkeyargs *,
|
||||||
struct sc_pkcs15_object **);
|
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 *,
|
extern int sc_pkcs15init_store_certificate(struct sc_pkcs15_card *,
|
||||||
struct sc_profile *,
|
struct sc_profile *,
|
||||||
struct sc_pkcs15init_certargs *,
|
struct sc_pkcs15init_certargs *,
|
||||||
|
|
|
@ -1276,6 +1276,83 @@ err:
|
||||||
LOG_FUNC_RETURN(ctx, r);
|
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
|
static int
|
||||||
_pkcd15init_set_aux_md_data(struct sc_pkcs15_card *p15card, struct sc_auxiliary_data **aux_data,
|
_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);
|
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
|
* Store private key
|
||||||
|
@ -1707,6 +1846,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
|
* Store a certificate
|
||||||
*/
|
*/
|
||||||
|
@ -2336,6 +2547,12 @@ key_pkcs15_algo(struct sc_pkcs15_card *p15card, unsigned int algorithm)
|
||||||
return SC_PKCS15_TYPE_PRKEY_GOSTR3410;
|
return SC_PKCS15_TYPE_PRKEY_GOSTR3410;
|
||||||
case SC_ALGORITHM_EC:
|
case SC_ALGORITHM_EC:
|
||||||
return SC_PKCS15_TYPE_PRKEY_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.");
|
sc_log(ctx, "Unsupported key algorithm.");
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
|
Loading…
Reference in New Issue