summaryrefslogtreecommitdiff
path: root/lib/pkcs11_privkey.c
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2017-03-10 17:12:50 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2017-03-13 08:29:54 +0100
commit8a3773782f59df8ac9ad6ff3758c330559e860ad (patch)
tree18437c5e7db6dad45aab6f6d3065e13810787930 /lib/pkcs11_privkey.c
parentb012133ddf21d7d349369a1cf2f196d305db4e79 (diff)
downloadgnutls-8a3773782f59df8ac9ad6ff3758c330559e860ad.tar.gz
pkcs11: introduced locks to PKCS#11 private key structure
This allows to run PKCS#11 private key operations such as signing and decryption in parallel. Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Diffstat (limited to 'lib/pkcs11_privkey.c')
-rw-r--r--lib/pkcs11_privkey.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c
index bb9b286b1c..220d718ddc 100644
--- a/lib/pkcs11_privkey.c
+++ b/lib/pkcs11_privkey.c
@@ -1,6 +1,7 @@
/*
* GnuTLS PKCS#11 support
* Copyright (C) 2010-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2017 Red Hat, Inc.
*
* Authors: Nikos Mavrogiannopoulos, Stef Walter
*
@@ -29,6 +30,7 @@
#include <pk.h>
#include <fips.h>
#include "urls.h"
+#include "locks.h"
#include <p11-kit/uri.h>
/* In case of a fork, it will invalidate the open session
@@ -71,6 +73,8 @@ struct gnutls_pkcs11_privkey_st {
ck_object_handle_t ref; /* the key in the session */
unsigned reauth; /* whether we need to login on each operation */
+ void *mutex; /* lock for operations requiring co-ordination */
+
struct pin_info_st pin;
};
@@ -85,6 +89,7 @@ struct gnutls_pkcs11_privkey_st {
**/
int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
{
+ int ret;
FAIL_IF_LIB_ERROR;
*key = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_privkey_st));
@@ -100,6 +105,14 @@ int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
return GNUTLS_E_MEMORY_ERROR;
}
+ ret = gnutls_mutex_init(&(*key)->mutex);
+ if (ret < 0) {
+ gnutls_assert();
+ p11_kit_uri_free((*key)->uinfo);
+ free(*key);
+ return GNUTLS_E_LOCKING_ERROR;
+ }
+
return 0;
}
@@ -135,6 +148,7 @@ void gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)
gnutls_free(key->url);
if (key->sinfo.init != 0)
pkcs11_close_session(&key->sinfo);
+ gnutls_mutex_deinit(&key->mutex);
gnutls_free(key);
}
@@ -261,6 +275,10 @@ _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key,
mech.parameter = NULL;
mech.parameter_len = 0;
+ ret = gnutls_mutex_lock(&key->mutex);
+ if (ret != 0)
+ return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
+
/* Initialize signing operation; using the private key discovered
* earlier. */
rv = pkcs11_sign_init(sinfo->module, sinfo->pks, &mech, key->ref);
@@ -335,6 +353,7 @@ _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key,
ret = 0;
cleanup:
+ gnutls_mutex_unlock(&key->mutex);
if (sinfo != &key->sinfo)
pkcs11_close_session(sinfo);
if (ret < 0)
@@ -519,6 +538,10 @@ _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
mech.parameter = NULL;
mech.parameter_len = 0;
+ ret = gnutls_mutex_lock(&key->mutex);
+ if (ret != 0)
+ return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
+
/* Initialize signing operation; using the private key discovered
* earlier. */
rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks, &mech, key->ref);
@@ -565,6 +588,7 @@ _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
ret = 0;
cleanup:
+ gnutls_mutex_unlock(&key->mutex);
return ret;
}