Add locks around sodium_init()

This commit is contained in:
Frank Denis 2016-04-25 16:13:46 +02:00
parent 14211cd7ea
commit f8ff8ebf66
3 changed files with 121 additions and 4 deletions

View File

@ -644,7 +644,7 @@ dnl Checks for functions and headers
AS_IF([test "x$EMSCRIPTEN" = "x"],[ AS_IF([test "x$EMSCRIPTEN" = "x"],[
AC_CHECK_FUNCS([arc4random arc4random_buf]) AC_CHECK_FUNCS([arc4random arc4random_buf])
AC_CHECK_FUNCS([mmap mlock madvise mprotect explicit_bzero]) AC_CHECK_FUNCS([mmap mlock madvise mprotect explicit_bzero nanosleep])
]) ])
AC_CHECK_FUNCS([posix_memalign getpid]) AC_CHECK_FUNCS([posix_memalign getpid])

View File

@ -1,4 +1,12 @@
#include <string.h>
#include <time.h>
#ifdef HAVE_PTHREAD
# include <pthread.h>
#elif defined(_WIN32)
# include <windows.h>
#endif
#include "core.h" #include "core.h"
#include "crypto_generichash.h" #include "crypto_generichash.h"
#include "crypto_onetimeauth.h" #include "crypto_onetimeauth.h"
@ -18,12 +26,21 @@
# warning Alternatively, use the "stable" branch in the git repository. # warning Alternatively, use the "stable" branch in the git repository.
#endif #endif
static int initialized; static int _sodium_crit_enter(void);
static int _sodium_crit_leave(void);
static volatile int initialized;
int int
sodium_init(void) sodium_init(void)
{ {
if (_sodium_crit_enter() != 0) {
return -1;
}
if (initialized != 0) { if (initialized != 0) {
if (_sodium_crit_leave() != 0) {
return -1;
}
return 1; return 1;
} }
_sodium_runtime_get_cpu_features(); _sodium_runtime_get_cpu_features();
@ -35,6 +52,105 @@ sodium_init(void)
_crypto_scalarmult_curve25519_pick_best_implementation(); _crypto_scalarmult_curve25519_pick_best_implementation();
_crypto_stream_chacha20_pick_best_implementation(); _crypto_stream_chacha20_pick_best_implementation();
initialized = 1; initialized = 1;
if (_sodium_crit_leave() != 0) {
return -1;
}
return 0;
}
#ifdef HAVE_PTHREAD
static pthread_mutex_t _sodium_lock = PTHREAD_MUTEX_INITIALIZER;
static int
_sodium_crit_enter(void)
{
return pthread_mutex_lock(&_sodium_lock);
}
static int
_sodium_crit_leave(void)
{
return pthread_mutex_unlock(&_sodium_lock);
}
#elif defined(_WIN32)
static CRITICAL_SECTION *_sodium_lock;
static volatile LONG _sodium_lock_initialized;
static int
_sodium_crit_enter(void)
{
if (InterlockedCompareExchange(&_sodium_lock_initialized,
1L, 0L) != 0L) {
InitializeCriticalSection(_sodium_lock);
InterlockedIncrement(&_sodium_lock_initialized);
} else {
while (InterlockedCompareExchange(&_sodium_lock_initialized,
2L, 2L) != 2L) {
Sleep(0);
}
}
return 0;
}
static int
_sodium_crit_leave(void)
{
if (_sodium_lock == NULL) {
return -1;
}
LeaveCriticalSection(_sodium_lock);
return 0; return 0;
} }
#elif defined(__GNUC__) && !defined(__EMSCRIPTEN__)
static volatile int _sodium_lock;
static int
_sodium_crit_enter(void)
{
if (__sync_lock_test_and_set(&_sodium_lock, 1) != 0) {
for (;;) {
if (_sodium_lock == 0U &&
__sync_lock_test_and_set(&_sodium_lock, 1) == 0) {
break;
}
# ifdef HAVE_NANOSLEEP
{
struct timespec q;
memset(&q, 0, sizeof q);
(void) nanosleep(&q, NULL);
}
# endif
}
}
return 0;
}
static int
_sodium_crit_leave(void)
{
__sync_lock_release(&_sodium_lock);
return 0;
}
#else
static int
_sodium_crit_enter(void)
{
return 0;
}
static int
_sodium_crit_leave(void)
{
return 0;
}
#endif

View File

@ -14,8 +14,6 @@
# include <sys/mman.h> # include <sys/mman.h>
#endif #endif
#include "utils.h"
#include "randombytes.h"
#ifdef _WIN32 #ifdef _WIN32
# include <windows.h> # include <windows.h>
# include <wincrypt.h> # include <wincrypt.h>
@ -23,6 +21,9 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
#include "utils.h"
#include "randombytes.h"
#ifndef ENOSYS #ifndef ENOSYS
# define ENOSYS ENXIO # define ENOSYS ENXIO
#endif #endif