[pkg-opensc-commit] [libp11] 29/67: Added PKCS11_enumerate_public_keys to the API
Eric Dorland
eric at moszumanska.debian.org
Sat Jan 30 05:34:14 UTC 2016
This is an automated email from the git hooks/post-receive script.
eric pushed a commit to branch master
in repository libp11.
commit 914e85046fb484cb8eba7b8476f3d073360c979c
Author: Michał Trojnara <Michal.Trojnara at stunnel.org>
Date: Sun Jan 3 19:56:58 2016 +0100
Added PKCS11_enumerate_public_keys to the API
---
NEWS | 4 +-
src/libp11-int.h | 25 ++--
src/libp11.exports | 1 +
src/libp11.h | 9 +-
src/p11_ec.c | 129 +++++++++-----------
src/p11_key.c | 344 ++++++++++++++++++++++++++++-------------------------
src/p11_misc.c | 2 +-
src/p11_rsa.c | 69 ++++-------
src/p11_slot.c | 20 +++-
9 files changed, 310 insertions(+), 293 deletions(-)
diff --git a/NEWS b/NEWS
index 292e1b8..a5e1800 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,10 @@
NEWS for Libp11 -- History of user visible changes
New in 0.3.1; unreleased;
+* Fixed EVP_PKEY handling of public keys (Michał Trojnara)
+* Added PKCS11_enumerate_public_keys to the API (Michał Trojnara)
* Added thread safety based on OpenSSL dynamic locks (Michał Trojnara)
-* Added PKCS11_is_logged_in to API (Mikhail Denisenko)
+* Added PKCS11_is_logged_in to the API (Mikhail Denisenko)
* Fixes in reinitialization after fork; addresses #39
(Michał Trojnara)
* MSVC build fixes (Michał Trojnara)
diff --git a/src/libp11-int.h b/src/libp11-int.h
index 494daec..9f44546 100644
--- a/src/libp11-int.h
+++ b/src/libp11-int.h
@@ -46,7 +46,7 @@ typedef struct pkcs11_ctx_private {
unsigned int forkid;
int lockid;
} PKCS11_CTX_private;
-#define PRIVCTX(ctx) ((PKCS11_CTX_private *) (ctx->_private))
+#define PRIVCTX(ctx) ((PKCS11_CTX_private *) ((ctx)->_private))
int check_fork(PKCS11_CTX *);
#define CHECK_FORK(ctx) if (check_fork(ctx) < 0) return -1
@@ -66,7 +66,7 @@ typedef struct pkcs11_slot_private {
/* per-slot lock */
int lockid;
} PKCS11_SLOT_private;
-#define PRIVSLOT(slot) ((PKCS11_SLOT_private *) (slot->_private))
+#define PRIVSLOT(slot) ((PKCS11_SLOT_private *) ((slot)->_private))
#define SLOT2CTX(slot) (PRIVSLOT(slot)->parent)
int check_slot_fork(PKCS11_SLOT *);
@@ -75,21 +75,24 @@ int check_slot_fork(PKCS11_SLOT *);
int check_key_fork(PKCS11_KEY *);
#define CHECK_KEY_FORK(key) if (check_key_fork(key) < 0) return -1
+typedef struct pkcs11_keys {
+ int num;
+ PKCS11_KEY *keys;
+} PKCS11_keys;
+
typedef struct pkcs11_token_private {
PKCS11_SLOT *parent;
- int nkeys, nprkeys;
- PKCS11_KEY *keys;
+ PKCS11_keys prv, pub;
int ncerts;
PKCS11_CERT *certs;
} PKCS11_TOKEN_private;
-#define PRIVTOKEN(token) ((PKCS11_TOKEN_private *) (token->_private))
+#define PRIVTOKEN(token) ((PKCS11_TOKEN_private *) ((token)->_private))
#define TOKEN2SLOT(token) (PRIVTOKEN(token)->parent)
#define TOKEN2CTX(token) SLOT2CTX(TOKEN2SLOT(token))
typedef struct pkcs11_key_ops {
int type; /* EVP_PKEY_xxx */
- int (*get_public) (PKCS11_KEY *, EVP_PKEY *);
- int (*get_private) (PKCS11_KEY *, EVP_PKEY *);
+ EVP_PKEY *(*get_evp_key) (PKCS11_KEY *);
} PKCS11_KEY_ops;
typedef struct pkcs11_key_private {
@@ -100,7 +103,7 @@ typedef struct pkcs11_key_private {
PKCS11_KEY_ops *ops;
unsigned int forkid;
} PKCS11_KEY_private;
-#define PRIVKEY(key) ((PKCS11_KEY_private *) key->_private)
+#define PRIVKEY(key) ((PKCS11_KEY_private *) (key)->_private)
#define KEY2SLOT(key) TOKEN2SLOT(KEY2TOKEN(key))
#define KEY2TOKEN(key) (PRIVKEY(key)->parent)
#define KEY2CTX(key) TOKEN2CTX(KEY2TOKEN(key))
@@ -111,7 +114,7 @@ typedef struct pkcs11_cert_private {
unsigned char id[255];
size_t id_len;
} PKCS11_CERT_private;
-#define PRIVCERT(cert) ((PKCS11_CERT_private *) cert->_private)
+#define PRIVCERT(cert) ((PKCS11_CERT_private *) (cert)->_private)
#define CERT2SLOT(cert) TOKEN2SLOT(CERT2TOKEN(cert))
#define CERT2TOKEN(cert) (PRIVCERT(cert)->parent)
#define CERT2CTX(cert) TOKEN2CTX(CERT2TOKEN(cert))
@@ -148,7 +151,7 @@ typedef struct pkcs11_cert_private {
extern int pkcs11_enumerate_slots(PKCS11_CTX *, PKCS11_SLOT **, unsigned int *);
extern void pkcs11_release_slot(PKCS11_CTX *, PKCS11_SLOT *slot);
-extern void pkcs11_destroy_keys(PKCS11_TOKEN *);
+extern void pkcs11_destroy_keys(PKCS11_TOKEN *, unsigned int);
extern void pkcs11_destroy_certs(PKCS11_TOKEN *);
extern void *pkcs11_malloc(size_t);
extern char *pkcs11_strdup(char *, size_t);
@@ -162,7 +165,7 @@ extern int pkcs11_getattr_var(PKCS11_TOKEN *, CK_OBJECT_HANDLE,
extern int pkcs11_getattr_bn(PKCS11_TOKEN *, CK_OBJECT_HANDLE,
unsigned int, BIGNUM **);
-extern int pkcs11_reload_keys(PKCS11_KEY * keyin);
+extern int pkcs11_reload_key(PKCS11_KEY *);
#define key_getattr(key, t, p, s) \
pkcs11_getattr(KEY2TOKEN((key)), PRIVKEY((key))->object, (t), (p), (s))
diff --git a/src/libp11.exports b/src/libp11.exports
index dc7b5d9..8b6bb67 100644
--- a/src/libp11.exports
+++ b/src/libp11.exports
@@ -11,6 +11,7 @@ PKCS11_is_logged_in
PKCS11_login
PKCS11_logout
PKCS11_enumerate_keys
+PKCS11_enumerate_public_keys
PKCS11_get_key_type
PKCS11_get_key_size
PKCS11_get_key_modulus
diff --git a/src/libp11.h b/src/libp11.h
index 355c6fd..c782a8f 100644
--- a/src/libp11.h
+++ b/src/libp11.h
@@ -238,8 +238,13 @@ extern int PKCS11_login(PKCS11_SLOT * slot, int so, const char *pin);
*/
extern int PKCS11_logout(PKCS11_SLOT * slot);
-/* Get a list of all keys associated with this token */
-extern int PKCS11_enumerate_keys(PKCS11_TOKEN *, PKCS11_KEY **, unsigned int *);
+/* Get a list of private keys associated with this token */
+extern int PKCS11_enumerate_keys(PKCS11_TOKEN *,
+ PKCS11_KEY **, unsigned int *);
+
+/* Get a list of public keys associated with this token */
+extern int PKCS11_enumerate_public_keys(PKCS11_TOKEN *,
+ PKCS11_KEY **, unsigned int *);
/* Get the key type (as EVP_PKEY_XXX) */
extern int PKCS11_get_key_type(PKCS11_KEY *);
diff --git a/src/p11_ec.c b/src/p11_ec.c
index f298da9..2a2b3ac 100644
--- a/src/p11_ec.c
+++ b/src/p11_ec.c
@@ -2,7 +2,7 @@
* Copyright (C) 2005 Olaf Kirch <okir at lst.de>
* Copyright (C) 2011, 2013 Douglas E. Engert <deengert at anl.gov>
* Copyright (C) 2014 Douglas E. Engert <deengert at gmail.com>
-
+ * Copyright (C) 2016 Michał Trojnara <Michal.Trojnara at stunnel.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -84,22 +84,20 @@
#include "libp11-int.h"
-static int pkcs11_get_ec_public(PKCS11_KEY *, EVP_PKEY *);
-static int pkcs11_get_ec_private(PKCS11_KEY *, EVP_PKEY *);
-
static ECDSA_METHOD *ops = NULL;
/*
- * Get EC key material and stach pointer in ex_data
+ * Get EC key material and stash pointer in ex_data
* Note we get called twice, once for private key, and once for public
* We need to get the EC_PARAMS and EC_POINT into both,
* as lib11 dates from RSA only where all the pub key components
- * were also part of the privite key. With EC the point
- * is not in the privite key, and the params may or may not be.
+ * were also part of the private key. With EC the point
+ * is not in the private key, and the params may or may not be.
*
*/
-static int pkcs11_get_ec_private(PKCS11_KEY * key, EVP_PKEY * pk)
+static EVP_PKEY *pkcs11_get_evp_key_ec(PKCS11_KEY * key)
{
+ EVP_PKEY *pk;
CK_BBOOL sensitive, extractable;
EC_KEY * ec = NULL;
CK_RV ckrv;
@@ -107,58 +105,51 @@ static int pkcs11_get_ec_private(PKCS11_KEY * key, EVP_PKEY * pk)
CK_BYTE * ec_params = NULL;
size_t ec_pointlen = 0;
CK_BYTE * ec_point = NULL;
- PKCS11_KEY * prkey;
PKCS11_KEY * pubkey;
ASN1_OCTET_STRING *os=NULL;
- if (key->isPrivate) { /* Are we being called for the prive or pub key */
- prkey = key;
- pubkey = PKCS11_find_key_from_key(key);
- } else {
- pubkey = key;
- prkey = PKCS11_find_key_from_key(key);
+ pk = EVP_PKEY_new();
+ if (pk == NULL)
+ return NULL;
+
+ ec = EC_KEY_new();
+ if (ec == NULL) {
+ EVP_PKEY_free(pk);
+ return NULL;
}
+ EVP_PKEY_set1_EC_KEY(pk, ec); /* Also increments the ec ref count */
- if (pk->type == EVP_PKEY_EC) {
- ec = EVP_PKEY_get1_EC_KEY(pk);
- } else {
- ec = EC_KEY_new();
- EVP_PKEY_set1_EC_KEY(pk, ec);
+ if (key_getattr(key, CKA_SENSITIVE, &sensitive, sizeof(sensitive))
+ || key_getattr(key, CKA_EXTRACTABLE, &extractable, sizeof(extractable))) {
+ EVP_PKEY_free(pk);
+ EC_KEY_free(ec);
+ return NULL;
}
- /* After above ec has ref count incremented. */
- if (prkey) {
- if (key_getattr(prkey, CKA_SENSITIVE, &sensitive, sizeof(sensitive))
- || key_getattr(prkey, CKA_EXTRACTABLE, &extractable, sizeof(extractable))) {
- EC_KEY_free(ec);
- return -1;
- }
+ /* For Openssl req we need at least the
+ * EC_KEY_get0_group(ec_key)) to return the group.
+ * Even if it fails will continue as a sign only does not need
+ * need this if the pkcs11 or card can figure this out.
+ */
- /* For Openssl req we need at least the
- * EC_KEY_get0_group(ec_key)) to return the group.
- * Even if it fails will continue as a sign only does not need
- * need this if the pkcs11 or card can figure this out.
- */
-
- if (key_getattr_var(prkey, CKA_EC_PARAMS, NULL, &ec_paramslen) == CKR_OK &&
- ec_paramslen > 0) {
- ec_params = OPENSSL_malloc(ec_paramslen);
- if (ec_params) {
- ckrv = key_getattr_var(prkey, CKA_EC_PARAMS, ec_params, &ec_paramslen);
- if (ckrv == CKR_OK) {
- const unsigned char * a = ec_params;
- /* convert to OpenSSL parmas */
- d2i_ECParameters(&ec, &a, ec_paramslen);
- }
- }
+ if (key_getattr_var(key, CKA_EC_PARAMS, NULL, &ec_paramslen) == CKR_OK &&
+ ec_paramslen > 0) {
+ ec_params = OPENSSL_malloc(ec_paramslen);
+ if (ec_params) {
+ ckrv = key_getattr_var(key, CKA_EC_PARAMS, ec_params, &ec_paramslen);
+ if (ckrv == CKR_OK) {
+ const unsigned char * a = ec_params;
+ /* convert to OpenSSL parmas */
+ d2i_ECParameters(&ec, &a, ec_paramslen);
+ }
}
}
/* Now get the ec_point */
-
+ pubkey = key->isPrivate ? PKCS11_find_key_from_key(key) : key;
if (pubkey) {
- if (key_getattr_var(pubkey, CKA_EC_POINT, NULL, &ec_pointlen) == CKR_OK &&
- ec_pointlen > 0) {
+ ckrv = key_getattr_var(pubkey, CKA_EC_POINT, NULL, &ec_pointlen);
+ if (ckrv == CKR_OK && ec_pointlen > 0) {
ec_point = OPENSSL_malloc(ec_pointlen);
if (ec_point) {
ckrv = key_getattr_var(pubkey, CKA_EC_POINT, ec_point, &ec_pointlen);
@@ -183,34 +174,29 @@ static int pkcs11_get_ec_private(PKCS11_KEY * key, EVP_PKEY * pk)
* that will use the card's functions to sign & decrypt
*/
if (os)
- M_ASN1_OCTET_STRING_free(os);
+ M_ASN1_OCTET_STRING_free(os);
if (ec_point)
OPENSSL_free(ec_point);
if (ec_params)
OPENSSL_free(ec_params);
if (sensitive || !extractable) {
- ECDSA_set_ex_data(ec, 0, key);
- EC_KEY_free(ec); /* drops our reference to it. */
- return 0;
+ ECDSA_set_method(ec, PKCS11_get_ecdsa_method());
+ } else if (key->isPrivate) {
+ /* TODO: Extract the ECDSA private key */
+ /* In the meantime lets use the card anyway */
+ ECDSA_set_method(ec, PKCS11_get_ecdsa_method());
}
- if (ec)
- EC_KEY_free(ec);
- return -1;
-}
-
-static int pkcs11_get_ec_public(PKCS11_KEY * key, EVP_PKEY * pk)
-{
- /* TBD */
- return pkcs11_get_ec_private(key, pk);
+ ECDSA_set_ex_data(ec, 0, key);
+ EC_KEY_free(ec); /* drops our reference to it */
+ return pk;
}
/* TODO Looks like this is never called */
static int pkcs11_ecdsa_sign_setup(EC_KEY *ec, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp) {
-
if (*kinvp != NULL)
BN_clear_free(*kinvp);
*kinvp = BN_new();
@@ -256,7 +242,7 @@ static ECDSA_SIG * pkcs11_ecdsa_do_sign(const unsigned char *dgst, int dlen,
*/
#if !defined(LIBP11_BUILD_WITH_ECS_LOCL_H)
-/* New way to allocate a ECDSA_METOD... */
+/* New way to allocate an ECDSA_METOD object */
ECDSA_METHOD *PKCS11_get_ecdsa_method(void)
{
@@ -276,9 +262,9 @@ void PKCS11_ecdsa_method_free(void)
}
}
-#else
+#else /* LIBP11_BUILD_WITH_ECS_LOCL_H */
-/* old way using ecs_locl.h */
+/* Old way using ecs_locl.h */
ECDSA_METHOD *PKCS11_get_ecdsa_method(void)
{
static struct ecdsa_method sops;
@@ -294,14 +280,14 @@ ECDSA_METHOD *PKCS11_get_ecdsa_method(void)
void PKCS11_ecdsa_method_free(void)
{
- /* in old method it is static */
+ /* It is static in the old method */
}
-#endif
+
+#endif /* LIBP11_BUILD_WITH_ECS_LOCL_H */
PKCS11_KEY_ops pkcs11_ec_ops_s = {
EVP_PKEY_EC,
- pkcs11_get_ec_public,
- pkcs11_get_ec_private
+ pkcs11_get_evp_key_ec
};
PKCS11_KEY_ops *pkcs11_ec_ops = {&pkcs11_ec_ops_s};
@@ -313,12 +299,15 @@ void *pkcs11_ec_ops = {NULL};
* add these routines so engine_pkcs11 can be built now and not
* require further changes */
#warning "ECDSA support not built with libp11"
+
void * PKCS11_get_ecdsa_method(void)
{
return NULL;
}
+
void PKCS11_ecdsa_method_free(void)
{
- /* no op, as it is static in old code. */
+ /* no op, as it is static in the old code */
}
-#endif /* OPENSSL_NO_EC */
+
+#endif /* LIBP11_BUILD_WITHOUT_ECDSA */
diff --git a/src/p11_key.c b/src/p11_key.c
index 416a438..626e89b 100644
--- a/src/p11_key.c
+++ b/src/p11_key.c
@@ -1,5 +1,6 @@
/* libp11, a simple layer on to of PKCS#11 API
* Copyright (C) 2005 Olaf Kirch <okir at lst.de>
+ * Copyright (C) 2016 Michał Trojnara <Michal.Trojnara at stunnel.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,47 +25,37 @@
#define strncasecmp strnicmp
#endif
+static int pkcs11_enumerate_keys(PKCS11_TOKEN *, unsigned int,
+ PKCS11_KEY **, unsigned int *);
static int pkcs11_find_keys(PKCS11_TOKEN *, unsigned int);
static int pkcs11_next_key(PKCS11_CTX * ctx, PKCS11_TOKEN * token,
- CK_SESSION_HANDLE session, CK_OBJECT_CLASS type);
+ CK_SESSION_HANDLE session, CK_OBJECT_CLASS type);
static int pkcs11_init_key(PKCS11_CTX * ctx, PKCS11_TOKEN * token,
- CK_SESSION_HANDLE session, CK_OBJECT_HANDLE o,
- CK_OBJECT_CLASS type, PKCS11_KEY **);
+ CK_SESSION_HANDLE session, CK_OBJECT_HANDLE o,
+ CK_OBJECT_CLASS type, PKCS11_KEY **);
static int pkcs11_store_private_key(PKCS11_TOKEN *, EVP_PKEY *, char *,
- unsigned char *, size_t, PKCS11_KEY **);
+ unsigned char *, size_t, PKCS11_KEY **);
static int pkcs11_store_public_key(PKCS11_TOKEN *, EVP_PKEY *, char *,
- unsigned char *, size_t, PKCS11_KEY **);
-
-static CK_OBJECT_CLASS key_search_class;
-static CK_ATTRIBUTE key_search_attrs[] = {
- {CKA_CLASS, &key_search_class, sizeof(key_search_class)},
-};
-#define numof(arr) (sizeof(arr)/sizeof((arr)[0]))
+ unsigned char *, size_t, PKCS11_KEY **);
/*
- * Enumerate all keys on the card
- * For now, we enumerate just the private keys.
+ * Enumerate private keys on the card
*/
int
-PKCS11_enumerate_keys(PKCS11_TOKEN * token, PKCS11_KEY ** keyp, unsigned int *countp)
+PKCS11_enumerate_keys(PKCS11_TOKEN * token,
+ PKCS11_KEY ** keyp, unsigned int *countp)
{
- PKCS11_TOKEN_private *priv = PRIVTOKEN(token);
+ return pkcs11_enumerate_keys(token, CKO_PRIVATE_KEY, keyp, countp);
+}
- if (priv->nkeys < 0) {
- priv->nkeys = 0;
- if (pkcs11_find_keys(token, CKO_PRIVATE_KEY)) {
- pkcs11_destroy_keys(token);
- return -1;
- }
- priv->nprkeys = priv->nkeys;
- if (pkcs11_find_keys(token, CKO_PUBLIC_KEY)) {
- pkcs11_destroy_keys(token);
- return -1;
- }
- }
- *keyp = priv->keys;
- *countp = priv->nprkeys;
- return 0;
+/*
+ * Enumerate private keys on the card
+ */
+int
+PKCS11_enumerate_public_keys(PKCS11_TOKEN * token,
+ PKCS11_KEY ** keyp, unsigned int *countp)
+{
+ return pkcs11_enumerate_keys(token, CKO_PUBLIC_KEY, keyp, countp);
}
/*
@@ -72,21 +63,21 @@ PKCS11_enumerate_keys(PKCS11_TOKEN * token, PKCS11_KEY ** keyp, unsigned int *co
*/
PKCS11_KEY *PKCS11_find_key(PKCS11_CERT *cert)
{
- PKCS11_CERT_private *cpriv;
- PKCS11_KEY_private *kpriv;
- PKCS11_KEY *key;
- unsigned int n, count;
+ PKCS11_CERT_private *cpriv;
+ PKCS11_KEY_private *kpriv;
+ PKCS11_KEY *keys;
+ unsigned int n, count;
cpriv = PRIVCERT(cert);
- if (PKCS11_enumerate_keys(CERT2TOKEN(cert), &key, &count))
- return NULL;
- for (n = 0; n < count; n++, key++) {
- kpriv = PRIVKEY(key);
- if (cpriv->id_len == kpriv->id_len
- && !memcmp(cpriv->id, kpriv->id, cpriv->id_len))
- return key;
- }
- return NULL;
+ if (PKCS11_enumerate_keys(CERT2TOKEN(cert), &keys, &count))
+ return NULL;
+ for (n = 0; n < count; n++) {
+ kpriv = PRIVKEY(&keys[n]);
+ if (cpriv->id_len == kpriv->id_len
+ && !memcmp(cpriv->id, kpriv->id, cpriv->id_len))
+ return &keys[n];
+ }
+ return NULL;
}
/*
@@ -94,82 +85,68 @@ PKCS11_KEY *PKCS11_find_key(PKCS11_CERT *cert)
*/
PKCS11_KEY *PKCS11_find_key_from_key(PKCS11_KEY * keyin)
{
- PKCS11_TOKEN_private *tpriv;
- PKCS11_KEY_private *kinpriv;
- PKCS11_KEY_private *kpriv;
- PKCS11_KEY *key;
- unsigned int n, count;
-
- kinpriv = PRIVKEY(keyin);
- tpriv = PRIVTOKEN(KEY2TOKEN(keyin));
- PKCS11_enumerate_keys(KEY2TOKEN(keyin), &key, &count);
- /* We want to use all the keys, the above only returns count for private */
- count = tpriv->nkeys;
- if (count < 2) /* must be at least two key to have a match */
- return NULL;
- for (n = 0; n < count; n++, key++) {
- kpriv = PRIVKEY(key);
- if (keyin->isPrivate != key->isPrivate
- && kinpriv->id_len == kpriv->id_len
- && !memcmp(kinpriv->id, kpriv->id, kinpriv->id_len))
- return key;
- }
- return NULL;
+ PKCS11_KEY_private *kinpriv = PRIVKEY(keyin);
+ PKCS11_KEY *keys;
+ unsigned int n, count;
+
+ pkcs11_enumerate_keys(KEY2TOKEN(keyin),
+ keyin->isPrivate ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY, /* other type */
+ &keys, &count);
+ for (n = 0; n < count; n++) {
+ PKCS11_KEY_private *kpriv = PRIVKEY(&keys[n]);
+ if (kinpriv->id_len == kpriv->id_len
+ && !memcmp(kinpriv->id, kpriv->id, kinpriv->id_len))
+ return &keys[n];
+ }
+ return NULL;
}
-/* Reopens the object associated with the key
+/*
+ * Reopens the object associated with the key
*/
-int pkcs11_reload_keys(PKCS11_KEY * keyin)
+int pkcs11_reload_key(PKCS11_KEY * key)
{
- PKCS11_TOKEN_private *tpriv;
- PKCS11_KEY_private *kinpriv;
- unsigned long count, n;
- CK_OBJECT_CLASS kclass = CKO_PRIVATE_KEY;
- CK_ATTRIBUTE attrs[2];
- int rv;
- PKCS11_CTX *ctx;
- PKCS11_SLOT *slot;
-
- kinpriv = PRIVKEY(keyin);
- tpriv = PRIVTOKEN(KEY2TOKEN(keyin));
- ctx = TOKEN2CTX(KEY2TOKEN(keyin));
- slot = TOKEN2SLOT(KEY2TOKEN(keyin));
-
- /* We want to use all the keys, the above only returns count for private */
- count = tpriv->nkeys;
-
- for (n = 0; n < count; n++) {
- attrs[0].type = CKA_CLASS;
- attrs[0].pValue = &kclass;
- attrs[0].ulValueLen = sizeof(kclass);
- attrs[1].type = CKA_ID;
- attrs[1].pValue = kinpriv->id;
- attrs[1].ulValueLen = kinpriv->id_len;
-
- rv = CRYPTOKI_call(ctx, C_FindObjectsInit(PRIVSLOT(slot)->session, attrs, 2));
- CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);
-
- rv = CRYPTOKI_call(ctx, C_FindObjects(PRIVSLOT(slot)->session, &kinpriv->object, 1, &count));
- CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);
-
- CRYPTOKI_call(ctx, C_FindObjectsFinal(PRIVSLOT(slot)->session));
-
- kinpriv->forkid = _P11_get_forkid();
- }
- return 0;
+ PKCS11_KEY_private *kpriv = PRIVKEY(key);
+ PKCS11_SLOT *slot = KEY2SLOT(key);
+ PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
+ PKCS11_CTX *ctx = SLOT2CTX(slot);
+ CK_OBJECT_CLASS key_search_class =
+ key->isPrivate ? CKO_PRIVATE_KEY : CKO_PUBLIC_KEY;
+ CK_ATTRIBUTE key_search_attrs[2] = {
+ {CKA_CLASS, &key_search_class, sizeof(key_search_class)},
+ {CKA_ID, kpriv->id, kpriv->id_len},
+ };
+ CK_ULONG count;
+ int rv;
+
+ /* this is already covered with a per-ctx lock */
+
+ rv = CRYPTOKI_call(ctx,
+ C_FindObjectsInit(spriv->session, key_search_attrs, 2));
+ CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);
+
+ rv = CRYPTOKI_call(ctx,
+ C_FindObjects(spriv->session, &kpriv->object, 1, &count));
+ CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);
+
+ CRYPTOKI_call(ctx, C_FindObjectsFinal(spriv->session));
+
+ return 0;
}
/*
* Store a private key on the token
*/
-int PKCS11_store_private_key(PKCS11_TOKEN * token, EVP_PKEY * pk, char *label, unsigned char *id, size_t id_len)
+int PKCS11_store_private_key(PKCS11_TOKEN * token, EVP_PKEY * pk, char *label,
+ unsigned char *id, size_t id_len)
{
if (pkcs11_store_private_key(token, pk, label, id, id_len, NULL))
return -1;
return 0;
}
-int PKCS11_store_public_key(PKCS11_TOKEN * token, EVP_PKEY * pk, char *label, unsigned char *id, size_t id_len)
+int PKCS11_store_public_key(PKCS11_TOKEN * token, EVP_PKEY * pk, char *label,
+ unsigned char *id, size_t id_len)
{
if (pkcs11_store_public_key(token, pk, label, id, id_len, NULL))
return -1;
@@ -182,8 +159,8 @@ int PKCS11_store_public_key(PKCS11_TOKEN * token, EVP_PKEY * pk, char *label, un
* on-board key generation, and if it does, use its own algorithm
*/
int
-PKCS11_generate_key(PKCS11_TOKEN * token,
- int algorithm, unsigned int bits, char *label, unsigned char* id, size_t id_len)
+PKCS11_generate_key(PKCS11_TOKEN * token, int algorithm, unsigned int bits,
+ char *label, unsigned char* id, size_t id_len)
{
PKCS11_KEY *key_obj;
EVP_PKEY *pk;
@@ -213,7 +190,7 @@ PKCS11_generate_key(PKCS11_TOKEN * token,
kpriv = PRIVKEY(key_obj);
rc = pkcs11_store_public_key(token, pk, label,
- kpriv->id, kpriv->id_len, NULL);
+ kpriv->id, kpriv->id_len, NULL);
}
EVP_PKEY_free(pk);
return rc;
@@ -224,66 +201,115 @@ PKCS11_generate_key(PKCS11_TOKEN * token,
*/
int PKCS11_get_key_type(PKCS11_KEY * key)
{
- PKCS11_KEY_private *priv = PRIVKEY(key);
+ PKCS11_KEY_private *kpriv = PRIVKEY(key);
- return priv->ops->type;
+ return kpriv->ops->type;
}
/*
- * Create a key object that will allow an OpenSSL application
- * to use the token via an EVP_PKEY
+ * Create an EVP_PKEY OpenSSL object for a given key
+ * Returns either private or public key object depending on the isPrivate
+ * value for compatibility with a bug in engine_pkcs11 <= 0.2.0
+ * TODO: Fix this when the affected engine_pkcs11 is phased out
*/
EVP_PKEY *PKCS11_get_private_key(PKCS11_KEY * key)
{
- PKCS11_KEY_private *priv = PRIVKEY(key);
+ PKCS11_KEY_private *kpriv;
+ if (key == NULL)
+ return NULL;
if (key->evp_key == NULL) {
- EVP_PKEY *pk = EVP_PKEY_new();
- if (pk == NULL)
- return NULL;
- if (priv->ops->get_private(key, pk)
- || priv->ops->get_public(key, pk)) {
- EVP_PKEY_free(pk);
- return NULL;
- }
- key->evp_key = pk;
+ kpriv = PRIVKEY(key);
+ key->evp_key = kpriv->ops->get_evp_key(key);
}
-
return key->evp_key;
}
+/*
+ * Create an EVP_PKEY OpenSSL object for a given key
+ * Always returns the public key object
+ */
EVP_PKEY *PKCS11_get_public_key(PKCS11_KEY * key)
{
- return PKCS11_get_private_key(key);
+ PKCS11_KEY_private *kpriv;
+
+ if (key == NULL)
+ return NULL;
+ if (key->isPrivate) {
+ key = PKCS11_find_key_from_key(key);
+ if (key == NULL)
+ return NULL;
+ }
+ if (key->evp_key == NULL) {
+ kpriv = PRIVKEY(key);
+ key->evp_key = kpriv->ops->get_evp_key(key);
+ }
+ return key->evp_key;
}
+/*
+ * Return keys of a given type (public or private)
+ * Use the cached values if available
+ */
+static int pkcs11_enumerate_keys(PKCS11_TOKEN * token, unsigned int type,
+ PKCS11_KEY ** keyp, unsigned int * countp)
+{
+ PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
+ PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub;
+ PKCS11_CTX *ctx = TOKEN2CTX(token);
+ PKCS11_CTX_private *cpriv = PRIVCTX(ctx);
+ int rv;
+
+ if (keys->num < 0) { /* No cache was built for the specified type */
+ CRYPTO_w_lock(cpriv->lockid);
+ rv = pkcs11_find_keys(token, type);
+ CRYPTO_w_unlock(cpriv->lockid);
+ if (rv < 0) {
+ pkcs11_destroy_keys(token, type);
+ return -1;
+ }
+ }
+ if(keyp)
+ *keyp = keys->keys;
+ if(countp)
+ *countp = keys->num;
+ return 0;
+}
/*
* Find all keys of a given type (public or private)
*/
static int pkcs11_find_keys(PKCS11_TOKEN * token, unsigned int type)
{
+ PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
+ PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub;
+ CK_OBJECT_CLASS key_search_class;
+ CK_ATTRIBUTE key_search_attrs[1] = {
+ {CKA_CLASS, &key_search_class, sizeof(key_search_class)},
+ };
+
PKCS11_SLOT *slot = TOKEN2SLOT(token);
+ PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
PKCS11_CTX *ctx = TOKEN2CTX(token);
- CK_SESSION_HANDLE session;
int rv, res = -1;
/* Make sure we have a session */
if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 0))
return -1;
- session = PRIVSLOT(slot)->session;
/* Tell the PKCS11 lib to enumerate all matching objects */
key_search_class = type;
- rv = CRYPTOKI_call(ctx, C_FindObjectsInit(session, key_search_attrs,
- numof(key_search_attrs)));
+ rv = CRYPTOKI_call(ctx,
+ C_FindObjectsInit(spriv->session, key_search_attrs, 1));
CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);
+ keys->num = 0;
do {
- res = pkcs11_next_key(ctx, token, session, type);
+ res = pkcs11_next_key(ctx, token, spriv->session, type);
} while (res == 0);
- CRYPTOKI_call(ctx, C_FindObjectsFinal(session));
+ CRYPTOKI_call(ctx, C_FindObjectsFinal(spriv->session));
+
return (res < 0) ? -1 : 0;
}
@@ -311,7 +337,8 @@ static int pkcs11_init_key(PKCS11_CTX * ctx, PKCS11_TOKEN * token,
CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj,
CK_OBJECT_CLASS type, PKCS11_KEY ** ret)
{
- PKCS11_TOKEN_private *tpriv;
+ PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
+ PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub;
PKCS11_KEY_private *kpriv;
PKCS11_KEY *key, *tmp;
char label[256];
@@ -335,24 +362,23 @@ static int pkcs11_init_key(PKCS11_CTX * ctx, PKCS11_TOKEN * token,
case CKK_EC:
ops = pkcs11_ec_ops;
if (ops == NULL)
- return 0; /* not supported */
+ return 0; /* not supported */
break;
default:
/* Ignore any keys we don't understand */
return 0;
}
- tpriv = PRIVTOKEN(token);
- tmp = (PKCS11_KEY *) OPENSSL_realloc(tpriv->keys,
- (tpriv->nkeys + 1) * sizeof(PKCS11_KEY));
+ tmp = (PKCS11_KEY *) OPENSSL_realloc(keys->keys,
+ (keys->num + 1) * sizeof(PKCS11_KEY));
if (!tmp) {
- free(tpriv->keys);
- tpriv->keys = NULL;
+ free(keys->keys);
+ keys->keys = NULL;
return -1;
}
- tpriv->keys = tmp;
+ keys->keys = tmp;
- key = tpriv->keys + tpriv->nkeys++;
+ key = keys->keys + keys->num++;
memset(key, 0, sizeof(*key));
key->_private = kpriv = PKCS11_NEW(PKCS11_KEY_private);
kpriv->object = obj;
@@ -380,14 +406,15 @@ static int pkcs11_init_key(PKCS11_CTX * ctx, PKCS11_TOKEN * token,
}
/*
- * Destroy all keys
+ * Destroy all keys of a given type (public or private)
*/
-void pkcs11_destroy_keys(PKCS11_TOKEN * token)
+void pkcs11_destroy_keys(PKCS11_TOKEN * token, unsigned int type)
{
- PKCS11_TOKEN_private *priv = PRIVTOKEN(token);
+ PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
+ PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub;
- while (priv->nkeys > 0) {
- PKCS11_KEY *key = &priv->keys[--(priv->nkeys)];
+ while (keys->num > 0) {
+ PKCS11_KEY *key = &keys->keys[--(keys->num)];
if (key->evp_key)
EVP_PKEY_free(key->evp_key);
@@ -397,11 +424,10 @@ void pkcs11_destroy_keys(PKCS11_TOKEN * token)
if (key->_private != NULL)
OPENSSL_free(key->_private);
}
- if (priv->keys)
- OPENSSL_free(priv->keys);
- priv->nprkeys = -1;
- priv->nkeys = -1;
- priv->keys = NULL;
+ if (keys->keys)
+ OPENSSL_free(keys->keys);
+ keys->keys = NULL;
+ keys->num = -1;
}
/*
@@ -466,7 +492,7 @@ static int pkcs11_store_private_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
/* Gobble the key object */
return pkcs11_init_key(ctx, token, session, object,
- CKO_PRIVATE_KEY, ret_key);
+ CKO_PRIVATE_KEY, ret_key);
}
/*
@@ -523,28 +549,28 @@ static int pkcs11_store_public_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
CRYPTOKI_checkerr(PKCS11_F_PKCS11_STORE_PUBLIC_KEY, rv);
/* Gobble the key object */
- return pkcs11_init_key(ctx, token, session, object, CKO_PUBLIC_KEY, ret_key);
+ return pkcs11_init_key(ctx, token, session, object,
+ CKO_PUBLIC_KEY, ret_key);
}
-int PKCS11_get_key_modulus(PKCS11_KEY * key, BIGNUM **bn)
+int PKCS11_get_key_modulus(PKCS11_KEY * key, BIGNUM **bn)
{
-
- if (pkcs11_getattr_bn(KEY2TOKEN(key), PRIVKEY(key)->object, CKA_MODULUS, bn))
+ if (pkcs11_getattr_bn(KEY2TOKEN(key), PRIVKEY(key)->object,
+ CKA_MODULUS, bn))
return 0;
return 1;
}
-int PKCS11_get_key_exponent(PKCS11_KEY * key, BIGNUM **bn)
+int PKCS11_get_key_exponent(PKCS11_KEY * key, BIGNUM **bn)
{
-
- if (pkcs11_getattr_bn(KEY2TOKEN(key), PRIVKEY(key)->object, CKA_PUBLIC_EXPONENT, bn))
+ if (pkcs11_getattr_bn(KEY2TOKEN(key), PRIVKEY(key)->object,
+ CKA_PUBLIC_EXPONENT, bn))
return 0;
return 1;
}
-
-int PKCS11_get_key_size(const PKCS11_KEY * key)
+int PKCS11_get_key_size(const PKCS11_KEY * key)
{
BIGNUM* n = NULL;
- int numbytes = 0;
+ int numbytes = 0;
if(key_getattr_bn(key, CKA_MODULUS, &n))
return 0;
numbytes = BN_num_bytes(n);
diff --git a/src/p11_misc.c b/src/p11_misc.c
index ccd48e2..2f57d0a 100644
--- a/src/p11_misc.c
+++ b/src/p11_misc.c
@@ -124,7 +124,7 @@ static int check_key_fork_int(PKCS11_KEY *key)
if (check_slot_fork_int(slot) < 0)
return -1;
if (spriv->forkid != priv->forkid) {
- pkcs11_reload_keys(key);
+ pkcs11_reload_key(key);
priv->forkid = spriv->forkid;
}
return 0;
diff --git a/src/p11_rsa.c b/src/p11_rsa.c
index 4a93af0..dbe1b48 100644
--- a/src/p11_rsa.c
+++ b/src/p11_rsa.c
@@ -1,5 +1,6 @@
/* libp11, a simple layer on to of PKCS#11 API
* Copyright (C) 2005 Olaf Kirch <okir at lst.de>
+ * Copyright (C) 2016 Michał Trojnara <Michal.Trojnara at stunnel.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,42 +28,46 @@
#include <openssl/rsa.h>
#include "libp11-int.h"
-static int pkcs11_get_rsa_public(PKCS11_KEY *, EVP_PKEY *);
-static int pkcs11_get_rsa_private(PKCS11_KEY *, EVP_PKEY *);
-
-
/*
* Get RSA key material
*/
-static int pkcs11_get_rsa_private(PKCS11_KEY * key, EVP_PKEY * pk)
+static EVP_PKEY *pkcs11_get_evp_key_rsa(PKCS11_KEY * key)
{
+ EVP_PKEY *pk;
CK_BBOOL sensitive, extractable;
RSA *rsa;
- if (!(rsa = EVP_PKEY_get1_RSA(pk))) {
- ERR_clear_error(); /* the above flags an error */
- rsa = RSA_new();
- EVP_PKEY_set1_RSA(pk, rsa);
+ pk = EVP_PKEY_new();
+ if (pk == NULL)
+ return NULL;
+
+ rsa = RSA_new();
+ if (rsa == NULL) {
+ EVP_PKEY_free(pk);
+ return NULL;
}
+ EVP_PKEY_set1_RSA(pk, rsa); /* Also increments the rsa ref count */
if (key_getattr(key, CKA_SENSITIVE, &sensitive, sizeof(sensitive))
|| key_getattr(key, CKA_EXTRACTABLE, &extractable, sizeof(extractable))) {
+ EVP_PKEY_free(pk);
RSA_free(rsa);
- return -1;
+ return NULL;
}
if (key_getattr_bn(key, CKA_MODULUS, &rsa->n) ||
key_getattr_bn(key, CKA_PUBLIC_EXPONENT, &rsa->e)) {
+ EVP_PKEY_free(pk);
RSA_free(rsa);
- return -1;
+ return NULL;
}
if (BN_is_zero(rsa->e)) {
- PKCS11_TOKEN_private * token = PRIVTOKEN(KEY2TOKEN(key));
+ PKCS11_TOKEN_private * tpriv = PRIVTOKEN(KEY2TOKEN(key));
int ki;
BIGNUM* pubmod = NULL;
- for(ki = token->nprkeys; ki < token->nkeys; ki++) {
- PKCS11_KEY* pubkey = token->keys + ki;
+ for(ki = 0; ki < tpriv->pub.num; ki++) {
+ PKCS11_KEY* pubkey = &tpriv->pub.keys[ki];
if(key_getattr_bn(pubkey, CKA_MODULUS, &pubmod)) {
continue;
@@ -87,39 +92,18 @@ static int pkcs11_get_rsa_private(PKCS11_KEY * key, EVP_PKEY * pk)
* that will use the card's functions to sign & decrypt */
if (sensitive || !extractable) {
RSA_set_method(rsa, PKCS11_get_rsa_method());
- rsa->flags |= RSA_FLAG_SIGN_VER;
- RSA_set_app_data(rsa, key);
-
- RSA_free(rsa);
- return 0;
+ } else if (key->isPrivate) {
+ /* TODO: Extract the RSA private key */
+ /* In the meantime lets use the card anyway */
+ RSA_set_method(rsa, PKCS11_get_rsa_method());
}
- /* TBD - extract RSA private key. */
- /* In the mean time let's use the card anyway */
- RSA_set_method(rsa, PKCS11_get_rsa_method());
rsa->flags |= RSA_FLAG_SIGN_VER;
RSA_set_app_data(rsa, key);
-
- RSA_free(rsa);
-
- return 0;
- /*
- PKCS11err(PKCS11_F_PKCS11_GET_KEY, PKCS11_NOT_SUPPORTED);
- return -1;
- */
-}
-
-static int pkcs11_get_rsa_public(PKCS11_KEY * key, EVP_PKEY * pk)
-{
- (void)key;
- (void)pk;
-
- /* TBD */
- return 0;
-/* return pkcs11_get_rsa_private(key,pk);*/
+ RSA_free(rsa); /* drops our reference to it */
+ return pk;
}
-
static int pkcs11_rsa_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA * rsa, int padding)
{
@@ -182,6 +166,5 @@ RSA_METHOD *PKCS11_get_rsa_method(void)
PKCS11_KEY_ops pkcs11_rsa_ops = {
EVP_PKEY_RSA,
- pkcs11_get_rsa_public,
- pkcs11_get_rsa_private
+ pkcs11_get_evp_key_rsa
};
diff --git a/src/p11_slot.c b/src/p11_slot.c
index 2b85eb6..5f91f68 100644
--- a/src/p11_slot.c
+++ b/src/p11_slot.c
@@ -214,8 +214,10 @@ int pkcs11_login(PKCS11_SLOT * slot, int so, const char *pin, int relogin)
/* Calling PKCS11_login invalidates all cached
* keys we have */
- if (slot->token)
- pkcs11_destroy_keys(slot->token);
+ if (slot->token) {
+ pkcs11_destroy_keys(slot->token, CKO_PRIVATE_KEY);
+ pkcs11_destroy_keys(slot->token, CKO_PUBLIC_KEY);
+ }
if (priv->loggedIn) {
/* already logged in, log out first */
if (PKCS11_logout(slot))
@@ -278,8 +280,10 @@ int PKCS11_logout(PKCS11_SLOT * slot)
/* Calling PKCS11_logout invalidates all cached
* keys we have */
- if (slot->token)
- pkcs11_destroy_keys(slot->token);
+ if (slot->token) {
+ pkcs11_destroy_keys(slot->token, CKO_PRIVATE_KEY);
+ pkcs11_destroy_keys(slot->token, CKO_PUBLIC_KEY);
+ }
if (!priv->haveSession) {
PKCS11err(PKCS11_F_PKCS11_LOGOUT, PKCS11_NO_SESSION);
return -1;
@@ -506,7 +510,10 @@ static int pkcs11_check_token(PKCS11_CTX * ctx, PKCS11_SLOT * slot)
/* We have a token */
tpriv = PKCS11_NEW(PKCS11_TOKEN_private);
tpriv->parent = slot;
- tpriv->nkeys = -1;
+ tpriv->prv.keys = NULL;
+ tpriv->prv.num = -1;
+ tpriv->pub.keys = NULL;
+ tpriv->pub.num = -1;
tpriv->ncerts = -1;
token->label = PKCS11_DUP(info.label);
@@ -534,7 +541,8 @@ static int pkcs11_check_token(PKCS11_CTX * ctx, PKCS11_SLOT * slot)
static void pkcs11_destroy_token(PKCS11_TOKEN * token)
{
- pkcs11_destroy_keys(token);
+ pkcs11_destroy_keys(token, CKO_PRIVATE_KEY);
+ pkcs11_destroy_keys(token, CKO_PUBLIC_KEY);
pkcs11_destroy_certs(token);
OPENSSL_free(token->label);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/libp11.git
More information about the pkg-opensc-commit
mailing list