Blob Blame History Raw
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
index ec5754e89..c8b2c71f2 100644
--- a/lib/pkcs11.c
+++ b/lib/pkcs11.c
@@ -264,20 +264,20 @@ pkcs11_add_module(const char* name, struct ck_function_list *module, const char
 */
 int _gnutls_pkcs11_check_init(init_level_t req_level, void *priv, pkcs11_reinit_function cb)
 {
-	int ret;
+	int ret, sret = 0;
 
 	ret = gnutls_mutex_lock(&_gnutls_pkcs11_mutex);
 	if (ret != 0)
 		return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
 
-	if (providers_initialized >= req_level) {
+	if (providers_initialized > PROV_UNINITIALIZED) {
 		ret = 0;
 
 		if (_gnutls_detect_fork(pkcs11_forkid)) {
 			/* if we are initialized but a fork is detected */
 			ret = _gnutls_pkcs11_reinit();
 			if (ret == 0) {
-				ret = 1;
+				sret = 1;
 				if (cb) {
 					int ret2 = cb(priv);
 					if (ret2 < 0)
@@ -287,25 +287,60 @@ int _gnutls_pkcs11_check_init(init_level_t req_level, void *priv, pkcs11_reinit_
 			}
 		}
 
-		gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
-		return ret;
-	} else if (providers_initialized < req_level &&
-		   (req_level == PROV_INIT_TRUSTED)) {
-		_gnutls_debug_log("Initializing needed PKCS #11 modules\n");
-		ret = auto_load(1);
+		if (ret < 0) {
+			gnutls_assert();
+			goto cleanup;
+		}
+	}
 
-		providers_initialized = PROV_INIT_TRUSTED;
-	} else {
-		_gnutls_debug_log("Initializing all PKCS #11 modules\n");
-		ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
+	/* Possible Transitions: PROV_UNINITIALIZED -> PROV_INIT_MANUAL -> PROV_INIT_MANUAL_TRUSTED
+	 * PROV_UNINITIALIZED -> PROV_INIT_TRUSTED -> PROV_INIT_ALL
+	 *
+	 * request for PROV_INIT_TRUSTED may result to PROV_INIT_MANUAL_TRUSTED
+	 * request for PROV_INIT_ALL may result to PROV_INIT_MANUAL or PROV_INIT_MANUAL_TRUSTED
+	 */
+	switch(req_level) {
+		case PROV_UNINITIALIZED:
+		case PROV_INIT_MANUAL:
+			break;
+		case PROV_INIT_TRUSTED:
+		case PROV_INIT_MANUAL_TRUSTED:
+			if (providers_initialized < PROV_INIT_MANUAL_TRUSTED) {
+				_gnutls_debug_log("Initializing needed PKCS #11 modules\n");
+				ret = auto_load(1);
+				if (ret < 0) {
+					gnutls_assert();
+				}
+
+				if (providers_initialized == PROV_INIT_MANUAL)
+					providers_initialized = PROV_INIT_MANUAL_TRUSTED;
+				else
+					providers_initialized = PROV_INIT_TRUSTED;
+
+				goto cleanup;
+			}
+			break;
+		case PROV_INIT_ALL:
+			if (providers_initialized == PROV_INIT_TRUSTED ||
+			    providers_initialized == PROV_UNINITIALIZED) {
+				_gnutls_debug_log("Initializing all PKCS #11 modules\n");
+				ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
+				if (ret < 0) {
+					gnutls_assert();
+				}
+
+				providers_initialized = PROV_INIT_ALL;
+				goto cleanup;
+			}
+			break;
 	}
 
-	gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
+	ret = sret;
 
-	if (ret < 0)
-		return gnutls_assert_val(ret);
+ cleanup:
+	gnutls_mutex_unlock(&_gnutls_pkcs11_mutex);
 
-	return 0;
+	return ret;
 }
 
 
@@ -3149,11 +3184,7 @@ gnutls_pkcs11_obj_list_import_url4(gnutls_pkcs11_obj_t ** p_list,
 	int ret;
 	struct find_obj_data_st priv;
 
-	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
-		PKCS11_CHECK_INIT_TRUSTED;
-	} else {
-		PKCS11_CHECK_INIT;
-	}
+	PKCS11_CHECK_INIT_FLAGS(flags);
 
 	memset(&priv, 0, sizeof(priv));
 
@@ -3790,7 +3821,7 @@ int gnutls_pkcs11_get_raw_issuer(const char *url, gnutls_x509_crt_t cert,
 	size_t id_size;
 	struct p11_kit_uri *info = NULL;
 
-	PKCS11_CHECK_INIT;
+	PKCS11_CHECK_INIT_FLAGS(flags);
 
 	memset(&priv, 0, sizeof(priv));
 
@@ -3882,7 +3913,7 @@ int gnutls_pkcs11_get_raw_issuer_by_dn (const char *url, const gnutls_datum_t *d
 	struct find_cert_st priv;
 	struct p11_kit_uri *info = NULL;
 
-	PKCS11_CHECK_INIT;
+	PKCS11_CHECK_INIT_FLAGS(flags);
 
 	memset(&priv, 0, sizeof(priv));
 
@@ -3969,7 +4000,7 @@ int gnutls_pkcs11_get_raw_issuer_by_subject_key_id (const char *url,
 	struct find_cert_st priv;
 	struct p11_kit_uri *info = NULL;
 
-	PKCS11_CHECK_INIT;
+	PKCS11_CHECK_INIT_FLAGS(flags);
 
 	memset(&priv, 0, sizeof(priv));
 
@@ -4063,7 +4094,7 @@ unsigned gnutls_pkcs11_crt_is_known(const char *url, gnutls_x509_crt_t cert,
 	size_t serial_size;
 	struct p11_kit_uri *info = NULL;
 
-	PKCS11_CHECK_INIT_RET(0);
+	PKCS11_CHECK_INIT_FLAGS_RET(flags, 0);
 
 	memset(&priv, 0, sizeof(priv));
 
diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h
index e27518e3f..168bb7807 100644
--- a/lib/pkcs11_int.h
+++ b/lib/pkcs11_int.h
@@ -69,10 +69,14 @@ typedef int (*pkcs11_reinit_function)(void *priv);
 typedef enum init_level_t {
 	PROV_UNINITIALIZED = 0,
 	PROV_INIT_MANUAL,
+	PROV_INIT_MANUAL_TRUSTED,
 	PROV_INIT_TRUSTED,
 	PROV_INIT_ALL
 } init_level_t;
 
+/* See _gnutls_pkcs11_check_init() for possible Transitions.
+ */
+
 int _gnutls_pkcs11_check_init(init_level_t req_level, void *priv, pkcs11_reinit_function cb);
 
 #define FIX_KEY_USAGE(pk, usage) \
@@ -84,20 +88,26 @@ int _gnutls_pkcs11_check_init(init_level_t req_level, void *priv, pkcs11_reinit_
 	}
 
 #define PKCS11_CHECK_INIT \
-	ret = _gnutls_pkcs11_check_init(PROV_INIT_MANUAL, NULL, NULL); \
+	ret = _gnutls_pkcs11_check_init(PROV_INIT_ALL, NULL, NULL); \
 	if (ret < 0) \
 		return gnutls_assert_val(ret)
 
-#define PKCS11_CHECK_INIT_TRUSTED \
-	ret = _gnutls_pkcs11_check_init(PROV_INIT_TRUSTED, NULL, NULL); \
+#define PKCS11_CHECK_INIT_RET(x) \
+	ret = _gnutls_pkcs11_check_init(PROV_INIT_ALL, NULL, NULL); \
+	if (ret < 0) \
+		return gnutls_assert_val(x)
+
+#define PKCS11_CHECK_INIT_FLAGS(f) \
+	ret = _gnutls_pkcs11_check_init((f & GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE)?PROV_INIT_TRUSTED:PROV_INIT_ALL, NULL, NULL); \
 	if (ret < 0) \
 		return gnutls_assert_val(ret)
 
-#define PKCS11_CHECK_INIT_RET(x) \
-	ret = _gnutls_pkcs11_check_init(PROV_INIT_MANUAL, NULL, NULL); \
+#define PKCS11_CHECK_INIT_FLAGS_RET(f, x) \
+	ret = _gnutls_pkcs11_check_init((f & GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE)?PROV_INIT_TRUSTED:PROV_INIT_ALL, NULL, NULL); \
 	if (ret < 0) \
 		return gnutls_assert_val(x)
 
+
 /* thus function is called for every token in the traverse_tokens
  * function. Once everything is traversed it is called with NULL tinfo.
  * It should return 0 if found what it was looking for.
diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c
index 4a9d928a3..6e9027d0b 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(PROV_INIT_MANUAL, k, reopen_privkey_session); \
+	ret = _gnutls_pkcs11_check_init(PROV_INIT_ALL, k, reopen_privkey_session); \
 	if (ret < 0) \
 		return gnutls_assert_val(ret)
 
diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c
index 1749d49b1..ec1a52ace 100644
--- a/lib/x509/verify-high.c
+++ b/lib/x509/verify-high.c
@@ -368,7 +368,7 @@ advance_iter(gnutls_x509_trust_list_t list,
 	if (list->pkcs11_token != NULL) {
 		if (iter->pkcs11_list == NULL) {
 			ret = gnutls_pkcs11_obj_list_import_url2(&iter->pkcs11_list, &iter->pkcs11_size,
-			    list->pkcs11_token, (GNUTLS_PKCS11_OBJ_FLAG_CRT|GNUTLS_PKCS11_OBJ_FLAG_MARK_CA|GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED), 0);
+			    list->pkcs11_token, (GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE|GNUTLS_PKCS11_OBJ_FLAG_CRT|GNUTLS_PKCS11_OBJ_FLAG_MARK_CA|GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED), 0);
 			if (ret < 0)
 				return gnutls_assert_val(ret);
 
@@ -964,7 +964,7 @@ int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t list,
 		gnutls_datum_t der = {NULL, 0};
 		/* use the token for verification */
 		ret = gnutls_pkcs11_get_raw_issuer(list->pkcs11_token, cert, &der,
-			GNUTLS_X509_FMT_DER, 0);
+			GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE);
 		if (ret < 0) {
 			gnutls_assert();
 			return ret;
@@ -1036,7 +1036,7 @@ int gnutls_x509_trust_list_get_issuer_by_dn(gnutls_x509_trust_list_t list,
 		gnutls_datum_t der = {NULL, 0};
 		/* use the token for verification */
 		ret = gnutls_pkcs11_get_raw_issuer_by_dn(list->pkcs11_token, dn, &der,
-			GNUTLS_X509_FMT_DER, 0);
+			GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE);
 		if (ret < 0) {
 			gnutls_assert();
 			return ret;
@@ -1097,7 +1097,7 @@ int gnutls_x509_trust_list_get_issuer_by_subject_key_id(gnutls_x509_trust_list_t
 		gnutls_datum_t der = {NULL, 0};
 		/* use the token for verification */
 		ret = gnutls_pkcs11_get_raw_issuer_by_subject_key_id(list->pkcs11_token, dn, spki, &der,
-			GNUTLS_X509_FMT_DER, 0);
+			GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE);
 		if (ret < 0) {
 			gnutls_assert();
 			return ret;
diff --git a/lib/x509/verify-high2.c b/lib/x509/verify-high2.c
index fb9f9ce10..8c75b2641 100644
--- a/lib/x509/verify-high2.c
+++ b/lib/x509/verify-high2.c
@@ -188,6 +188,10 @@ int add_trust_list_pkcs11_object_url(gnutls_x509_trust_list_t list, const char *
 	gnutls_pkcs11_obj_t *pcrt_list = NULL;
 	unsigned int pcrt_list_size = 0, i;
 	int ret;
+
+	/* here we don't use the flag GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE,
+	 * as we want to explicitly load from any module available in the system.
+	 */
 	ret =
 	    gnutls_pkcs11_obj_list_import_url2(&pcrt_list, &pcrt_list_size,
 					       url,
@@ -323,7 +327,7 @@ gnutls_x509_trust_list_add_trust_file(gnutls_x509_trust_list_t list,
 			 */
 			if (is_pkcs11_url_object(ca_file) != 0) {
 				return add_trust_list_pkcs11_object_url(list, ca_file, tl_flags);
-			} else { /* token */
+			} else { /* trusted token */
 				if (list->pkcs11_token != NULL)
 					return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 				list->pkcs11_token = gnutls_strdup(ca_file);
@@ -331,7 +335,7 @@ gnutls_x509_trust_list_add_trust_file(gnutls_x509_trust_list_t list,
 				/* enumerate the certificates */
 				ret = gnutls_pkcs11_obj_list_import_url(NULL, &pcrt_list_size,
 					ca_file, 
-					(GNUTLS_PKCS11_OBJ_FLAG_CRT|GNUTLS_PKCS11_OBJ_FLAG_MARK_CA|GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED),
+					(GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE|GNUTLS_PKCS11_OBJ_FLAG_CRT|GNUTLS_PKCS11_OBJ_FLAG_MARK_CA|GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED),
 					0);
 				if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
 					return gnutls_assert_val(ret);