diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-10-13 23:10:28 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-10-13 23:10:28 +0200 |
commit | b777e41ccd09ed9202d38e4506a31b3e5780b098 (patch) | |
tree | 76001e15d74e5a4c8bbb6a6814f2d3632821bdaf | |
parent | 4cf63ca284a1fe2b11170e8a50b2789f8491299a (diff) | |
download | ncrypto-b777e41ccd09ed9202d38e4506a31b3e5780b098.tar.gz ncrypto-b777e41ccd09ed9202d38e4506a31b3e5780b098.tar.xz ncrypto-b777e41ccd09ed9202d38e4506a31b3e5780b098.zip |
Automatically initialize NSS on first use.
-rw-r--r-- | include/ncrypto/ncrypto.h | 4 | ||||
-rw-r--r-- | lib/ncrypto_nss.c | 106 | ||||
-rw-r--r-- | tests/rsa.c | 12 |
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; } |