[pkg-opensc-commit] [libp11] 191/239: When a fork is detected, the PKCS #11 modules will be reinitialized.

Eric Dorland eric at moszumanska.debian.org
Sat Oct 17 06:21:32 UTC 2015


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

eric pushed a commit to branch master
in repository libp11.

commit ecb83dad73ae39afb24b3cea294d44b7f3e3a6f1
Author: Nikos Mavrogiannopoulos <nmav at redhat.com>
Date:   Fri Jun 26 14:42:07 2015 +0200

    When a fork is detected, the PKCS #11 modules will be reinitialized.
    
    That includes calling C_Initialize and reopening any sessions.
    The reinitialization takes place during the next use of the object.
---
 configure.ac     |  2 ++
 src/Makefile.am  |  2 +-
 src/atfork.c     | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/atfork.h     | 63 ++++++++++++++++++++++++++++++++++++++
 src/libp11-int.h | 41 +++++++++++++++++++++++++
 src/libp11.h     |  9 ++++++
 src/p11_attr.c   |  2 ++
 src/p11_cert.c   |  2 ++
 src/p11_key.c    |  4 +++
 src/p11_load.c   | 30 +++++++++++++++++-
 src/p11_ops.c    | 16 ++++++++++
 src/p11_slot.c   | 93 +++++++++++++++++++++++++++++++++++++++++++++++---------
 12 files changed, 337 insertions(+), 16 deletions(-)

diff --git a/configure.ac b/configure.ac
index 1f08a8e..35ba66e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -141,6 +141,8 @@ if test "${WIN32}" != "yes"; then
 	)
 fi
 
+AC_CHECK_FUNCS([__register_atfork],,)
+
 PKG_CHECK_MODULES(
 	[OPENSSL],
 	[libcrypto >= 0.9.7],
diff --git a/src/Makefile.am b/src/Makefile.am
index 1b35442..ecc9cf4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,7 +10,7 @@ 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
+	libp11.exports atfork.c atfork.h
 if WIN32
 libp11_la_SOURCES += versioninfo.rc
 else
diff --git a/src/atfork.c b/src/atfork.c
new file mode 100644
index 0000000..b679008
--- /dev/null
+++ b/src/atfork.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2014 Red Hat
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+
+#include <sys/socket.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <atfork.h>
+
+#ifdef __sun
+# pragma fini(lib_deinit)
+# pragma init(lib_init)
+# define _CONSTRUCTOR
+# define _DESTRUCTOR
+#else
+# define _CONSTRUCTOR __attribute__((constructor))
+# define _DESTRUCTOR __attribute__((destructor))
+#endif
+
+unsigned int P11_forkid = 0;
+
+#ifndef _WIN32
+
+# ifdef HAVE_ATFORK
+static void fork_handler(void)
+{
+	P11_forkid++;
+}
+# endif
+
+# if defined(HAVE___REGISTER_ATFORK)
+extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
+extern void *__dso_handle;
+
+_CONSTRUCTOR
+int _P11_register_fork_handler(void)
+{
+	if (__register_atfork(0, 0, fork_handler, __dso_handle) != 0)
+		return -1;
+	return 0;
+}
+
+# else
+
+unsigned int _P11_get_forkid(void)
+{
+	return getpid();
+}
+
+int _P11_detect_fork(unsigned int forkid)
+{
+	if (getpid() == forkid)
+		return 0;
+	return 1;
+}
+
+/* we have to detect fork manually */
+_CONSTRUCTOR
+int _P11_register_fork_handler(void)
+{
+	P11_forkid = getpid();
+	return 0;
+}
+
+# endif
+
+#endif /* !_WIN32 */
diff --git a/src/atfork.h b/src/atfork.h
new file mode 100644
index 0000000..ebb0eb0
--- /dev/null
+++ b/src/atfork.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014 Red Hat
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef ATFORK_H
+# define ATFORK_H
+
+#include <config.h>
+
+extern unsigned int P11_forkid;
+
+#if defined(HAVE___REGISTER_ATFORK)
+# define HAVE_ATFORK
+#endif
+
+#ifndef _WIN32
+
+/* API */
+int _P11_register_fork_handler(void); /* global init */
+
+# if defined(HAVE_ATFORK)
+inline static int _P11_detect_fork(unsigned int forkid)
+{
+	if (forkid == P11_forkid)
+		return 0;
+	return 1;
+}
+
+inline static unsigned int _P11_get_forkid(void)
+{
+	return P11_forkid;
+}
+# else
+int _P11_detect_fork(unsigned int forkid);
+unsigned int _P11_get_forkid(void);
+# endif
+
+#else
+
+# define _P11_detect_fork(x) 0
+# define _P11_get_forkid() 0
+
+#endif
+
+#endif
diff --git a/src/libp11-int.h b/src/libp11-int.h
index 28e6196..358fda5 100644
--- a/src/libp11-int.h
+++ b/src/libp11-int.h
@@ -30,6 +30,7 @@ extern void *C_LoadModule(const char *name, CK_FUNCTION_LIST_PTR_PTR);
 extern CK_RV C_UnloadModule(void *module);
 
 #include "libp11.h"
+#include "atfork.h"
 
 /* get private implementations of PKCS11 structures */
 
@@ -42,18 +43,55 @@ typedef struct pkcs11_ctx_private {
 	CK_FUNCTION_LIST_PTR method;
 
 	char *init_args;
+	unsigned int forkid;
 } 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(); \
+	}}
+
 typedef struct pkcs11_slot_private {
 	PKCS11_CTX *parent;
 	unsigned char haveSession, loggedIn;
 	CK_SLOT_ID id;
 	CK_SESSION_HANDLE session;
+	unsigned int forkid;
+	int prev_rw; /* the rw status the session was open */
+
+	/* options used in last PKCS11_login */
+	char prev_pin[64];
+	int prev_so;
 } 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; \
