diff --git a/lib/pkcs11.c b/lib/pkcs11.c index e6e37c60c..e1aa64f19 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -267,20 +267,20 @@ pkcs11_add_module(const char* name, struct ck_function_list *module, unsigned cu */ 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) @@ -290,25 +290,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; } @@ -3220,11 +3255,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)); @@ -3965,7 +3996,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)); @@ -4057,7 +4088,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)); @@ -4144,7 +4175,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)); @@ -4238,7 +4269,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 de9afbdee..3ba9c5501 100644 --- a/lib/pkcs11_int.h +++ b/lib/pkcs11_int.h @@ -86,10 +86,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) \ @@ -101,20 +105,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 afe831ee9..fd1997c8c 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 69fc0f2e6..7b375d61f 100644 --- a/lib/x509/verify-high.c +++ b/lib/x509/verify-high.c @@ -367,7 +367,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); @@ -972,7 +972,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; @@ -1044,7 +1044,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; @@ -1105,7 +1105,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);