int CRYPTO_set_thread_local(thread_local_data_t index, void *value, thread_local_destructor_t destructor) { CRYPTO_once(&g_thread_local_init_once, thread_local_init); if (g_thread_local_failed) { destructor(value); return 0; } void **pointers = pthread_getspecific(g_thread_local_key); if (pointers == NULL) { pointers = OPENSSL_malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); if (pointers == NULL) { destructor(value); return 0; } memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); if (pthread_setspecific(g_thread_local_key, pointers) != 0) { OPENSSL_free(pointers); destructor(value); return 0; } } if (pthread_mutex_lock(&g_destructors_lock) != 0) { destructor(value); return 0; } g_destructors[index] = destructor; pthread_mutex_unlock(&g_destructors_lock); pointers[index] = value; return 1; }
int CRYPTO_set_thread_local(thread_local_data_t index, void *value, thread_local_destructor_t destructor) { CRYPTO_once(&g_thread_local_init_once, thread_local_init); if (g_thread_local_failed) { destructor(value); return 0; } void **pointers = TlsGetValue(g_thread_local_key); if (pointers == NULL) { pointers = OPENSSL_malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); if (pointers == NULL) { destructor(value); return 0; } memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS); if (TlsSetValue(g_thread_local_key, pointers) == 0) { OPENSSL_free(pointers); destructor(value); return 0; } } EnterCriticalSection(&g_destructors_lock); g_destructors[index] = destructor; LeaveCriticalSection(&g_destructors_lock); pointers[index] = value; return 1; }
static void NTAPI thread_local_destructor(PVOID module, DWORD reason, PVOID reserved) { (void)module; (void)reserved; if (DLL_THREAD_DETACH != reason && DLL_PROCESS_DETACH != reason) { return; } CRYPTO_once(&g_thread_local_init_once, thread_local_init); if (g_thread_local_failed) { return; } void **pointers = (void**) TlsGetValue(g_thread_local_key); if (pointers == NULL) { return; } thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS]; EnterCriticalSection(&g_destructors_lock); memcpy(destructors, g_destructors, sizeof(destructors)); LeaveCriticalSection(&g_destructors_lock); unsigned i; for (i = 0; i < NUM_OPENSSL_THREAD_LOCALS; i++) { if (destructors[i] != NULL) { destructors[i](pointers[i]); } } OPENSSL_free(pointers); }
void RAND_enable_fork_unsafe_buffering(int fd) { if (fd >= 0) { fd = dup(fd); if (fd < 0) { abort(); } } else { fd = kUnset; } CRYPTO_STATIC_MUTEX_lock_write(&requested_lock); urandom_buffering_requested = 1; urandom_fd_requested = fd; CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock); CRYPTO_once(&once, init_once); if (urandom_buffering != 1) { abort(); // Already initialized } if (fd >= 0) { if (urandom_fd == kHaveGetrandom) { close(fd); } else if (urandom_fd != fd) { abort(); // Already initialized. } } }
void CRYPTO_library_init(void) { // TODO(davidben): It would be tidier if this build knob could be replaced // with an internal lazy-init mechanism that would handle things correctly // in-library. https://crbug.com/542879 #if defined(BORINGSSL_NO_STATIC_INITIALIZER) CRYPTO_once(&once, do_library_init); #endif }
void *CRYPTO_get_thread_local(thread_local_data_t index) { CRYPTO_once(&g_thread_local_init_once, thread_local_init); if (g_thread_local_failed) { return NULL; } void **pointers = TlsGetValue(g_thread_local_key); if (pointers == NULL) { return NULL; } return pointers[index]; }
void RAND_set_urandom_fd(int fd) { fd = dup(fd); if (fd < 0) { abort(); } CRYPTO_STATIC_MUTEX_lock_write(&requested_lock); urandom_fd_requested = fd; CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock); CRYPTO_once(&once, init_once); if (urandom_fd == kHaveGetrandom) { close(fd); } else if (urandom_fd != fd) { abort(); // Already initialized. } }
/* CRYPTO_sysrand puts |requested| random bytes into |out|. */ void CRYPTO_sysrand(uint8_t *out, size_t requested) { if (requested == 0) { return; } CRYPTO_once(&once, init_once); if (urandom_buffering && requested < BUF_SIZE) { struct rand_buffer *buf = get_thread_local_buffer(); if (buf != NULL) { read_from_buffer(buf, out, requested); return; } } if (!fill_with_entropy(out, requested)) { abort(); } }
static int test_once(void) { if (g_once_init_called != 0) { fprintf(stderr, "g_once_init_called was non-zero at start.\n"); return 0; } thread_t thread; if (!run_thread(&thread, call_once_thread) || !wait_for_thread(thread)) { fprintf(stderr, "thread failed.\n"); return 0; } CRYPTO_once(&g_test_once, once_init); if (g_once_init_called != 1) { fprintf(stderr, "Expected init function to be called once, but found %u.\n", g_once_init_called); return 0; } return 1; }
static EC_GROUP *ec_group_new_from_data(unsigned built_in_index) { const struct built_in_curve *curve = &OPENSSL_built_in_curves[built_in_index]; EC_GROUP *group = NULL; EC_POINT *P = NULL; BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; const EC_METHOD *meth; int ok = 0; BN_CTX *ctx = BN_CTX_new(); if (ctx == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); goto err; } const struct curve_data *data = curve->data; const unsigned param_len = data->param_len; const uint8_t *params = data->data; if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) || !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) || !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (curve->method != 0) { meth = curve->method(); if (((group = ec_group_new(meth)) == NULL) || (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } } else { if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } } if ((P = EC_POINT_new(group)) == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) || !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order) || !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } CRYPTO_once(&built_in_curve_scalar_field_monts_once, built_in_curve_scalar_field_monts_init); if (built_in_curve_scalar_field_monts != NULL) { group->mont_data = built_in_curve_scalar_field_monts[built_in_index]; } group->generator = P; P = NULL; ok = 1; err: if (!ok) { EC_GROUP_free(group); group = NULL; } EC_POINT_free(P); BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); BN_free(x); BN_free(y); return group; }
static void call_once_thread(void) { CRYPTO_once(&g_test_once, once_init); }