+	}}
+
 typedef struct pkcs11_token_private {
 	PKCS11_SLOT *parent;
 	int nkeys, nprkeys;
@@ -156,6 +194,9 @@ extern void pkcs11_zap_attrs(CK_ATTRIBUTE_PTR, unsigned int);
 
 extern void *memdup(const void *, size_t);
 
+int PKCS11_reopen_session(PKCS11_SLOT * slot);
+int PKCS11_relogin(PKCS11_SLOT * slot);
+
 extern PKCS11_KEY_ops pkcs11_rsa_ops;
 extern PKCS11_KEY_ops *pkcs11_ec_ops;
 
diff --git a/src/libp11.h b/src/libp11.h
index 96e65ce..dfd278d 100644
--- a/src/libp11.h
+++ b/src/libp11.h
@@ -134,6 +134,15 @@ extern void PKCS11_CTX_init_args(PKCS11_CTX * ctx, const char * init_args);
 extern int PKCS11_CTX_load(PKCS11_CTX * ctx, const char * ident);
 
 /**
+ * Reinitialize a PKCS#11 module (after a fork)
+ *
+ * @param ctx context allocated by PKCS11_CTX_new()
+ * @retval 0 success
+ * @retval -1 error
+ */
+extern int PKCS11_CTX_reload(PKCS11_CTX * ctx);
+
+/**
  * Unload a PKCS#11 module
  *
  * @param ctx context allocated by PKCS11_CTX_new()
diff --git a/src/p11_attr.c b/src/p11_attr.c
index 7db82a5..83a3f4a 100644
--- a/src/p11_attr.c
+++ b/src/p11_attr.c
@@ -45,6 +45,8 @@ pkcs11_getattr_int(PKCS11_CTX * ctx, CK_SESSION_HANDLE session,
 	CK_ATTRIBUTE templ;
 	int rv;
 
+	CHECK_FORK(ctx);
+
 	templ.type = type;
 	templ.pValue = value;
 	templ.ulValueLen = *size;
diff --git a/src/p11_cert.c b/src/p11_cert.c
index abd0292..676fd14 100644
--- a/src/p11_cert.c
+++ b/src/p11_cert.c
@@ -233,6 +233,8 @@ PKCS11_store_certificate(PKCS11_TOKEN * token, X509 * x509, char *label,
 	unsigned int n = 0;
 	int rv;
 
+	CHECK_SLOT_FORK(slot);
+
 	/* First, make sure we have a session */
 	if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
 		return -1;
diff --git a/src/p11_key.c b/src/p11_key.c
index 030149b..d93ccfa 100644
--- a/src/p11_key.c
+++ b/src/p11_key.c
@@ -377,6 +377,8 @@ static int pkcs11_store_private_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
 	unsigned int n = 0;
 	int rv;
 
+	CHECK_SLOT_FORK(slot);
+
 	/* First, make sure we have a session */
 	if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
 		return -1;
@@ -440,6 +442,8 @@ static int pkcs11_store_public_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
 	unsigned int n = 0;
 	int rv;
 
+	CHECK_SLOT_FORK(slot);
+
 	/* First, make sure we have a session */
 	if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
 		return -1;
diff --git a/src/p11_load.c b/src/p11_load.c
index d315aa6..32116c2 100644
--- a/src/p11_load.c
+++ b/src/p11_load.c
@@ -36,6 +36,7 @@ PKCS11_CTX *PKCS11_CTX_new(void)
 	priv = PKCS11_NEW(PKCS11_CTX_private);
 	ctx = PKCS11_NEW(PKCS11_CTX);
 	ctx->_private = priv;
+	priv->forkid = _P11_get_forkid();
 
 	return ctx;
 }
