mirror of https://github.com/oxen-io/lokinet
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
3.8 KiB
C
231 lines
3.8 KiB
C
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#elif defined(HAVE_PTHREAD)
|
|
#include <pthread.h>
|
|
#endif
|
|
|
|
#include <sodium/core.h>
|
|
#include <sodium/crypto_generichash.h>
|
|
#include <sodium/crypto_scalarmult.h>
|
|
#include <sodium/crypto_stream_chacha20.h>
|
|
#include <sodium/crypto_stream_salsa20.h>
|
|
#include <sodium/randombytes.h>
|
|
#include <sodium/runtime.h>
|
|
#include <sodium/utils.h>
|
|
#include <sodium/private/implementations.h>
|
|
#include <sodium/private/mutex.h>
|
|
|
|
static volatile int initialized;
|
|
|
|
int
|
|
sodium_init(void)
|
|
{
|
|
if(sodium_crit_enter() != 0)
|
|
{
|
|
return -1; /* LCOV_EXCL_LINE */
|
|
}
|
|
if(initialized != 0)
|
|
{
|
|
if(sodium_crit_leave() != 0)
|
|
{
|
|
return -1; /* LCOV_EXCL_LINE */
|
|
}
|
|
/* if we're here, we already started properly */
|
|
return initialized ? 0 : -1;
|
|
}
|
|
_sodium_runtime_get_cpu_features();
|
|
_crypto_generichash_blake2b_pick_best_implementation();
|
|
_crypto_scalarmult_curve25519_pick_best_implementation();
|
|
_crypto_stream_chacha20_pick_best_implementation();
|
|
_crypto_stream_salsa20_pick_best_implementation();
|
|
randombytes_stir();
|
|
initialized = 1;
|
|
if(sodium_crit_leave() != 0)
|
|
{
|
|
return -1; /* LCOV_EXCL_LINE */
|
|
}
|
|
return initialized ? 0 : -1;
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
|
|
static CRITICAL_SECTION _sodium_lock;
|
|
static volatile LONG _sodium_lock_initialized;
|
|
static volatile int locked;
|
|
|
|
int
|
|
_sodium_crit_init(void)
|
|
{
|
|
LONG status = 0L;
|
|
|
|
while((status = InterlockedCompareExchange(&_sodium_lock_initialized, 1L, 0L))
|
|
== 1L)
|
|
{
|
|
Sleep(0);
|
|
}
|
|
|
|
switch(status)
|
|
{
|
|
case 0L:
|
|
InitializeCriticalSection(&_sodium_lock);
|
|
return InterlockedExchange(&_sodium_lock_initialized, 2L) == 1L ? 0 : -1;
|
|
case 2L:
|
|
return 0;
|
|
default: /* should never be reached */
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int
|
|
sodium_crit_enter(void)
|
|
{
|
|
if(_sodium_crit_init() != 0)
|
|
{
|
|
return -1; /* LCOV_EXCL_LINE */
|
|
}
|
|
EnterCriticalSection(&_sodium_lock);
|
|
assert(locked == 0);
|
|
locked = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
sodium_crit_leave(void)
|
|
{
|
|
if(locked == 0)
|
|
{
|
|
#ifdef EPERM
|
|
errno = EPERM;
|
|
#endif
|
|
return -1;
|
|
}
|
|
locked = 0;
|
|
LeaveCriticalSection(&_sodium_lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#elif defined(HAVE_PTHREAD) && !defined(__EMSCRIPTEN__)
|
|
|
|
static pthread_mutex_t _sodium_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
static volatile int locked;
|
|
|
|
int
|
|
sodium_crit_enter(void)
|
|
{
|
|
int ret;
|
|
|
|
if((ret = pthread_mutex_lock(&_sodium_lock)) == 0)
|
|
{
|
|
assert(locked == 0);
|
|
locked = 1;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
sodium_crit_leave(void)
|
|
{
|
|
int ret;
|
|
|
|
if(locked == 0)
|
|
{
|
|
#ifdef EPERM
|
|
errno = EPERM;
|
|
#endif
|
|
return -1;
|
|
}
|
|
locked = 0;
|
|
|
|
return pthread_mutex_unlock(&_sodium_lock);
|
|
}
|
|
|
|
#elif defined(HAVE_ATOMIC_OPS) && !defined(__EMSCRIPTEN__) \
|
|
&& !defined(__native_client__)
|
|
|
|
static volatile int _sodium_lock;
|
|
|
|
int
|
|
sodium_crit_enter(void)
|
|
{
|
|
#ifdef HAVE_NANOSLEEP
|
|
struct timespec q;
|
|
memset(&q, 0, sizeof q);
|
|
#endif
|
|
while(__sync_lock_test_and_set(&_sodium_lock, 1) != 0)
|
|
{
|
|
#ifdef HAVE_NANOSLEEP
|
|
(void)nanosleep(&q, NULL);
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
__asm__ __volatile__("pause");
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
sodium_crit_leave(void)
|
|
{
|
|
__sync_lock_release(&_sodium_lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
|
|
int
|
|
sodium_crit_enter(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
sodium_crit_leave(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
static void (*_misuse_handler)(void);
|
|
|
|
void
|
|
sodium_misuse(void)
|
|
{
|
|
void (*handler)(void);
|
|
|
|
(void)sodium_crit_leave();
|
|
if(sodium_crit_enter() == 0)
|
|
{
|
|
handler = _misuse_handler;
|
|
if(handler != NULL)
|
|
{
|
|
handler();
|
|
}
|
|
}
|
|
/* LCOV_EXCL_START */
|
|
abort();
|
|
}
|
|
/* LCOV_EXCL_STOP */
|
|
|
|
int
|
|
sodium_set_misuse_handler(void (*handler)(void))
|
|
{
|
|
if(sodium_crit_enter() != 0)
|
|
{
|
|
return -1; /* LCOV_EXCL_LINE */
|
|
}
|
|
_misuse_handler = handler;
|
|
if(sodium_crit_leave() != 0)
|
|
{
|
|
return -1; /* LCOV_EXCL_LINE */
|
|
}
|
|
return 0;
|
|
}
|