[pkg-opensc-commit] [libp11] 25/67: Thread-safety for the PKCS#11 reinitialization

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 e3dab4690e3f1fb48bf1210eea788a3d55989683
Author: Michał Trojnara <Michal.Trojnara at mirt.net>
Date:   Wed Dec 30 12:08:54 2015 +0100

    Thread-safety for the PKCS#11 reinitialization
---
 NEWS             |   3 +-
 src/Makefile.am  |   4 +-
 src/Makefile.mak |   5 ++-
 src/libp11-int.h |  52 ++++----------------------
 src/p11_load.c   |   2 +
 src/p11_misc.c   | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 129 insertions(+), 49 deletions(-)

diff --git a/NEWS b/NEWS
index b866e88..292e1b8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,11 @@
 NEWS for Libp11 -- History of user visible changes
 
 New in 0.3.1; unreleased;
+* Added thread safety based on OpenSSL dynamic locks (Michał Trojnara)
 * Added PKCS11_is_logged_in to API (Mikhail Denisenko)
 * Fixes in reinitialization after fork; addresses #39
   (Michał Trojnara)
-* MSVC build improvements (Michał Trojnara)
+* MSVC build fixes (Michał Trojnara)
 
 New in 0.3.0; 2015-10-09; Nikos Mavrogiannopoulos
 * Added small test suite based on softhsm (run on make check)
diff --git a/src/Makefile.am b/src/Makefile.am
index ace93c2..eb64f8c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,14 +5,14 @@ MAINTAINERCLEANFILES = \
 CLEANFILES = libp11.pc
 EXTRA_DIST = Makefile.mak versioninfo.rc.in
 
-noinst_HEADERS= libp11-int.h pkcs11.h
+noinst_HEADERS= libp11-int.h pkcs11.h atfork.h
 include_HEADERS= libp11.h
 lib_LTLIBRARIES = libp11.la
 pkgconfig_DATA = libp11.pc
 
 libp11_la_SOURCES = libpkcs11.c p11_attr.c p11_cert.c p11_err.c p11_key.c \
 	p11_load.c p11_misc.c p11_ops.c p11_rsa.c p11_ec.c p11_slot.c \
-	libp11.exports atfork.c atfork.h
+	libp11.exports atfork.c
 if WIN32
 libp11_la_SOURCES += versioninfo.rc
 else
diff --git a/src/Makefile.mak b/src/Makefile.mak
index f6d3d93..a7b44c3 100644
--- a/src/Makefile.mak
+++ b/src/Makefile.mak
@@ -4,8 +4,9 @@ TOPDIR = ..
 
 TARGET                  = libp11.dll
 
-OBJECTS                 = libpkcs11.obj p11_attr.obj p11_cert.obj p11_err.obj \
-	p11_key.obj p11_load.obj p11_misc.obj p11_rsa.obj p11_ec.obj p11_slot.obj p11_ops.obj
+OBJECTS                 = libpkcs11.obj p11_attr.obj p11_cert.obj \
+	p11_err.obj p11_key.obj p11_load.obj p11_misc.obj p11_rsa.obj \
+	p11_ec.obj p11_slot.obj p11_ops.obj
 
 all: $(TARGET) versioninfo.res
 
diff --git a/src/libp11-int.h b/src/libp11-int.h
index 168b48f..b2b1263 100644
--- a/src/libp11-int.h
+++ b/src/libp11-int.h
@@ -44,18 +44,12 @@ typedef struct pkcs11_ctx_private {
 
 	char *init_args;
 	unsigned int forkid;
+	int lockid;
 } PKCS11_CTX_private;
 #define PRIVCTX(ctx)		((PKCS11_CTX_private *) (ctx->_private))
 
