summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/includes/gnutls/pkcs11.h1
-rw-r--r--lib/pkcs11.c51
-rw-r--r--lib/pkcs11_int.h11
-rw-r--r--lib/pkcs11_privkey.c2
4 files changed, 50 insertions, 15 deletions
diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h
index e7a57d96a7..0c7ebe1e6e 100644
--- a/lib/includes/gnutls/pkcs11.h
+++ b/lib/includes/gnutls/pkcs11.h
@@ -65,6 +65,7 @@ typedef struct gnutls_pkcs11_obj_st *gnutls_pkcs11_obj_t;
#define GNUTLS_PKCS11_FLAG_MANUAL 0 /* Manual loading of libraries */
#define GNUTLS_PKCS11_FLAG_AUTO 1 /* Automatically load libraries by reading /etc/gnutls/pkcs11.conf */
+#define GNUTLS_PKCS11_FLAG_AUTO_TRUSTED (1<<1) /* Automatically load trusted libraries by reading /etc/gnutls/pkcs11.conf */
/* pkcs11.conf format:
* load = /lib/xxx-pkcs11.so
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
index 13e0537485..7e8c0d4367 100644
--- a/lib/pkcs11.c
+++ b/lib/pkcs11.c
@@ -106,7 +106,14 @@ struct find_cert_st {
static struct gnutls_pkcs11_provider_st providers[MAX_PROVIDERS];
static unsigned int active_providers = 0;
-static unsigned int providers_initialized = 0;
+
+typedef enum init_level_t {
+ PROV_UNINITIALIZED = 0,
+ PROV_INIT_TRUSTED,
+ PROV_INIT_ALL
+} init_level_t;
+
+static init_level_t providers_initialized = PROV_UNINITIALIZED;
static unsigned int pkcs11_forkid = 0;
static int _gnutls_pkcs11_reinit(void);
@@ -258,15 +265,21 @@ pkcs11_add_module(const char* name, struct ck_function_list *module, const char
* The output value of the callback will be returned if it is
* a negative one (indicating failure).
*/
-int _gnutls_pkcs11_check_init(void *priv, pkcs11_reinit_function cb)
+int _gnutls_pkcs11_check_init(unsigned trusted, void *priv, pkcs11_reinit_function cb)
{
int ret;
+ init_level_t req_level = PROV_UNINITIALIZED;
+
+ if (trusted)
+ req_level = PROV_INIT_TRUSTED;
+ else
+ req_level = PROV_INIT_ALL;
ret = gnutls_mutex_lock(&_gnutls_pkcs11_mutex);
if (ret != 0)
return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
- if (providers_initialized != 0) {
+ if (providers_initialized >= req_level) {
ret = 0;
if (_gnutls_detect_fork(pkcs11_forkid)) {
@@ -285,10 +298,16 @@ int _gnutls_pkcs11_check_init(void *priv, pkcs11_reinit_function cb)
gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
return ret;
+ } else if (providers_initialized < req_level) {
+ /* when upgrading initialization level, deinitialize
+ * and re-initialize everything. */
+ gnutls_pkcs11_deinit();
}
_gnutls_debug_log("Initializing PKCS #11 modules\n");
- ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
+ ret = gnutls_pkcs11_init(
+ trusted?GNUTLS_PKCS11_FLAG_AUTO_TRUSTED:GNUTLS_PKCS11_FLAG_AUTO,
+ NULL);
gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
@@ -715,13 +734,13 @@ static void compat_load(const char *configfile)
return;
}
-static int auto_load(void)
+static int auto_load(unsigned trusted)
{
struct ck_function_list **modules;
int i, ret;
char* name;
- modules = p11_kit_modules_load_and_initialize(0);
+ modules = p11_kit_modules_load_and_initialize(trusted?P11_KIT_MODULE_TRUSTED:0);
if (modules == NULL) {
gnutls_assert();
_gnutls_debug_log
@@ -790,15 +809,21 @@ gnutls_pkcs11_init(unsigned int flags, const char *deprecated_config_file)
if (flags == GNUTLS_PKCS11_FLAG_MANUAL) {
/* if manual configuration is requested then don't
* bother loading any other providers */
- providers_initialized = 1;
+ providers_initialized = PROV_INIT_ALL;
return 0;
} else if (flags & GNUTLS_PKCS11_FLAG_AUTO) {
if (deprecated_config_file == NULL)
- ret = auto_load();
+ ret = auto_load(0);
compat_load(deprecated_config_file);
- providers_initialized = 1;
+ providers_initialized = PROV_INIT_ALL;
+
+ return ret;
+ } else if (flags & GNUTLS_PKCS11_FLAG_AUTO_TRUSTED) {
+ ret = auto_load(1);
+
+ providers_initialized = PROV_INIT_TRUSTED;
return ret;
}
@@ -886,7 +911,7 @@ void gnutls_pkcs11_deinit(void)
p11_kit_module_release(providers[i].module);
}
active_providers = 0;
- providers_initialized = 0;
+ providers_initialized = PROV_UNINITIALIZED;
gnutls_pkcs11_set_pin_function(NULL, NULL);
gnutls_pkcs11_set_token_function(NULL, NULL);
@@ -3133,7 +3158,11 @@ gnutls_pkcs11_obj_list_import_url4(gnutls_pkcs11_obj_t ** p_list,
int ret;
struct find_obj_data_st priv;
- PKCS11_CHECK_INIT;
+ if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
+ PKCS11_CHECK_INIT_TRUSTED;
+ } else {
+ PKCS11_CHECK_INIT;
+ }
memset(&priv, 0, sizeof(priv));
diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h
index 885a69ff00..37e5a269ea 100644
--- a/lib/pkcs11_int.h
+++ b/lib/pkcs11_int.h
@@ -65,7 +65,7 @@ struct gnutls_pkcs11_obj_st {
* directly. It can be provided a callback function to run when a reinitialization
* occurs. */
typedef int (*pkcs11_reinit_function)(void *priv);
-int _gnutls_pkcs11_check_init(void *priv, pkcs11_reinit_function cb);
+int _gnutls_pkcs11_check_init(unsigned trusted, void *priv, pkcs11_reinit_function cb);
#define FIX_KEY_USAGE(pk, usage) \
if (usage == 0) { \
@@ -76,12 +76,17 @@ int _gnutls_pkcs11_check_init(void *priv, pkcs11_reinit_function cb);
}
#define PKCS11_CHECK_INIT \
- ret = _gnutls_pkcs11_check_init(NULL, NULL); \
+ ret = _gnutls_pkcs11_check_init(0, NULL, NULL); \
+ if (ret < 0) \
+ return gnutls_assert_val(ret)
+
+#define PKCS11_CHECK_INIT_TRUSTED \
+ ret = _gnutls_pkcs11_check_init(1, NULL, NULL); \
if (ret < 0) \
return gnutls_assert_val(ret)
#define PKCS11_CHECK_INIT_RET(x) \
- ret = _gnutls_pkcs11_check_init(NULL, NULL); \
+ ret = _gnutls_pkcs11_check_init(0, NULL, NULL); \
if (ret < 0) \
return gnutls_assert_val(x)
diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c
index 0b042463c8..7150343874 100644
--- a/lib/pkcs11_privkey.c
+++ b/lib/pkcs11_privkey.c
@@ -36,7 +36,7 @@
/* In case of a fork, it will invalidate the open session
* in the privkey and start another */
#define PKCS11_CHECK_INIT_PRIVKEY(k) \
- ret = _gnutls_pkcs11_check_init(k, reopen_privkey_session); \
+ ret = _gnutls_pkcs11_check_init(0, k, reopen_privkey_session); \
if (ret < 0) \
return gnutls_assert_val(ret)