diff options
author | Daiki Ueno <ueno@gnu.org> | 2021-11-22 10:59:38 +0000 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2021-11-22 10:59:38 +0000 |
commit | 8f17428b84f877bd04e03b6cccd0f4f23101ef3a (patch) | |
tree | 247b778cbba3e9dec8f84bd47116a1c9cc424abd | |
parent | a957c6c0b4abf6cb1c9756ef10e8b884cf7ae8aa (diff) | |
parent | f0b5403b9d89c2231d7ac84f53f3723075ef0fb3 (diff) | |
download | gnutls-8f17428b84f877bd04e03b6cccd0f4f23101ef3a.tar.gz |
Merge branch 'wip/dueno/thr' into 'master'
locks: couple of improvements using Gnulib glthread
See merge request gnutls/gnutls!1485
-rw-r--r-- | lib/global.c | 33 | ||||
-rw-r--r-- | lib/kx.c | 31 | ||||
-rw-r--r-- | lib/locks.c | 73 | ||||
-rw-r--r-- | lib/locks.h | 67 | ||||
-rw-r--r-- | lib/pkcs11.c | 6 | ||||
-rw-r--r-- | lib/priority.c | 180 | ||||
-rw-r--r-- | lib/random.c | 7 | ||||
-rw-r--r-- | lib/system/threads.c | 106 | ||||
-rw-r--r-- | lib/tpm2.c | 5 | ||||
-rw-r--r-- | lib/tpm2.h | 11 | ||||
-rw-r--r-- | lib/tpm2_esys.c | 60 | ||||
-rw-r--r-- | lib/verify-tofu.c | 8 | ||||
-rw-r--r-- | tests/seccomp.c | 3 |
13 files changed, 300 insertions, 290 deletions
diff --git a/lib/global.c b/lib/global.c index 3731418835..77039d9ded 100644 --- a/lib/global.c +++ b/lib/global.c @@ -70,8 +70,6 @@ inline static int _gnutls_global_init_skip(void) /* created by asn1c */ extern const asn1_static_node gnutls_asn1_tab[]; extern const asn1_static_node pkix_asn1_tab[]; -void *_gnutls_file_mutex; -void *_gnutls_pkcs11_mutex; asn1_node _gnutls_pkix1_asn = NULL; asn1_node _gnutls_gnutls_asn = NULL; @@ -232,7 +230,10 @@ static int _gnutls_global_init(unsigned constructor) const char* e; if (!constructor) { - GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex); + ret = gnutls_static_mutex_lock(&global_init_mutex); + if (ret < 0) { + return gnutls_assert_val(ret); + } } _gnutls_init++; @@ -309,18 +310,6 @@ static int _gnutls_global_init(unsigned constructor) goto out; } - ret = gnutls_mutex_init(&_gnutls_file_mutex); - if (ret < 0) { - gnutls_assert(); - goto out; - } - - ret = gnutls_mutex_init(&_gnutls_pkcs11_mutex); - if (ret < 0) { - gnutls_assert(); - goto out; - } - ret = gnutls_system_global_init(); if (ret < 0) { gnutls_assert(); @@ -383,7 +372,7 @@ static int _gnutls_global_init(unsigned constructor) out: _gnutls_init_ret = ret; if (!constructor) { - GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex); + (void)gnutls_static_mutex_unlock(&global_init_mutex); } return ret; } @@ -391,7 +380,9 @@ static int _gnutls_global_init(unsigned constructor) static void _gnutls_global_deinit(unsigned destructor) { if (!destructor) { - GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex); + if (gnutls_static_mutex_lock(&global_init_mutex) < 0) { + return; + } } if (_gnutls_init == 1) { @@ -429,11 +420,11 @@ static void _gnutls_global_deinit(unsigned destructor) #ifdef HAVE_TROUSERS _gnutls_tpm_global_deinit(); #endif +#ifdef HAVE_TPM2 + _gnutls_tpm2_deinit(); +#endif _gnutls_nss_keylog_deinit(); - - gnutls_mutex_deinit(&_gnutls_file_mutex); - gnutls_mutex_deinit(&_gnutls_pkcs11_mutex); } else { if (_gnutls_init > 0) _gnutls_init--; @@ -441,7 +432,7 @@ static void _gnutls_global_deinit(unsigned destructor) fail: if (!destructor) { - GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex); + (void)gnutls_static_mutex_unlock(&global_init_mutex); } } @@ -136,25 +136,34 @@ _gnutls_nss_keylog_func(gnutls_session_t session, #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wanalyzer-file-leak" +GNUTLS_ONCE(keylog_once); + +static void +keylog_once_init(void) +{ + const char *keylogfile; + + keylogfile = secure_getenv("SSLKEYLOGFILE"); + if (keylogfile != NULL && *keylogfile != '\0') { + keylog = fopen(keylogfile, "ae"); + _gnutls_debug_log("unable to open keylog file %s\n", + keylogfile); + } +} + void _gnutls_nss_keylog_write(gnutls_session_t session, const char *label, const uint8_t *secret, size_t secret_size) { - static const char *keylogfile = NULL; - static unsigned checked_env = 0; - - if (!checked_env) { - checked_env = 1; - keylogfile = secure_getenv("SSLKEYLOGFILE"); - if (keylogfile != NULL) - keylog = fopen(keylogfile, "ae"); - } + (void)gnutls_once(&keylog_once, keylog_once_init); if (keylog) { char client_random_hex[2*GNUTLS_RANDOM_SIZE+1]; char secret_hex[2*MAX_HASH_SIZE+1]; - GNUTLS_STATIC_MUTEX_LOCK(keylog_mutex); + if (gnutls_static_mutex_lock(&keylog_mutex) < 0) { + return; + } fprintf(keylog, "%s %s %s\n", label, _gnutls_bin2hex(session->security_parameters. @@ -164,7 +173,7 @@ void _gnutls_nss_keylog_write(gnutls_session_t session, _gnutls_bin2hex(secret, secret_size, secret_hex, sizeof(secret_hex), NULL)); fflush(keylog); - GNUTLS_STATIC_MUTEX_UNLOCK(keylog_mutex); + (void)gnutls_static_mutex_unlock(&keylog_mutex); } } diff --git a/lib/locks.c b/lib/locks.c index d9ea4d77b5..d61504e077 100644 --- a/lib/locks.c +++ b/lib/locks.c @@ -43,32 +43,77 @@ * unless really needed to. GnuTLS will use the appropriate locks for the running * system. * - * Note that since the move to implicit initialization of GnuTLS on library - * load, calling this function will deinitialize the library, and re-initialize - * it after the new locking functions are set. + * This function must be called prior to any other GnuTLS function; otherwise + * the behavior is undefined. + * + * Deprecated: This function is discouraged on GnuTLS 3.7.3 or later. * - * This function must be called prior to any other gnutls function. - * * Since: 2.12.0 **/ void gnutls_global_set_mutex(mutex_init_func init, mutex_deinit_func deinit, mutex_lock_func lock, mutex_unlock_func unlock) { -int ret; - - if (init == NULL || deinit == NULL || lock == NULL - || unlock == NULL) + if (init == NULL || deinit == NULL || lock == NULL || unlock == NULL) { return; - - gnutls_global_deinit(); + } gnutls_mutex_init = init; gnutls_mutex_deinit = deinit; gnutls_mutex_lock = lock; gnutls_mutex_unlock = unlock; +} + +int +gnutls_static_mutex_lock(gnutls_static_mutex_t lock) +{ + if (unlikely(glthread_lock_lock(lock))) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } + return 0; +} + +int +gnutls_static_mutex_unlock(gnutls_static_mutex_t lock) +{ + if (unlikely(glthread_lock_unlock(lock))) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } + return 0; +} - ret = gnutls_global_init(); - if (ret < 0) - _gnutls_debug_log("error in gnutls_global_init(): %s\n", gnutls_strerror(ret)); +int +gnutls_rwlock_rdlock(gnutls_rwlock_t rwlock) +{ + if (unlikely(glthread_rwlock_rdlock(rwlock))) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } + return 0; +} + +int +gnutls_rwlock_wrlock(gnutls_rwlock_t rwlock) +{ + if (unlikely(glthread_rwlock_wrlock(rwlock))) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } + return 0; +} + +int +gnutls_rwlock_unlock(gnutls_rwlock_t rwlock) +{ + if (unlikely(glthread_rwlock_unlock(rwlock))) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } + return 0; +} + +int +gnutls_once(gnutls_once_t once, void (*init_func) (void)) +{ + if (unlikely(glthread_once(once, init_func))) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } + return 0; } diff --git a/lib/locks.h b/lib/locks.h index 51a0f56f43..a1ff0fa9d7 100644 --- a/lib/locks.h +++ b/lib/locks.h @@ -25,61 +25,38 @@ #include <gnutls/gnutls.h> #include "gnutls_int.h" -#include <system.h> +#include "system.h" #include "glthread/lock.h" -#ifdef HAVE_STDATOMIC_H -# include <stdatomic.h> -#endif - extern mutex_init_func gnutls_mutex_init; extern mutex_deinit_func gnutls_mutex_deinit; extern mutex_lock_func gnutls_mutex_lock; extern mutex_unlock_func gnutls_mutex_unlock; -#if defined(HAVE_WIN32_LOCKS) -# include <windows.h> - -/* Idea based based on comment 2 at: - * https://stackoverflow.com/questions/3555859/is-it-possible-to-do-static-initialization-of-mutexes-in-windows +/* If a mutex is initialized with GNUTLS_STATIC_MUTEX, it must be + * locked/unlocked with the gnutls_static_mutex_* functions defined + * below instead of the above gnutls_mutex_* functions, because the + * latter can be replaced with gnutls_global_set_mutex(). */ -# define GNUTLS_STATIC_MUTEX(mutex) \ - static CRITICAL_SECTION *mutex = NULL - -# define GNUTLS_STATIC_MUTEX_LOCK(mutex) \ - if (mutex == NULL) { \ - CRITICAL_SECTION *mutex##tmp = malloc(sizeof(CRITICAL_SECTION)); \ - InitializeCriticalSection(mutex##tmp); \ - if (InterlockedCompareExchangePointer((PVOID*)&mutex, (PVOID)mutex##tmp, NULL) != NULL) { \ - DeleteCriticalSection(mutex##tmp); \ - free(mutex##tmp); \ - } \ - } \ - EnterCriticalSection(mutex) - -# define GNUTLS_STATIC_MUTEX_UNLOCK(mutex) \ - LeaveCriticalSection(mutex) - -#elif defined(HAVE_PTHREAD_LOCKS) -# include <pthread.h> -# define GNUTLS_STATIC_MUTEX(mutex) \ - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER - -# define GNUTLS_STATIC_MUTEX_LOCK(mutex) \ - pthread_mutex_lock(&mutex) +#define GNUTLS_STATIC_MUTEX(lock) gl_lock_define_initialized(static, lock) +typedef gl_lock_t *gnutls_static_mutex_t; +int gnutls_static_mutex_lock(gnutls_static_mutex_t lock); +int gnutls_static_mutex_unlock(gnutls_static_mutex_t lock); + +/* Unlike static mutexes, static rwlocks can be locked/unlocked with + * the functions defined below, because there is no way to replace + * those functions. + */ +#define GNUTLS_RWLOCK(rwlock) gl_rwlock_define_initialized(static, rwlock) +typedef gl_rwlock_t *gnutls_rwlock_t; -# define GNUTLS_STATIC_MUTEX_UNLOCK(mutex) \ - pthread_mutex_unlock(&mutex) +int gnutls_rwlock_rdlock(gnutls_rwlock_t rwlock); +int gnutls_rwlock_wrlock(gnutls_rwlock_t rwlock); +int gnutls_rwlock_unlock(gnutls_rwlock_t rwlock); -#else -# define GNUTLS_STATIC_MUTEX(mutex) -# define GNUTLS_STATIC_MUTEX_LOCK(mutex) -# define GNUTLS_STATIC_MUTEX_UNLOCK(mutex) -#endif +#define GNUTLS_ONCE(once) gl_once_define(static, once) +typedef gl_once_t *gnutls_once_t; -#define GNUTLS_STATIC_RWLOCK(rwlock) gl_rwlock_define_initialized(static, rwlock) -#define GNUTLS_STATIC_RWLOCK_RDLOCK gl_rwlock_rdlock -#define GNUTLS_STATIC_RWLOCK_WRLOCK gl_rwlock_wrlock -#define GNUTLS_STATIC_RWLOCK_UNLOCK gl_rwlock_unlock +int gnutls_once(gnutls_once_t once, void (*init_func) (void)); #endif /* GNUTLS_LIB_LOCKS_H */ diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 364c0c49a9..8dda0f07c9 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -46,7 +46,7 @@ #define MAX_SLOTS 48 -extern void *_gnutls_pkcs11_mutex; +GNUTLS_STATIC_MUTEX(pkcs11_mutex); struct gnutls_pkcs11_provider_st { struct ck_function_list *module; @@ -279,7 +279,7 @@ int _gnutls_pkcs11_check_init(init_level_t req_level, void *priv, pkcs11_reinit_ { int ret, sret = 0; - ret = gnutls_mutex_lock(&_gnutls_pkcs11_mutex); + ret = gnutls_static_mutex_lock(&pkcs11_mutex); if (ret != 0) return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); @@ -351,7 +351,7 @@ int _gnutls_pkcs11_check_init(init_level_t req_level, void *priv, pkcs11_reinit_ ret = sret; cleanup: - gnutls_mutex_unlock(&_gnutls_pkcs11_mutex); + gnutls_static_mutex_unlock(&pkcs11_mutex); return ret; } diff --git a/lib/priority.c b/lib/priority.c index e45c6aa11d..2851d51474 100644 --- a/lib/priority.c +++ b/lib/priority.c @@ -1012,7 +1012,7 @@ struct cfg { }; /* Lock for reading and writing system_wide_config */ -GNUTLS_STATIC_RWLOCK(system_wide_config_rwlock); +GNUTLS_RWLOCK(system_wide_config_rwlock); static struct cfg system_wide_config; static unsigned fail_on_invalid_config = 0; @@ -1308,13 +1308,17 @@ static int cfg_ini_handler(void *_ctx, const char *section, const char *name, co return 1; } -static void _gnutls_update_system_priorities(void) +static int _gnutls_update_system_priorities(void) { - int ret = 0; + int ret, err = 0; struct stat sb; FILE *fp; - GNUTLS_STATIC_RWLOCK_RDLOCK(system_wide_config_rwlock); + ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock); + if (ret < 0) { + return gnutls_assert_val(ret); + } + if (stat(system_priority_file, &sb) < 0) { _gnutls_debug_log("cfg: unable to access: %s: %d\n", system_priority_file, errno); @@ -1328,9 +1332,12 @@ static void _gnutls_update_system_priorities(void) goto out; } - GNUTLS_STATIC_RWLOCK_UNLOCK(system_wide_config_rwlock); + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); - GNUTLS_STATIC_RWLOCK_WRLOCK(system_wide_config_rwlock); + ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock); + if (ret < 0) { + return gnutls_assert_val(ret); + } /* Another thread has successfully updated the system wide config (with * the same modification time as checked above), while upgrading to @@ -1350,11 +1357,11 @@ static void _gnutls_update_system_priorities(void) system_priority_file, errno); goto out; } - ret = ini_parse_file(fp, cfg_ini_handler, NULL); + err = ini_parse_file(fp, cfg_ini_handler, NULL); fclose(fp); - if (ret != 0) { + if (err) { _gnutls_debug_log("cfg: unable to parse: %s: %d\n", - system_priority_file, ret); + system_priority_file, err); goto out; } @@ -1366,16 +1373,19 @@ static void _gnutls_update_system_priorities(void) system_priority_last_mod = sb.st_mtime; out: - GNUTLS_STATIC_RWLOCK_UNLOCK(system_wide_config_rwlock); + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); - if (ret != 0 && fail_on_invalid_config) { + if (err && fail_on_invalid_config) { exit(1); } + + return ret; } void _gnutls_load_system_priorities(void) { const char *p; + int ret; p = secure_getenv("GNUTLS_SYSTEM_PRIORITY_FILE"); if (p != NULL) @@ -1385,7 +1395,11 @@ void _gnutls_load_system_priorities(void) if (p != NULL && p[0] == '1' && p[1] == 0) fail_on_invalid_config = 1; - _gnutls_update_system_priorities(); + ret = _gnutls_update_system_priorities(); + if (ret < 0) { + _gnutls_debug_log("failed to update system priorities: %s\n", + gnutls_strerror(ret)); + } } void _gnutls_unload_system_priorities(void) @@ -1423,88 +1437,101 @@ char *_gnutls_resolve_priorities(const char* priorities) { const char *p = priorities; char *additional = NULL; - char *ret = NULL; + char *resolved = NULL; const char *ss, *ss_next; unsigned ss_len, ss_next_len; size_t n, n2 = 0; + int ret; - while (c_isspace(*p)) + while (c_isspace(*p)) { p++; + } - if (*p == '@') { - ss = p+1; - additional = strchr(ss, ':'); - if (additional != NULL) { - additional++; - } + /* Cannot reduce further. */ + if (*p != '@') { + return gnutls_strdup(p); + } - /* Always try to refresh the cached data, to - * allow it to be updated without restarting - * all applications - */ - _gnutls_update_system_priorities(); - - do { - ss_next = strchr(ss, ','); - if (ss_next != NULL) { - if (additional && ss_next > additional) - ss_next = NULL; - else - ss_next++; - } + ss = p+1; + additional = strchr(ss, ':'); + if (additional) { + additional++; + } + + /* Always try to refresh the cached data, to allow it to be + * updated without restarting all applications. + */ + ret = _gnutls_update_system_priorities(); + if (ret < 0) { + _gnutls_debug_log("failed to update system priorities: %s\n", + gnutls_strerror(ret)); + } - if (ss_next) { - ss_len = ss_next - ss - 1; - ss_next_len = additional - ss_next - 1; - } else if (additional) { - ss_len = additional - ss - 1; - ss_next_len = 0; + do { + ss_next = strchr(ss, ','); + if (ss_next) { + if (additional && ss_next > additional) { + ss_next = NULL; } else { - ss_len = strlen(ss); - ss_next_len = 0; + ss_next++; } + } + + if (ss_next) { + ss_len = ss_next - ss - 1; + ss_next_len = additional - ss_next - 1; + } else if (additional) { + ss_len = additional - ss - 1; + ss_next_len = 0; + } else { + ss_len = strlen(ss); + ss_next_len = 0; + } - GNUTLS_STATIC_RWLOCK_RDLOCK(system_wide_config_rwlock); - p = _name_val_array_value(system_wide_config.priority_strings, ss, ss_len); + ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock); + if (ret < 0) { + _gnutls_debug_log("cannot read system priority strings: %s\n", + gnutls_strerror(ret)); + break; + } - _gnutls_debug_log("resolved '%.*s' to '%s', next '%.*s'\n", - ss_len, ss, S(p), ss_next_len, S(ss_next)); + p = _name_val_array_value(system_wide_config.priority_strings, + ss, ss_len); - if (p) { - n = strlen(p); - if (additional) { - n2 = strlen(additional); - } + _gnutls_debug_log("resolved '%.*s' to '%s', next '%.*s'\n", + ss_len, ss, S(p), ss_next_len, S(ss_next)); - ret = gnutls_malloc(n+n2+1+1); - if (ret) { - memcpy(ret, p, n); - if (additional != NULL) { - ret[n] = ':'; - memcpy(&ret[n+1], additional, n2); - ret[n+n2+1] = 0; - } else { - ret[n] = 0; - } + if (p) { + n = strlen(p); + if (additional) { + n2 = strlen(additional); + } + + resolved = gnutls_malloc(n+n2+1+1); + if (resolved) { + memcpy(resolved, p, n); + if (additional) { + resolved[n] = ':'; + memcpy(&resolved[n+1], additional, n2); + resolved[n+n2+1] = 0; + } else { + resolved[n] = 0; } } - GNUTLS_STATIC_RWLOCK_UNLOCK(system_wide_config_rwlock); + } - ss = ss_next; - } while (ss && ret == NULL); + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); - if (ret == NULL) { - _gnutls_debug_log("unable to resolve %s\n", priorities); - } - } else { - return gnutls_strdup(p); - } + ss = ss_next; + } while (ss && !resolved); - if (ret != NULL) { - _gnutls_debug_log("selected priority string: %s\n", ret); + if (resolved) { + _gnutls_debug_log("selected priority string: %s\n", resolved); + } else { + _gnutls_debug_log("unable to resolve %s\n", priorities); } - return ret; + return resolved; } static void add_ec(gnutls_priority_t priority_cache) @@ -1572,7 +1599,10 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) /* The following requires a lock so there are no inconsistencies in the * members of system_wide_config loaded from the config file. */ - GNUTLS_STATIC_RWLOCK_RDLOCK(system_wide_config_rwlock); + ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock); + if (ret < 0) { + return gnutls_assert_val(ret); + } /* disable key exchanges which are globally disabled */ z = 0; @@ -1853,7 +1883,7 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) } out: - GNUTLS_STATIC_RWLOCK_UNLOCK(system_wide_config_rwlock); + gnutls_rwlock_unlock(&system_wide_config_rwlock); return ret; } diff --git a/lib/random.c b/lib/random.c index 605fc8d51a..f1abe743c3 100644 --- a/lib/random.c +++ b/lib/random.c @@ -79,9 +79,12 @@ inline static int _gnutls_rnd_init(void) return GNUTLS_E_RANDOM_FAILED; } - GNUTLS_STATIC_MUTEX_LOCK(gnutls_rnd_ctx_list_mutex); + ret = gnutls_static_mutex_lock(&gnutls_rnd_ctx_list_mutex); + if (ret < 0) { + return gnutls_assert_val(ret); + } ret = append(gnutls_rnd_ctx); - GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_ctx_list_mutex); + (void)gnutls_static_mutex_unlock(&gnutls_rnd_ctx_list_mutex); if (ret < 0) { gnutls_assert(); _gnutls_rnd_ops.deinit(gnutls_rnd_ctx); diff --git a/lib/system/threads.c b/lib/system/threads.c index cbc7c920e9..89b5959ee6 100644 --- a/lib/system/threads.c +++ b/lib/system/threads.c @@ -31,135 +31,55 @@ #include <sys/stat.h> #include <sys/types.h> -#ifdef _WIN32 -# include <windows.h> -# include <wincrypt.h> - -#else /* !_WIN32 */ - -# ifdef HAVE_PTHREAD_LOCKS -# include <pthread.h> -# endif - -#endif +#include "glthread/lock.h" /* System specific lock function wrappers. */ /* Thread stuff */ -#ifdef HAVE_WIN32_LOCKS static int gnutls_system_mutex_init(void **priv) { - CRITICAL_SECTION *lock = malloc(sizeof(CRITICAL_SECTION)); + gl_lock_t *lock = malloc(sizeof(gl_lock_t)); - if (lock == NULL) - return GNUTLS_E_MEMORY_ERROR; - - InitializeCriticalSection(lock); - - *priv = lock; - - return 0; -} - -static int gnutls_system_mutex_deinit(void **priv) -{ - DeleteCriticalSection((CRITICAL_SECTION *) * priv); - free(*priv); - - return 0; -} - -static int gnutls_system_mutex_lock(void **priv) -{ - EnterCriticalSection((CRITICAL_SECTION *) * priv); - return 0; -} - -static int gnutls_system_mutex_unlock(void **priv) -{ - LeaveCriticalSection((CRITICAL_SECTION *) * priv); - return 0; -} - -#endif /* WIN32_LOCKS */ - -#ifdef HAVE_PTHREAD_LOCKS - -static int gnutls_system_mutex_init(void **priv) -{ - pthread_mutex_t *lock = malloc(sizeof(pthread_mutex_t)); - int ret; - - if (lock == NULL) + if (!lock) { return GNUTLS_E_MEMORY_ERROR; + } - ret = pthread_mutex_init(lock, NULL); - if (ret) { + if (glthread_lock_init(lock)) { free(lock); - gnutls_assert(); - return GNUTLS_E_LOCKING_ERROR; + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); } *priv = lock; - return 0; } static int gnutls_system_mutex_deinit(void **priv) { - pthread_mutex_destroy((pthread_mutex_t *) * priv); + if (glthread_lock_destroy((gl_lock_t *) * priv)) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); + } free(*priv); return 0; } static int gnutls_system_mutex_lock(void **priv) { - if (pthread_mutex_lock((pthread_mutex_t *) * priv)) { - gnutls_assert(); - return GNUTLS_E_LOCKING_ERROR; + if (glthread_lock_lock((gl_lock_t *) * priv)) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); } - return 0; } static int gnutls_system_mutex_unlock(void **priv) { - if (pthread_mutex_unlock((pthread_mutex_t *) * priv)) { - gnutls_assert(); - return GNUTLS_E_LOCKING_ERROR; + if (glthread_lock_unlock((gl_lock_t *) * priv)) { + return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); } - - return 0; -} - -#endif /* PTHREAD_LOCKS */ - -#ifdef HAVE_NO_LOCKS - -static int gnutls_system_mutex_init(void **priv) -{ - return 0; -} - -static int gnutls_system_mutex_deinit(void **priv) -{ return 0; } -static int gnutls_system_mutex_lock(void **priv) -{ - return 0; -} - -static int gnutls_system_mutex_unlock(void **priv) -{ - return 0; -} - -#endif /* NO_LOCKS */ - mutex_init_func gnutls_mutex_init = gnutls_system_mutex_init; mutex_deinit_func gnutls_mutex_deinit = gnutls_system_mutex_deinit; mutex_lock_func gnutls_mutex_lock = gnutls_system_mutex_lock; diff --git a/lib/tpm2.c b/lib/tpm2.c index 5c293a553c..076cc7f407 100644 --- a/lib/tpm2.c +++ b/lib/tpm2.c @@ -294,3 +294,8 @@ int _gnutls_load_tpm2_key(gnutls_privkey_t pkey, const gnutls_datum_t *fdata) gnutls_free(asn1.data); return ret; } + +void _gnutls_tpm2_deinit(void) +{ + tpm2_tcti_deinit(); +} diff --git a/lib/tpm2.h b/lib/tpm2.h index b55c2e1331..e40dc01df7 100644 --- a/lib/tpm2.h +++ b/lib/tpm2.h @@ -26,13 +26,20 @@ #include "pin.h" +/* Functions used outside tpm2.c */ + +void _gnutls_tpm2_deinit(void); +int _gnutls_load_tpm2_key(gnutls_privkey_t pkey, const gnutls_datum_t *fdata); + +/* Functions only used in tpm2.c */ + struct tpm2_info_st; struct tpm2_info_st *tpm2_info_init(struct pin_info_st *pin); -void release_tpm2_ctx(struct tpm2_info_st *info); +void tpm2_tcti_deinit(void); -int _gnutls_load_tpm2_key(gnutls_privkey_t pkey, const gnutls_datum_t *fdata); +void release_tpm2_ctx(struct tpm2_info_st *info); int install_tpm2_key(struct tpm2_info_st *info, gnutls_privkey_t pkey, unsigned int parent, bool emptyauth, diff --git a/lib/tpm2_esys.c b/lib/tpm2_esys.c index d219faf1e0..93e54413ba 100644 --- a/lib/tpm2_esys.c +++ b/lib/tpm2_esys.c @@ -66,13 +66,13 @@ #include <string.h> #include "tpm2.h" +#include "locks.h" #include <tss2/tss2_mu.h> #include <tss2/tss2_esys.h> #include <tss2/tss2_tctildr.h> struct tpm2_info_st { - TSS2_TCTI_CONTEXT *tcti_ctx; TPM2B_PUBLIC pub; TPM2B_PRIVATE priv; TPM2B_DIGEST userauth; @@ -85,6 +85,8 @@ struct tpm2_info_st { struct pin_info_st *pin_info; }; +static TSS2_TCTI_CONTEXT *tcti_ctx; + #define PRIMARY_HASH_ALGORITHM TPM2_ALG_SHA256 #define PRIMARY_OBJECT_ATTRIBUTES (TPMA_OBJECT_USERWITHAUTH | \ TPMA_OBJECT_RESTRICTED | \ @@ -357,7 +359,7 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *key_handle, _gnutls_debug_log("tpm2: establishing connection with TPM\n"); - rc = Esys_Initialize(ctx, info->tcti_ctx, NULL); + rc = Esys_Initialize(ctx, tcti_ctx, NULL); if (rc) { gnutls_assert(); _gnutls_debug_log("tpm2: Esys_Initialize failed: 0x%x\n", rc); @@ -693,9 +695,18 @@ int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, return ret; } -int install_tpm2_key(struct tpm2_info_st *info, gnutls_privkey_t pkey, - unsigned int parent, bool emptyauth, - gnutls_datum_t *privdata, gnutls_datum_t *pubdata) +GNUTLS_ONCE(tcti_once); + +void +tpm2_tcti_deinit(void) +{ + if (tcti_ctx) { + Tss2_TctiLdr_Finalize(&tcti_ctx); + } +} + +static void +tcti_once_init(void) { const char *tcti; const char * const tcti_vars[] = { @@ -707,16 +718,6 @@ int install_tpm2_key(struct tpm2_info_st *info, gnutls_privkey_t pkey, size_t i; TSS2_RC rc; - if (!parent_is_persistent(parent) && - parent != TPM2_RH_OWNER && parent != TPM2_RH_NULL && - parent != TPM2_RH_ENDORSEMENT && parent != TPM2_RH_PLATFORM) { - _gnutls_debug_log("tpm2: Invalid TPM2 parent handle 0x%08x\n", - parent); - return gnutls_assert_val(GNUTLS_E_TPM_ERROR); - } - - info->parent = parent; - for (i = 0; i < sizeof(tcti_vars) / sizeof(tcti_vars[0]); i++) { tcti = secure_getenv(tcti_vars[i]); if (tcti && *tcti != '\0') { @@ -726,13 +727,35 @@ int install_tpm2_key(struct tpm2_info_st *info, gnutls_privkey_t pkey, } } if (tcti && *tcti != '\0') { - rc = Tss2_TctiLdr_Initialize(tcti, &info->tcti_ctx); + rc = Tss2_TctiLdr_Initialize(tcti, &tcti_ctx); if (rc) { _gnutls_debug_log("tpm2: TSS2_TctiLdr_Initialize failed: 0x%x\n", rc); - return gnutls_assert_val(GNUTLS_E_TPM_ERROR); } } +} + +int install_tpm2_key(struct tpm2_info_st *info, gnutls_privkey_t pkey, + unsigned int parent, bool emptyauth, + gnutls_datum_t *privdata, gnutls_datum_t *pubdata) +{ + TSS2_RC rc; + + (void)gnutls_once(&tcti_once, tcti_once_init); + + if (!tcti_ctx) { + return gnutls_assert_val(GNUTLS_E_TPM_ERROR); + } + + if (!parent_is_persistent(parent) && + parent != TPM2_RH_OWNER && parent != TPM2_RH_NULL && + parent != TPM2_RH_ENDORSEMENT && parent != TPM2_RH_PLATFORM) { + _gnutls_debug_log("tpm2: Invalid TPM2 parent handle 0x%08x\n", + parent); + return gnutls_assert_val(GNUTLS_E_TPM_ERROR); + } + + info->parent = parent; rc = Tss2_MU_TPM2B_PRIVATE_Unmarshal(privdata->data, privdata->size, NULL, &info->priv); @@ -781,9 +804,6 @@ void release_tpm2_ctx(struct tpm2_info_st *info) sizeof(info->ownerauth.buffer)); zeroize_key(info->userauth.buffer, sizeof(info->userauth.buffer)); - if (info->tcti_ctx) { - Tss2_TctiLdr_Finalize(&info->tcti_ctx); - } gnutls_free(info); } } diff --git a/lib/verify-tofu.c b/lib/verify-tofu.c index 4e65c739f7..40b7acdc8a 100644 --- a/lib/verify-tofu.c +++ b/lib/verify-tofu.c @@ -35,6 +35,8 @@ #include <system.h> #include <locks.h> +GNUTLS_STATIC_MUTEX(file_mutex); + struct gnutls_tdb_int { gnutls_tdb_store_func store; gnutls_tdb_store_commitment_func cstore; @@ -58,8 +60,6 @@ int store_pubkey(const char *db_name, const char *host, static int find_config_file(char *file, size_t max_size); -extern void *_gnutls_file_mutex; - struct gnutls_tdb_int default_tdb = { store_pubkey, store_commitment, @@ -404,7 +404,7 @@ int store_pubkey(const char *db_name, const char *host, gnutls_datum_t b64key = { NULL, 0 }; int ret; - ret = gnutls_mutex_lock(&_gnutls_file_mutex); + ret = gnutls_static_mutex_lock(&file_mutex); if (ret != 0) return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR); @@ -434,7 +434,7 @@ int store_pubkey(const char *db_name, const char *host, if (fp != NULL) fclose(fp); - gnutls_mutex_unlock(&_gnutls_file_mutex); + gnutls_static_mutex_unlock(&file_mutex); gnutls_free(b64key.data); return ret; diff --git a/tests/seccomp.c b/tests/seccomp.c index ed14d00298..210fc9f9a3 100644 --- a/tests/seccomp.c +++ b/tests/seccomp.c @@ -98,6 +98,9 @@ int disable_system_calls(void) ADD_SYSCALL(sigreturn, 0); ADD_SYSCALL(rt_sigreturn, 0); + /* used by gl_once_t implementation with pthread */ + ADD_SYSCALL(futex, 0); + ret = seccomp_load(ctx); if (ret < 0) { fprintf(stderr, "could not load seccomp filter"); |