[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