Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PKCS11_generate_ec_key() for private EC key generation #379

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/libp11-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ extern int pkcs11_generate_key(PKCS11_TOKEN * token,
int algorithm, unsigned int bits,
char *label, unsigned char* id, size_t id_len);

/* Generate and store a private EC key on the token */
extern int pkcs11_generate_ec_key(PKCS11_TOKEN * token, const char *curve,
char *label, unsigned char* id, size_t id_len);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A question. We had internal discussion about the constness of label and id. As the pkcs11_generate_key() did not have the const decided not to add in here. But logically it would make library users life a bit easier if the signature would be:

extern int pkcs11_generate_ec_key(PKCS11_TOKEN * token, const char *curve,
	const char *label, const unsigned char* id, size_t id_len);

I understand that in the PKCS#11 world there is no concept of 'const' so from that design point of view it should be as what is now in the PR.


/* Get the RSA key modulus size (in bytes) */
extern int pkcs11_get_key_size(PKCS11_KEY *);

Expand Down
1 change: 1 addition & 0 deletions src/libp11.exports
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ PKCS11_init_token
PKCS11_init_pin
PKCS11_change_pin
PKCS11_generate_key
PKCS11_generate_ec_key
PKCS11_store_private_key
PKCS11_store_public_key
PKCS11_store_certificate
Expand Down
14 changes: 14 additions & 0 deletions src/libp11.h
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,20 @@ P11_DEPRECATED_FUNC extern int PKCS11_get_key_modulus(PKCS11_KEY *, BIGNUM **);
/* Get the RSA key public exponent as BIGNUM */
P11_DEPRECATED_FUNC extern int PKCS11_get_key_exponent(PKCS11_KEY *, BIGNUM **);

/**
* Generate a private EC key on the token
*
* @param token token returned by PKCS11_find_token()
* @param curve EC curve name
* @param label label for this key
* @param id bytes to use as the id value
* @param id_len length of the id value
* @retval 0 success
* @retval -1 error
*/
extern int PKCS11_generate_ec_key(PKCS11_TOKEN *token, const char *curve,
char *label, unsigned char* id, size_t id_len);

