summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2021-11-22 10:59:38 +0000
committerDaiki Ueno <ueno@gnu.org>2021-11-22 10:59:38 +0000
commit8f17428b84f877bd04e03b6cccd0f4f23101ef3a (patch)
tree247b778cbba3e9dec8f84bd47116a1c9cc424abd
parenta957c6c0b4abf6cb1c9756ef10e8b884cf7ae8aa (diff)
parentf0b5403b9d89c2231d7ac84f53f3723075ef0fb3 (diff)
downloadgnutls-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.c33
-rw-r--r--lib/kx.c31
-rw-r--r--lib/locks.c73
-rw-r--r--lib/locks.h67
-rw-r--r--lib/pkcs11.c6
-rw-r--r--lib/priority.c180
-rw-r--r--lib/random.c7
-rw-r--r--lib/system/threads.c106
-rw-r--r--lib/tpm2.c5
-rw-r--r--lib/tpm2.h11
-rw-r--r--lib/tpm2_esys.c60
-rw-r--r--lib/verify-tofu.c8
-rw-r--r--tests/seccomp.c3
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);
}
}
diff --git a/lib/kx.c b/lib/kx.c
index 43a7e29518..b016779e3f 100644
--- a/lib/kx.c
+++ b/lib/kx.c
@@ -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");