@@ -93,6 +94,32 @@ int PKCS11_CTX_load(PKCS11_CTX * ctx, const char *name)
 }
 
 /*
+ * Reinitialize (e.g., after a fork).
+ */
+int PKCS11_CTX_reload(PKCS11_CTX * ctx)
+{
+	PKCS11_CTX_private *priv = PRIVCTX(ctx);
+	CK_C_INITIALIZE_ARGS _args;
+	CK_C_INITIALIZE_ARGS *args = NULL;
+	CK_INFO ck_info;
+	int rv;
+
+	/* Tell the PKCS11 to initialize itself */
+	if (priv->init_args != NULL) {
+		memset(&_args, 0, sizeof(_args));
+		args = &_args;
+		args->pReserved = priv->init_args;
+	}
+	rv = priv->method->C_Initialize(args);
+	if (rv && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
+		PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, rv);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
  * Unload the shared library
  */
 void PKCS11_CTX_unload(PKCS11_CTX * ctx)
@@ -101,7 +128,8 @@ void PKCS11_CTX_unload(PKCS11_CTX * ctx)
 	priv = PRIVCTX(ctx);
 
 	/* Tell the PKCS11 library to shut down */
-	priv->method->C_Finalize(NULL);
+	if (priv->forkid == _P11_get_forkid())
+		priv->method->C_Finalize(NULL);
 
 	/* Unload the module */
 	C_UnloadModule(handle);
diff --git a/src/p11_ops.c b/src/p11_ops.c
index 8d9cbfc..ef92ed4 100644
--- a/src/p11_ops.c
+++ b/src/p11_ops.c
@@ -41,6 +41,9 @@ PKCS11_ecdsa_sign(const unsigned char *m, unsigned int m_len,
 	ctx = KEY2CTX(key);
 	priv = PRIVKEY(key);
 	slot = TOKEN2SLOT(priv->parent);
+
+	CHECK_SLOT_FORK(slot);
+
 	session = PRIVSLOT(slot)->session;
 
 	ck_sigsize = *siglen;
@@ -72,10 +75,17 @@ PKCS11_sign(int type, const unsigned char *m, unsigned int m_len,
 	int rv, ssl = ((type == NID_md5_sha1) ? 1 : 0);
 	unsigned char *encoded = NULL;
 	int sigsize;
+	PKCS11_KEY_private *priv;
+	PKCS11_SLOT *slot;
 
 	if (key == NULL)
 		return 0;
 
+	priv = PRIVKEY(key);
+	slot = TOKEN2SLOT(priv->parent);
+
+	CHECK_SLOT_FORK(slot);
+
 	sigsize = PKCS11_get_key_size(key);
 
 	if (ssl) {
@@ -146,6 +156,9 @@ PKCS11_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
 	ctx = KEY2CTX(key);
 	priv = PRIVKEY(key);
 	slot = TOKEN2SLOT(priv->parent);
+
+	CHECK_SLOT_FORK(slot);
+
 	session = PRIVSLOT(slot)->session;
 
 	sigsize=PKCS11_get_key_size(key);
@@ -203,10 +216,13 @@ PKCS11_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
 	ctx = KEY2CTX(key);
 	priv = PRIVKEY(key);
 	slot = TOKEN2SLOT(priv->parent);
+	CHECK_SLOT_FORK(slot);
+
 	session = PRIVSLOT(slot)->session;
 	memset(&mechanism, 0, sizeof(mechanism));
 	mechanism.mechanism = CKM_RSA_PKCS;
 
+
 	if( (rv = CRYPTOKI_call(ctx, C_DecryptInit(session, &mechanism, priv->object))) == 0) {
 		rv = CRYPTOKI_call(ctx, C_Decrypt
 			   (session, (CK_BYTE *) from, (CK_ULONG)flen,
diff --git a/src/p11_slot.c b/src/p11_slot.c
index 7e0d88b..1cbe5e7 100644
--- a/src/p11_slot.c
+++ b/src/p11_slot.c
@@ -33,7 +33,7 @@ PKCS11_get_slotid_from_slot(PKCS11_SLOT *slot)
 {
 	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
 
-		return priv->id;
+	return priv->id;
 }
 
 /*
@@ -42,13 +42,16 @@ PKCS11_get_slotid_from_slot(PKCS11_SLOT *slot)
 int
 PKCS11_enumerate_slots(PKCS11_CTX * ctx, PKCS11_SLOT ** slotp, unsigned int *countp)
 {
-	PKCS11_CTX_private *priv = PRIVCTX(ctx);
-
+	PKCS11_CTX_private *priv;
 	CK_SLOT_ID *slotid;
 	CK_ULONG nslots, n;
 	PKCS11_SLOT *slots;
 	int rv;
 
+	CHECK_FORK(ctx);
+
+	priv = PRIVCTX(ctx);
+
 	rv = priv->method->C_GetSlotList(FALSE, NULL_PTR, &nslots);
 	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_SLOTS, rv);
 
@@ -111,6 +114,8 @@ int PKCS11_open_session(PKCS11_SLOT * slot, int rw)
 	PKCS11_CTX *ctx = SLOT2CTX(slot);
 	int rv;
 
+	CHECK_SLOT_FORK(slot);
+
 	if (priv->haveSession) {
 		CRYPTOKI_call(ctx, C_CloseSession(priv->session));
 		priv->haveSession = 0;
@@ -122,27 +127,51 @@ int PKCS11_open_session(PKCS11_SLOT * slot, int rw)
 					 &priv->session));
 	CRYPTOKI_checkerr(PKCS11_F_PKCS11_OPEN_SESSION, rv);
 	priv->haveSession = 1;
+	priv->prev_rw = rw;
+
+	return 0;
+}
+
+int PKCS11_reopen_session(PKCS11_SLOT * slot)
+{
+	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
+	PKCS11_CTX *ctx = SLOT2CTX(slot);
+	int rv;
+
+	rv = CRYPTOKI_call(ctx,
+			   C_OpenSession(priv->id,
+					 CKF_SERIAL_SESSION | (priv->prev_rw ? CKF_RW_SESSION :
+							       0), NULL, NULL,
+					 &priv->session));
+	CRYPTOKI_checkerr(PKCS11_F_PKCS11_OPEN_SESSION, rv);
+	priv->haveSession = 1;
 
 	return 0;
 }
 
 /*
- * Authenticate with the card
+ * Authenticate with the card. relogin should be set if we automatically
+ * relogin after a fork.
  */
-int PKCS11_login(PKCS11_SLOT * slot, int so, const char *pin)
+static
+int PKCS11_login_int(PKCS11_SLOT * slot, int so, const char *pin, int relogin)
 {
 	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
 	PKCS11_CTX *ctx = priv->parent;
 	int rv;
 
-	/* Calling PKCS11_login invalidates all cached
-	 * keys we have */
-	if (slot->token)
-		pkcs11_destroy_keys(slot->token);
-	if (priv->loggedIn) {
-		/* already logged in, log out first */
-		if (PKCS11_logout(slot))
-			return -1;
+	if (relogin == 0) {
+		CHECK_SLOT_FORK(slot);
+
+		/* Calling PKCS11_login invalidates all cached
+		 * keys we have */
+		if (slot->token)
+			pkcs11_destroy_keys(slot->token);
+		if (priv->loggedIn) {
+			/* already logged in, log out first */
+			if (PKCS11_logout(slot))
+				return -1;
+		}
 	}
 	if (!priv->haveSession) {
 		/* SO gets a r/w session by default,
@@ -158,10 +187,31 @@ int PKCS11_login(PKCS11_SLOT * slot, int so, const char *pin)
 	if (rv && rv != CKR_USER_ALREADY_LOGGED_IN)  /* logged in -> OK   */
 		CRYPTOKI_checkerr(PKCS11_F_PKCS11_LOGIN, rv);
 	priv->loggedIn = 1;
+
+	if (priv->prev_pin != pin)
+		snprintf(priv->prev_pin, sizeof(priv->prev_pin), "%s", pin);
+	priv->prev_so = so;
 	return 0;
 }
 
 /*
+ * Authenticate with the card
+ */
+int PKCS11_login(PKCS11_SLOT * slot, int so, const char *pin)
+{
+	return PKCS11_login_int(slot, so, pin, 0);
+}
+
+
+
+int PKCS11_relogin(PKCS11_SLOT * slot)
+{
+	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
+
+	return PKCS11_login_int(slot, priv->prev_so, priv->prev_pin, 1);
+}
+
+/*
  * Log out
  */
 int PKCS11_logout(PKCS11_SLOT * slot)
@@ -170,6 +220,8 @@ int PKCS11_logout(PKCS11_SLOT * slot)
 	PKCS11_CTX *ctx = priv->parent;
 	int rv;
 
+	CHECK_SLOT_FORK(slot);
+
 	/* Calling PKCS11_logout invalidates all cached
 	 * keys we have */
 	if (slot->token)
@@ -194,6 +246,8 @@ int PKCS11_init_token(PKCS11_TOKEN * token, const char *pin, const char *label)
 	PKCS11_CTX *ctx = priv->parent;
 	int rv;
 
+	CHECK_FORK(ctx);
+
 	if (!label)
 		label = "PKCS#11 Token";
 	rv = CRYPTOKI_call(ctx, C_InitToken(priv->id,
@@ -223,6 +277,8 @@ int PKCS11_init_pin(PKCS11_TOKEN * token, const char *pin)
 	PKCS11_CTX *ctx = priv->parent;
 	int len, rv;
 
+	CHECK_FORK(ctx);
+
 	if (!priv->haveSession) {
 		PKCS11err(PKCS11_F_PKCS11_INIT_PIN, PKCS11_NO_SESSION);
 		return -1;
@@ -245,6 +301,8 @@ int PKCS11_change_pin(PKCS11_SLOT * slot, const char *old_pin,
 	PKCS11_CTX *ctx = priv->parent;
 	int old_len, new_len, rv;
 
+	CHECK_SLOT_FORK(slot);
+
 	if (!priv->haveSession) {
 		PKCS11err(PKCS11_F_PKCS11_CHANGE_PIN, PKCS11_NO_SESSION);
 		return -1;
@@ -269,6 +327,8 @@ int PKCS11_seed_random(PKCS11_SLOT *slot, const unsigned char *s,
 	PKCS11_CTX *ctx = priv->parent;
 	int rv;
 
+	CHECK_SLOT_FORK(slot);
+
 	if (!priv->haveSession && PKCS11_open_session(slot, 0)) {
 		PKCS11err(PKCS11_F_PKCS11_SEED_RANDOM, PKCS11_NO_SESSION);
 		return -1;
@@ -290,6 +350,8 @@ int PKCS11_generate_random(PKCS11_SLOT *slot, unsigned char *r,
 	PKCS11_CTX *ctx = priv->parent;
 	int rv;
 
+	CHECK_SLOT_FORK(slot);
+
 	if (!priv->haveSession && PKCS11_open_session(slot, 0)) {
 		PKCS11err(PKCS11_F_PKCS11_GENERATE_RANDOM, PKCS11_NO_SESSION);
 		return -1;
@@ -316,6 +378,7 @@ static int pkcs11_init_slot(PKCS11_CTX * ctx, PKCS11_SLOT * slot, CK_SLOT_ID id)
 	priv = PKCS11_NEW(PKCS11_SLOT_private);
 	priv->parent = ctx;
 	priv->id = id;
+	priv->forkid = PRIVCTX(ctx)->forkid;
 
 	slot->description = PKCS11_DUP(info.slotDescription);
 	slot->manufacturer = PKCS11_DUP(info.manufacturerID);
@@ -341,8 +404,10 @@ void pkcs11_release_slot(PKCS11_CTX * ctx, PKCS11_SLOT * slot)
 {
 	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
 
-	if (priv)
+	if (priv) {
+		OPENSSL_cleanse(priv->prev_pin, sizeof(priv->prev_pin));
 		CRYPTOKI_call(ctx, C_CloseAllSessions(priv->id));
+	}
 	OPENSSL_free(slot->_private);
 	OPENSSL_free(slot->description);
 	OPENSSL_free(slot->manufacturer);

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