-#define CHECK_FORK(ctx) { \
-	PKCS11_CTX_private *__priv = PRIVCTX(ctx); \
-	if (_P11_detect_fork(__priv->forkid)) { \
-		if (PKCS11_CTX_reload(ctx) < 0) { \
-			return -1; \
-		} \
-		__priv->forkid = _P11_get_forkid(); \
-	} \
-	}
+int check_fork(PKCS11_CTX *);
+#define CHECK_FORK(ctx) if (check_fork(ctx) < 0) return -1
 
 typedef struct pkcs11_slot_private {
 	PKCS11_CTX *parent;
@@ -72,41 +66,11 @@ typedef struct pkcs11_slot_private {
 #define PRIVSLOT(slot)		((PKCS11_SLOT_private *) (slot->_private))
 #define SLOT2CTX(slot)		(PRIVSLOT(slot)->parent)
 
-#define CHECK_SLOT_FORK(slot_ctx) { \
-	PKCS11_SLOT_private *__spriv = PRIVSLOT(slot_ctx); \
-	PKCS11_CTX *__ctx = SLOT2CTX(slot_ctx); \
-	PKCS11_CTX_private *__priv = PRIVCTX(__ctx); \
-	CHECK_FORK(SLOT2CTX(slot_ctx)); \
-	if (__spriv->forkid != __priv->forkid) { \
-		if (__spriv->loggedIn) { \
-			int __saved = __spriv->haveSession; \
-			__spriv->haveSession = 0; \
-			__spriv->loggedIn = 0; \
-			if (PKCS11_relogin(slot_ctx) < 0) { \
-				return -1; \
-			} \
-			__spriv->haveSession = __saved; \
-		} \
-		if (__spriv->haveSession) { \
-			__spriv->haveSession = 0; \
-			if (PKCS11_reopen_session(slot_ctx) < 0) { \
-				return -1; \
-			} \
-		} \
-		__spriv->forkid = __priv->forkid; \
-	} \
-	}
-
-#define CHECK_KEY_FORK(key) { \
-	PKCS11_KEY_private *__priv = PRIVKEY(key); \
-	PKCS11_SLOT *__slot = TOKEN2SLOT(__priv->parent); \
-	PKCS11_SLOT_private *__spriv = PRIVSLOT(__slot); \
-	CHECK_SLOT_FORK(__slot); \
-	if (__spriv->forkid != __priv->forkid) { \
-		pkcs11_reload_keys(key); \
-		__priv->forkid = __spriv->forkid; \
-	} \
-	}
+int check_slot_fork(PKCS11_SLOT *);
+#define CHECK_SLOT_FORK(slot_ctx) if (check_slot_fork(slot_ctx) < 0) return -1
+
+int check_key_fork(PKCS11_KEY *);
+#define CHECK_KEY_FORK(key) if (check_key_fork(key) < 0) return -1
 
 typedef struct pkcs11_token_private {
 	PKCS11_SLOT *parent;
diff --git a/src/p11_load.c b/src/p11_load.c
index eb3badc..940f5a1 100644
--- a/src/p11_load.c
+++ b/src/p11_load.c
@@ -41,6 +41,7 @@ PKCS11_CTX *PKCS11_CTX_new(void)
 		goto fail;
 	ctx->_private = priv;
 	priv->forkid = _P11_get_forkid();
+	priv->lockid = CRYPTO_get_new_dynlockid();
 
 	return ctx;
  fail:
@@ -164,6 +165,7 @@ void PKCS11_CTX_free(PKCS11_CTX * ctx)
 	if (priv->init_args) {
 		OPENSSL_free(priv->init_args);
 	}
+	CRYPTO_destroy_dynlockid(priv->lockid);
 	OPENSSL_free(ctx->manufacturer);
 	OPENSSL_free(ctx->description);
 	OPENSSL_free(ctx->_private);
diff --git a/src/p11_misc.c b/src/p11_misc.c
index bfbfce9..ccd48e2 100644
--- a/src/p11_misc.c
+++ b/src/p11_misc.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) 2015 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
@@ -61,3 +62,114 @@ void *memdup(const void *src, size_t size)
 	memcpy(dst, src, size);
 	return dst;
 }
+
+/*
+ * PKCS#11 reinitialization after fork
+ * It wipes out the internal state of the PKCS#11 library
+ * Any libp11 references to this state are no longer valid
+ */
+static int check_fork_int(PKCS11_CTX *ctx)
+{
+	PKCS11_CTX_private *priv = PRIVCTX(ctx);
+
+	if (_P11_detect_fork(priv->forkid)) {
+		if (PKCS11_CTX_reload(ctx) < 0)
+			return -1;
+		priv->forkid = _P11_get_forkid();
+	}
+	return 0;
+}
+
+/*
+ * PKCS#11 reinitialization after fork
+ * Also relogins and reopens the session if needed
+ */
+static int check_slot_fork_int(PKCS11_SLOT *slot)
+{
+	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
+	PKCS11_CTX *ctx = SLOT2CTX(slot);
+	PKCS11_CTX_private *priv = PRIVCTX(ctx);
+
+	if (check_fork_int(SLOT2CTX(slot)) < 0)
+		return -1;
+	if (spriv->forkid != priv->forkid) {
+		if (spriv->loggedIn) {
+			int saved = spriv->haveSession;
+			spriv->haveSession = 0;
+			spriv->loggedIn = 0;
+			if (PKCS11_relogin(slot) < 0)
+				return -1;
+			spriv->haveSession = saved;
+		}
+		if (spriv->haveSession) {
+			spriv->haveSession = 0;
+			if (PKCS11_reopen_session(slot) < 0)
+				return -1;
+		}
+		spriv->forkid = priv->forkid;
+	}
+	return 0;
+}
+
+/*
+ * PKCS#11 reinitialization after fork
+ * Also reloads the key
+ */
+static int check_key_fork_int(PKCS11_KEY *key)
+{
+	PKCS11_KEY_private *priv = PRIVKEY(key);
+	PKCS11_SLOT *slot = TOKEN2SLOT(priv->parent);
+	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
+
+	if (check_slot_fork_int(slot) < 0)
+		return -1;
+	if (spriv->forkid != priv->forkid) {
+		pkcs11_reload_keys(key);
+		priv->forkid = spriv->forkid;
+	}
+	return 0;
+}
+
+/*
+ * Locking interface to check_fork_int()
+ */
+int check_fork(PKCS11_CTX *ctx)
+{
+	PKCS11_CTX_private *priv = PRIVCTX(ctx);
+	int rv;
+
+	CRYPTO_w_lock(priv->lockid);
+	rv = check_fork_int(ctx);
+	CRYPTO_w_unlock(priv->lockid);
+	return rv;
+}
+
+/*
+ * Locking interface to check_slot_fork_int()
+ */
+int check_slot_fork(PKCS11_SLOT *slot)
+{
+	PKCS11_CTX *ctx = SLOT2CTX(slot);
+	PKCS11_CTX_private *priv = PRIVCTX(ctx);
+	int rv;
+
+	CRYPTO_w_lock(priv->lockid);
+	rv = check_slot_fork_int(slot);
+	CRYPTO_w_unlock(priv->lockid);
+	return rv;
+}
+
+/*
+ * Locking interface to check_key_fork_int()
+ */
+int check_key_fork(PKCS11_KEY *key)
+{
+	PKCS11_CTX *ctx = KEY2CTX(key);
+	PKCS11_CTX_private *priv = PRIVCTX(ctx);
+	int rv;
+
+	CRYPTO_w_lock(priv->lockid);
+	rv = check_key_fork_int(key);
+	CRYPTO_w_unlock(priv->lockid);
+	return rv;
+}

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