[pkg-opensc-commit] [libp11] 02/06: Fix #150: Update ex_data on EVP_PKEYs after enumerating keys

Eric Dorland eric at moszumanska.debian.org
Mon May 22 03:43:02 UTC 2017


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to annotated tag libp11-0.4.6
in repository libp11.

commit 985342accb1a0ce0b936097201cfca6cee0a2b12
Author: Matt Hauck <matthauck at gmail.com>
Date:   Wed Apr 5 18:13:28 2017 -0700

    Fix #150: Update ex_data on EVP_PKEYs after enumerating keys
    
    OPENSSL_realloc may shift the objects location in memory, invalidating
    pointers cached inside RSA and EC_KEY ex_datas. We should update
    those pointers to avoid segfaults.
---
 src/libp11-int.h |  1 +
 src/p11_ec.c     | 25 ++++++++++++++++++++++++-
 src/p11_key.c    | 11 +++++++++++
 src/p11_rsa.c    | 22 ++++++++++++++++++++--
 4 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/src/libp11-int.h b/src/libp11-int.h
index 053d2e8..dae0557 100644
--- a/src/libp11-int.h
+++ b/src/libp11-int.h
@@ -87,6 +87,7 @@ typedef struct pkcs11_token_private {
 typedef struct pkcs11_key_ops {
 	int type; /* EVP_PKEY_xxx */
 	EVP_PKEY *(*get_evp_key) (PKCS11_KEY *);
+	void (*update_ex_data) (PKCS11_KEY *);
 } PKCS11_KEY_ops;
 
 typedef struct pkcs11_key_private {
diff --git a/src/p11_ec.c b/src/p11_ec.c
index a3748d7..754da9a 100644
--- a/src/p11_ec.c
+++ b/src/p11_ec.c
@@ -240,6 +240,28 @@ static EC_KEY *pkcs11_get_ec(PKCS11_KEY *key)
 	return ec;
 }
 
+static void pkcs11_set_ex_data_ec(EC_KEY* ec, PKCS11_KEY* key)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+	EC_KEY_set_ex_data(ec, ec_ex_index, key);
+#else
+	ECDSA_set_ex_data(ec, ec_ex_index, key);
+#endif
+}
+
+static void pkcs11_update_ex_data_ec(PKCS11_KEY* key)
+{
+	EVP_PKEY* evp = key->evp_key;
+	if (evp == NULL)
+		return;
+	if (EVP_PKEY_base_id(evp) != EVP_PKEY_EC)
+		return;
+
+	EC_KEY* ec = EVP_PKEY_get1_EC_KEY(evp);
+	pkcs11_set_ex_data_ec(ec, key);
+	EC_KEY_free(ec);
+}
+
 /*
  * Get EC key material and stash pointer in ex_data
  * Note we get called twice, once for private key, and once for public
@@ -690,7 +712,8 @@ ECDH_METHOD *PKCS11_get_ecdh_method(void)
 
 PKCS11_KEY_ops pkcs11_ec_ops_s = {
 	EVP_PKEY_EC,
-	pkcs11_get_evp_key_ec
+	pkcs11_get_evp_key_ec,
+	pkcs11_update_ex_data_ec,
 };
 PKCS11_KEY_ops *pkcs11_ec_ops = {&pkcs11_ec_ops_s};
 
diff --git a/src/p11_key.c b/src/p11_key.c
index c38fb48..0702f4b 100644
--- a/src/p11_key.c
+++ b/src/p11_key.c
@@ -393,7 +393,9 @@ int pkcs11_enumerate_keys(PKCS11_TOKEN *token, unsigned int type,
 	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
 	PKCS11_CTX_private *cpriv = PRIVCTX(ctx);
 	PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub;
+	PKCS11_KEY *first_key_prev = keys->keys;
 	int rv;
+	int i;
 
 	/* Make sure we have a session */
 	if (!spriv->haveSession && PKCS11_open_session(slot, 0))
@@ -407,6 +409,15 @@ int pkcs11_enumerate_keys(PKCS11_TOKEN *token, unsigned int type,
 		return -1;
 	}
 
+	/* Always update key references if the keys pointer changed */
+	if (first_key_prev != NULL && first_key_prev != keys->keys) {
+		for (i = 0; i < keys->num; ++i) {
+			PKCS11_KEY *key = keys->keys + i;
+			PKCS11_KEY_private *kpriv = PRIVKEY(key);
+			kpriv->ops->update_ex_data(key);
+		}
+	}
+
 	if (keyp)
 		*keyp = keys->keys;
 	if (countp)
diff --git a/src/p11_rsa.c b/src/p11_rsa.c
index 0c6a14f..a53805d 100644
--- a/src/p11_rsa.c
+++ b/src/p11_rsa.c
@@ -235,6 +235,23 @@ success:
 	return rsa;
 }
 
+static void pkcs11_set_ex_data_rsa(RSA* rsa, PKCS11_KEY* key)
+{
+	RSA_set_ex_data(rsa, rsa_ex_index, key);
+}
+
+static void pkcs11_update_ex_data_rsa(PKCS11_KEY* key)
+{
+	EVP_PKEY* evp = key->evp_key;
+	if (evp == NULL)
+		return;
+	if (EVP_PKEY_base_id(evp) != EVP_PKEY_RSA)
+		return;
+
+	RSA* rsa = EVP_PKEY_get1_RSA(evp);
+	pkcs11_set_ex_data_rsa(rsa, key);
+	RSA_free(rsa);
+}
 /*
  * Build an EVP_PKEY object
  */
@@ -262,7 +279,7 @@ static EVP_PKEY *pkcs11_get_evp_key_rsa(PKCS11_KEY *key)
 	/* RSA_FLAG_SIGN_VER is no longer needed since OpenSSL 1.1 */
 	rsa->flags |= RSA_FLAG_SIGN_VER;
 #endif
-	RSA_set_ex_data(rsa, rsa_ex_index, key);
+	pkcs11_set_ex_data_rsa(rsa, key);
 	RSA_free(rsa); /* Drops our reference to it */
 	return pk;
 }
@@ -467,7 +484,8 @@ void PKCS11_rsa_method_free(void)
 
 PKCS11_KEY_ops pkcs11_rsa_ops = {
 	EVP_PKEY_RSA,
-	pkcs11_get_evp_key_rsa
+	pkcs11_get_evp_key_rsa,
+	pkcs11_update_ex_data_rsa
 };
 
 /* vim: set noexpandtab: */

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