summaryrefslogtreecommitdiff
path: root/libs/libsodium/src/sodium/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libsodium/src/sodium/core.c')
-rw-r--r--libs/libsodium/src/sodium/core.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/libs/libsodium/src/sodium/core.c b/libs/libsodium/src/sodium/core.c
new file mode 100644
index 0000000000..1ac29d09c8
--- /dev/null
+++ b/libs/libsodium/src/sodium/core.c
@@ -0,0 +1,231 @@
+
+#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 "core.h"
+#include "crypto_generichash.h"
+#include "crypto_onetimeauth.h"
+#include "crypto_scalarmult.h"
+#include "crypto_stream_chacha20.h"
+#include "crypto_stream_salsa20.h"
+#include "randombytes.h"
+#include "runtime.h"
+#include "utils.h"
+#include "private/implementations.h"
+#include "private/mutex.h"
+
+#if !defined(_MSC_VER) && 0
+# warning *** This is unstable, untested, development code.
+# warning It might not compile. It might not work as expected.
+# warning It might be totally insecure.
+# warning Do not use this in production.
+# warning Use releases available at https://download.libsodium.org/libsodium/releases/ instead.
+# warning Alternatively, use the "stable" branch in the git repository.
+#endif
+
+#if !defined(_MSC_VER) && (!defined(CONFIGURED) || CONFIGURED != 1)
+# warning *** The library is being compiled using an undocumented method.
+# warning This is not supported. It has not been tested, it might not
+# warning work as expected, and performance is likely to be suboptimal.
+#endif
+
+static volatile int initialized;
+static volatile int locked;
+
+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 */
+ }
+ return 1;
+ }
+ _sodium_runtime_get_cpu_features();
+ randombytes_stir();
+ _sodium_alloc_init();
+ _crypto_pwhash_argon2_pick_best_implementation();
+ _crypto_generichash_blake2b_pick_best_implementation();
+ _crypto_onetimeauth_poly1305_pick_best_implementation();
+ _crypto_scalarmult_curve25519_pick_best_implementation();
+ _crypto_stream_chacha20_pick_best_implementation();
+ _crypto_stream_salsa20_pick_best_implementation();
+ initialized = 1;
+ if (sodium_crit_leave() != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+}
+
+#ifdef _WIN32
+
+static CRITICAL_SECTION _sodium_lock;
+static volatile LONG _sodium_lock_initialized;
+
+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;
+
+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;
+}