summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-10-13 23:10:28 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-10-13 23:10:28 +0200
commitb777e41ccd09ed9202d38e4506a31b3e5780b098 (patch)
tree76001e15d74e5a4c8bbb6a6814f2d3632821bdaf
parent4cf63ca284a1fe2b11170e8a50b2789f8491299a (diff)
downloadncrypto-b777e41ccd09ed9202d38e4506a31b3e5780b098.tar.gz
ncrypto-b777e41ccd09ed9202d38e4506a31b3e5780b098.tar.xz
ncrypto-b777e41ccd09ed9202d38e4506a31b3e5780b098.zip
Automatically initialize NSS on first use.
-rw-r--r--include/ncrypto/ncrypto.h4
-rw-r--r--lib/ncrypto_nss.c106
-rw-r--r--tests/rsa.c12
3 files changed, 104 insertions, 18 deletions
diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h
index e47b46c..25cc285 100644
--- a/include/ncrypto/ncrypto.h
+++ b/include/ncrypto/ncrypto.h
@@ -40,6 +40,10 @@ Red Hat author: Miloslav Trmač <mitr@redhat.com> */
/* Global state */
+/* A program should pair calls of ncr_open () with ncr_close (). In absence
+ of ncr_open (), the library will be initialized automatically, and
+ ncr_close () will deinitialize it. */
+
CK_RV ncr_open (void);
CK_RV ncr_close (void);
diff --git a/lib/ncrypto_nss.c b/lib/ncrypto_nss.c
index 12aaab8..11dc74b 100644
--- a/lib/ncrypto_nss.c
+++ b/lib/ncrypto_nss.c
@@ -42,48 +42,74 @@ Red Hat author: Miloslav Trmač <mitr@redhat.com> */
static pthread_mutex_t refcount_mutex = PTHREAD_MUTEX_INITIALIZER;
static size_t refcount;
-CK_RV
-ncr_open (void)
+static CK_RV
+ncr_open_locked (void)
{
- if (pthread_mutex_lock (&refcount_mutex) != 0)
- return CKR_GENERAL_ERROR;
-
if (refcount == 0)
{
if (NSS_NoDB_Init (NULL) != SECSuccess)
- {
- (void)pthread_mutex_unlock (&refcount_mutex);
- return CKR_GENERAL_ERROR;
- }
+ return CKR_GENERAL_ERROR;
}
refcount++;
+ return CKR_OK;
+}
+
+CK_RV
+ncr_open (void)
+{
+ CK_RV res;
+ if (pthread_mutex_lock (&refcount_mutex) != 0)
+ return CKR_GENERAL_ERROR;
+ res = ncr_open_locked ();
if (pthread_mutex_unlock (&refcount_mutex) != 0)
return CKR_GENERAL_ERROR;
- return CKR_OK;
+ return res;
+}
+
+static CK_RV
+ensure_ncr_is_open (void)
+{
+ CK_RV res;
+
+ if (pthread_mutex_lock (&refcount_mutex) != 0)
+ return CKR_GENERAL_ERROR;
+ if (refcount != 0)
+ res = CKR_OK;
+ else
+ res = ncr_open_locked ();
+ if (pthread_mutex_unlock (&refcount_mutex) != 0)
+ return CKR_GENERAL_ERROR;
+
+ return res;
}
CK_RV
ncr_close (void)
{
+ CK_RV res;
+
if (pthread_mutex_lock (&refcount_mutex) != 0)
return CKR_GENERAL_ERROR;
- refcount--;
if (refcount == 0)
+ res = CKR_GENERAL_ERROR;
+ else
{
- if (NSS_Shutdown () != SECSuccess)
+ refcount--;
+ res = CKR_OK;
+ if (refcount == 0)
{
- (void)pthread_mutex_unlock (&refcount_mutex);
- return CKR_GENERAL_ERROR;
+ if (NSS_Shutdown () != SECSuccess)
+ res = CKR_GENERAL_ERROR;
}
}
if (pthread_mutex_unlock (&refcount_mutex) != 0)
return CKR_GENERAL_ERROR;
- return CKR_OK;
+ return res;
}
/* Asymmetric keys */
@@ -123,8 +149,13 @@ CK_RV
ncr_public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
const void *der, size_t der_size)
{
+ CK_RV res;
SECItem der_key;
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
g_return_val_if_fail (key != NULL, CKR_ARGUMENTS_BAD);
g_return_val_if_fail (der != NULL, CKR_ARGUMENTS_BAD);
@@ -136,6 +167,12 @@ ncr_public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
CK_RV
ncr_public_key_destroy (struct ncr_public_key *key)
{
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
/* Note: this leaks "key->key", which the function does not free (642767). */
@@ -295,6 +332,11 @@ ncr_private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
{
SECItem der_key;
SECItem public;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
g_return_val_if_fail (key != NULL, CKR_ARGUMENTS_BAD);
g_return_val_if_fail (der != NULL, CKR_ARGUMENTS_BAD);
@@ -309,6 +351,12 @@ ncr_private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
CK_RV
ncr_private_key_destroy (struct ncr_private_key *key)
{
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
SECKEY_DestroyPrivateKey (key->key);
@@ -339,6 +387,10 @@ ncr_public_key_create_rsa (struct ncr_public_key **key, const void *modulus,
SECItem der_key;
CK_RV res;
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
g_return_val_if_fail (modulus != NULL, CKR_ARGUMENTS_BAD);
g_return_val_if_fail (public_exponent != NULL, CKR_ARGUMENTS_BAD);
@@ -398,6 +450,10 @@ ncr_private_key_create_rsa (struct ncr_private_key **key, const void *modulus,
SECItem der_key;
CK_RV res;
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
g_return_val_if_fail (modulus != NULL, CKR_ARGUMENTS_BAD);
g_return_val_if_fail (public_exponent != NULL, CKR_ARGUMENTS_BAD);
@@ -439,6 +495,11 @@ ncr_public_key_encrypt (CK_MECHANISM_TYPE mech, struct ncr_public_key *key,
{
size_t dest_size;
SECStatus ss;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD);
@@ -488,6 +549,11 @@ ncr_private_key_decrypt (CK_MECHANISM_TYPE mech, struct ncr_private_key *key,
{
unsigned out_len;
SECStatus ss;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD);
@@ -525,6 +591,11 @@ ncr_private_key_sign (CK_MECHANISM_TYPE mech, struct ncr_private_key *key,
{
size_t dest_size;
SECItem src_item, dest_item;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD);
@@ -567,6 +638,11 @@ ncr_public_key_verify (CK_MECHANISM_TYPE mech, struct ncr_public_key *key,
const void *src, size_t src_size)
{
SECItem sig_item, src_item;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
g_return_val_if_fail (signature != NULL || signature_size == 0,
diff --git a/tests/rsa.c b/tests/rsa.c
index d836690..9addcf4 100644
--- a/tests/rsa.c
+++ b/tests/rsa.c
@@ -53,9 +53,6 @@ main (void)
size_t src_size, dest_size;
CK_RV res;
- res = ncr_open ();
- assert (res == CKR_OK);
-
/* Test the generic version as well? */
res = ncr_public_key_create_rsa (&public, modulus, sizeof (modulus),
public_exponent, sizeof (public_exponent));
@@ -98,8 +95,17 @@ main (void)
res = ncr_public_key_destroy (public);
assert (res == CKR_OK);
+ /* Test reference counting */
+ res = ncr_open ();
+ assert (res == CKR_OK);
+ res = ncr_close ();
+ assert (res == CKR_OK);
+ /* Close the implicit reference */
res = ncr_close ();
assert (res == CKR_OK);
+ /* Check further closes are invalid */
+ res = ncr_close ();
+ assert (res == CKR_GENERAL_ERROR);
return EXIT_SUCCESS;
}