/* Sign with the EC private key */
P11_DEPRECATED_FUNC extern int PKCS11_ecdsa_sign(
const unsigned char *m, unsigned int m_len,
Expand Down
8 changes: 8 additions & 0 deletions src/p11_front.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,14 @@ int PKCS11_generate_key(PKCS11_TOKEN *token,
return pkcs11_generate_key(token, algorithm, bits, label, id, id_len);
}

int PKCS11_generate_ec_key(PKCS11_TOKEN *token, const char *curve,
char *label, unsigned char *id, size_t id_len)
{
if (check_token_fork(token) < 0)
return -1;
return pkcs11_generate_ec_key(token, curve, label, id, id_len);
}

int PKCS11_get_key_size(PKCS11_KEY *key)
{
if (check_key_fork(key) < 0)
Expand Down
92 changes: 92 additions & 0 deletions src/p11_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,98 @@ int pkcs11_generate_key(PKCS11_TOKEN *token, int algorithm, unsigned int bits,
return 0;
}

/**
* Generate a keyPair directly on token
*/
int pkcs11_generate_ec_key(PKCS11_TOKEN *token, const char *curve,
char *label, unsigned char* id, size_t id_len) {

PKCS11_SLOT *slot = TOKEN2SLOT(token);
PKCS11_CTX *ctx = TOKEN2CTX(token);
PKCS11_SLOT_private *spriv = PRIVSLOT(slot);

CK_ATTRIBUTE pubkey_attrs[32];
CK_ATTRIBUTE privkey_attrs[32];
unsigned int n_pub = 0, n_priv = 0;
CK_MECHANISM mechanism = {
CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0
};
CK_OBJECT_HANDLE pub_key_obj, priv_key_obj;
int rv;

unsigned char *ecdsa_params = NULL;
int ecdsa_params_len = 0;
unsigned char *tmp = NULL;
ASN1_OBJECT *curve_obj = NULL;
int curve_nid = NID_undef;

/* make sure we have a session */
if (!spriv->haveSession && PKCS11_open_session(slot, 1))
return -1;

curve_nid = EC_curve_nist2nid(curve);
if (curve_nid == NID_undef)
curve_nid = OBJ_sn2nid(curve);
if (curve_nid == NID_undef)
curve_nid = OBJ_ln2nid(curve);
if (curve_nid == NID_undef)
return -1;

curve_obj = OBJ_nid2obj(curve_nid);
if (!curve_obj)
return -1;
ecdsa_params_len = i2d_ASN1_OBJECT(curve_obj, NULL);
ecdsa_params = (unsigned char *)OPENSSL_malloc(ecdsa_params_len);
vesajaaskelainen marked this conversation as resolved.
Show resolved Hide resolved
if (!ecdsa_params)
return -1;
tmp = ecdsa_params;
i2d_ASN1_OBJECT(curve_obj, &tmp);

/* pubkey attributes */
pkcs11_addattr(pubkey_attrs + n_pub++, CKA_ID, id, id_len);
if (label)
pkcs11_addattr_s(pubkey_attrs + n_pub++, CKA_LABEL, label);
pkcs11_addattr_bool(pubkey_attrs + n_pub++, CKA_TOKEN, TRUE);
pkcs11_addattr_bool(pubkey_attrs + n_pub++, CKA_DERIVE, TRUE);
pkcs11_addattr_bool(pubkey_attrs + n_pub++, CKA_WRAP, FALSE);
pkcs11_addattr_bool(pubkey_attrs + n_pub++, CKA_VERIFY, TRUE);
pkcs11_addattr_bool(pubkey_attrs + n_pub++, CKA_VERIFY_RECOVER, FALSE);
pkcs11_addattr_bool(pubkey_attrs + n_pub++, CKA_ENCRYPT, FALSE);
pkcs11_addattr(pubkey_attrs + n_pub++, CKA_ECDSA_PARAMS, ecdsa_params, ecdsa_params_len);

/* privkey attributes */
pkcs11_addattr(privkey_attrs + n_priv++, CKA_ID, id, id_len);
if (label)
pkcs11_addattr_s(privkey_attrs + n_priv++, CKA_LABEL, label);
pkcs11_addattr_bool(privkey_attrs + n_priv++, CKA_TOKEN, TRUE);
pkcs11_addattr_bool(privkey_attrs + n_priv++, CKA_PRIVATE, TRUE);
pkcs11_addattr_bool(privkey_attrs + n_priv++, CKA_SENSITIVE, TRUE);
pkcs11_addattr_bool(privkey_attrs + n_priv++, CKA_DERIVE, TRUE);
pkcs11_addattr_bool(privkey_attrs + n_priv++, CKA_UNWRAP, FALSE);
pkcs11_addattr_bool(privkey_attrs + n_priv++, CKA_SIGN, TRUE);
pkcs11_addattr_bool(privkey_attrs + n_priv++, CKA_DECRYPT, FALSE);

/* call the pkcs11 module to create the key pair */
rv = CRYPTOKI_call(ctx, C_GenerateKeyPair(
spriv->session,
&mechanism,
pubkey_attrs,
n_pub,
privkey_attrs,
n_priv,
&pub_key_obj,
&priv_key_obj
));

/* zap all memory allocated when building the template */
pkcs11_zap_attrs(privkey_attrs, n_priv);
pkcs11_zap_attrs(pubkey_attrs, n_pub);
OPENSSL_free(ecdsa_params);

CRYPTOKI_checkerr(CKR_F_PKCS11_GENERATE_KEY, rv);
return 0;
}

/*
* Store a private key on the token
*/
Expand Down