[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