summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/cryptlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/cryptlib.c')
-rw-r--r--src/lib/libcrypto/cryptlib.c469
1 files changed, 54 insertions, 415 deletions
diff --git a/src/lib/libcrypto/cryptlib.c b/src/lib/libcrypto/cryptlib.c
index f7b783a029..e10b4f0b58 100644
--- a/src/lib/libcrypto/cryptlib.c
+++ b/src/lib/libcrypto/cryptlib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: cryptlib.c,v 1.41 2017/04/29 21:48:43 jsing Exp $ */ 1/* $OpenBSD: cryptlib.c,v 1.42 2018/11/11 06:41:28 bcook Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
4 * 4 *
@@ -114,367 +114,129 @@
114 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. 114 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
115 */ 115 */
116 116
117#include <limits.h> 117#include <pthread.h>
118#include <stdarg.h> 118#include <stdarg.h>
119#include <stdint.h> 119#include <stdio.h>
120#include <string.h> 120#include <string.h>
121#include <unistd.h>
122 121
123#include <openssl/opensslconf.h> 122#include <openssl/opensslconf.h>
124
125#include <openssl/crypto.h> 123#include <openssl/crypto.h>
126#include <openssl/buffer.h>
127#include <openssl/err.h>
128#include <openssl/safestack.h>
129#include <openssl/sha.h>
130
131DECLARE_STACK_OF(CRYPTO_dynlock)
132
133/* real #defines in crypto.h, keep these upto date */
134static const char* const lock_names[CRYPTO_NUM_LOCKS] = {
135 "<<ERROR>>",
136 "err",
137 "ex_data",
138 "x509",
139 "x509_info",
140 "x509_pkey",
141 "x509_crl",
142 "x509_req",
143 "dsa",
144 "rsa",
145 "evp_pkey",
146 "x509_store",
147 "ssl_ctx",
148 "ssl_cert",
149 "ssl_session",
150 "ssl_sess_cert",
151 "ssl",
152 "ssl_method",
153 "rand",
154 "rand2",
155 "debug_malloc",
156 "BIO",
157 "gethostbyname",
158 "getservbyname",
159 "readdir",
160 "RSA_blinding",
161 "dh",
162 "debug_malloc2",
163 "dso",
164 "dynlock",
165 "engine",
166 "ui",
167 "ecdsa",
168 "ec",
169 "ecdh",
170 "bn",
171 "ec_pre_comp",
172 "store",
173 "comp",
174 "fips",
175 "fips2",
176#if CRYPTO_NUM_LOCKS != 41
177# error "Inconsistency between crypto.h and cryptlib.c"
178#endif
179};
180
181/* This is for applications to allocate new type names in the non-dynamic
182 array of lock names. These are numbered with positive numbers. */
183static STACK_OF(OPENSSL_STRING) *app_locks = NULL;
184
185/* For applications that want a more dynamic way of handling threads, the
186 following stack is used. These are externally numbered with negative
187 numbers. */
188static STACK_OF(CRYPTO_dynlock) *dyn_locks = NULL;
189
190static void (*locking_callback)(int mode, int type,
191 const char *file, int line) = 0;
192static int (*add_lock_callback)(int *pointer, int amount,
193 int type, const char *file, int line) = 0;
194#ifndef OPENSSL_NO_DEPRECATED
195static unsigned long (*id_callback)(void) = 0;
196#endif
197static void (*threadid_callback)(CRYPTO_THREADID *) = 0;
198static struct CRYPTO_dynlock_value *(*dynlock_create_callback)(
199 const char *file, int line) = 0;
200static void (*dynlock_lock_callback)(int mode,
201 struct CRYPTO_dynlock_value *l, const char *file, int line) = 0;
202static void (*dynlock_destroy_callback)(struct CRYPTO_dynlock_value *l,
203 const char *file, int line) = 0;
204
205int
206CRYPTO_get_new_lockid(char *name)
207{
208 char *str;
209 int i;
210
211 if ((app_locks == NULL) &&
212 ((app_locks = sk_OPENSSL_STRING_new_null()) == NULL)) {
213 CRYPTOerror(ERR_R_MALLOC_FAILURE);
214 return (0);
215 }
216 if (name == NULL || (str = strdup(name)) == NULL) {
217 CRYPTOerror(ERR_R_MALLOC_FAILURE);
218 return (0);
219 }
220 i = sk_OPENSSL_STRING_push(app_locks, str);
221 if (!i)
222 free(str);
223 else
224 i += CRYPTO_NUM_LOCKS; /* gap of one :-) */
225 return (i);
226}
227 124
228int 125int
229CRYPTO_num_locks(void) 126CRYPTO_num_locks(void)
230{ 127{
231 return CRYPTO_NUM_LOCKS; 128 return 1;
232} 129}
233 130
234int 131unsigned long (*CRYPTO_get_id_callback(void))(void)
235CRYPTO_get_new_dynlockid(void)
236{ 132{
237 int i = 0; 133 return NULL;
238 CRYPTO_dynlock *pointer = NULL;
239
240 if (dynlock_create_callback == NULL) {
241 CRYPTOerror(CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK);
242 return (0);
243 }
244 CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
245 if ((dyn_locks == NULL) &&
246 ((dyn_locks = sk_CRYPTO_dynlock_new_null()) == NULL)) {
247 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
248 CRYPTOerror(ERR_R_MALLOC_FAILURE);
249 return (0);
250 }
251 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
252
253 pointer = malloc(sizeof(CRYPTO_dynlock));
254 if (pointer == NULL) {
255 CRYPTOerror(ERR_R_MALLOC_FAILURE);
256 return (0);
257 }
258 pointer->references = 1;
259 pointer->data = dynlock_create_callback(__FILE__, __LINE__);
260 if (pointer->data == NULL) {
261 free(pointer);
262 CRYPTOerror(ERR_R_MALLOC_FAILURE);
263 return (0);
264 }
265
266 CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
267 /* First, try to find an existing empty slot */
268 i = sk_CRYPTO_dynlock_find(dyn_locks, NULL);
269 /* If there was none, push, thereby creating a new one */
270 if (i == -1)
271 /* Since sk_push() returns the number of items on the
272 stack, not the location of the pushed item, we need
273 to transform the returned number into a position,
274 by decreasing it. */
275 i = sk_CRYPTO_dynlock_push(dyn_locks, pointer) - 1;
276 else
277 /* If we found a place with a NULL pointer, put our pointer
278 in it. */
279 (void)sk_CRYPTO_dynlock_set(dyn_locks, i, pointer);
280 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
281
282 if (i == -1) {
283 dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
284 free(pointer);
285 } else
286 i += 1; /* to avoid 0 */
287 return -i;
288} 134}
289 135
290void 136void
291CRYPTO_destroy_dynlockid(int i) 137CRYPTO_set_id_callback(unsigned long (*func)(void))
292{
293 CRYPTO_dynlock *pointer = NULL;
294
295 if (i)
296 i = -i - 1;
297 if (dynlock_destroy_callback == NULL)
298 return;
299
300 CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
301
302 if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) {
303 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
304 return;
305 }
306 pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
307 if (pointer != NULL) {
308 --pointer->references;
309 if (pointer->references <= 0) {
310 (void)sk_CRYPTO_dynlock_set(dyn_locks, i, NULL);
311 } else
312 pointer = NULL;
313 }
314 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
315
316 if (pointer) {
317 dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
318 free(pointer);
319 }
320}
321
322struct CRYPTO_dynlock_value *
323CRYPTO_get_dynlock_value(int i)
324{ 138{
325 CRYPTO_dynlock *pointer = NULL; 139 return;
326
327 if (i)
328 i = -i - 1;
329
330 CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
331
332 if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks))
333 pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
334 if (pointer)
335 pointer->references++;
336
337 CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
338
339 if (pointer)
340 return pointer->data;
341 return NULL;
342} 140}
343 141
344struct CRYPTO_dynlock_value * 142unsigned long
345(*CRYPTO_get_dynlock_create_callback(void))(const char *file, int line) 143CRYPTO_thread_id(void)
346{ 144{
347 return (dynlock_create_callback); 145 return (unsigned long)pthread_self();
348} 146}
349 147
350void 148void
351(*CRYPTO_get_dynlock_lock_callback(void))(int mode, 149CRYPTO_set_locking_callback(void (*func)(int mode, int lock_num,
352 struct CRYPTO_dynlock_value *l, const char *file, int line) 150 const char *file, int line))
353{ 151{
354 return (dynlock_lock_callback); 152 return;
355} 153}
356 154
357void 155void
358(*CRYPTO_get_dynlock_destroy_callback(void))(struct CRYPTO_dynlock_value *l, 156(*CRYPTO_get_locking_callback(void))(int mode, int lock_num,
359 const char *file, int line) 157 const char *file, int line)
360{ 158{
361 return (dynlock_destroy_callback); 159 return NULL;
362} 160}
363 161
364void 162void
365CRYPTO_set_dynlock_create_callback( 163CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int lock_num,
366 struct CRYPTO_dynlock_value *(*func)(const char *file, int line)) 164 const char *file, int line))
367{ 165{
368 dynlock_create_callback = func; 166 return;
369} 167}
370 168
371void 169const char *
372CRYPTO_set_dynlock_lock_callback(void (*func)(int mode, 170CRYPTO_get_lock_name(int lock_num)
373 struct CRYPTO_dynlock_value *l, const char *file, int line))
374{ 171{
375 dynlock_lock_callback = func; 172 return "";
376} 173}
377 174
378void 175int
379CRYPTO_set_dynlock_destroy_callback( 176CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *))
380 void (*func)(struct CRYPTO_dynlock_value *l, const char *file, int line))
381{ 177{
382 dynlock_destroy_callback = func; 178 return 1;
383} 179}
384 180
385void 181void
386(*CRYPTO_get_locking_callback(void))(int mode, int type, const char *file, 182CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val)
387 int line)
388{ 183{
389 return (locking_callback); 184 return;
390} 185}
391 186
392int 187void
393(*CRYPTO_get_add_lock_callback(void))(int *num, int mount, int type, 188CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr)
394 const char *file, int line)
395{ 189{
396 return (add_lock_callback); 190 return;
397} 191}
398 192
399void 193void
400CRYPTO_set_locking_callback(void (*func)(int mode, int type, 194CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(
401 const char *file, int line)) 195 *dyn_create_function)(const char *file, int line))
402{ 196{
403 /* Calling this here ensures initialisation before any threads 197 return;
404 * are started.
405 */
406 locking_callback = func;
407} 198}
408 199
409void 200void
410CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int type, 201CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(
411 const char *file, int line)) 202 int mode, struct CRYPTO_dynlock_value *l, const char *file, int line))
412{ 203{
413 add_lock_callback = func; 204 return;
414} 205}
415 206
416/* the memset() here and in set_pointer() seem overkill, but for the sake of
417 * CRYPTO_THREADID_cmp() this avoids any platform silliness that might cause two
418 * "equal" THREADID structs to not be memcmp()-identical. */
419void 207void
420CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val) 208CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)(
209 struct CRYPTO_dynlock_value *l, const char *file, int line))
421{ 210{
422 memset(id, 0, sizeof(*id)); 211 return;
423 id->val = val;
424} 212}
425 213
426void 214struct CRYPTO_dynlock_value *
427CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr) 215(*CRYPTO_get_dynlock_create_callback(void))(
216 const char *file, int line)
428{ 217{
429 memset(id, 0, sizeof(*id)); 218 return NULL;
430 id->ptr = ptr;
431#if ULONG_MAX >= UINTPTR_MAX
432 /*s u 'ptr' can be embedded in 'val' without loss of uniqueness */
433 id->val = (uintptr_t)id->ptr;
434#else
435 {
436 SHA256_CTX ctx;
437 uint8_t results[SHA256_DIGEST_LENGTH];
438
439 SHA256_Init(&ctx);
440 SHA256_Update(&ctx, (char *)(&id->ptr), sizeof(id->ptr));
441 SHA256_Final(results, &ctx);
442 memcpy(&id->val, results, sizeof(id->val));
443 }
444#endif
445} 219}
446 220
447int 221void
448CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *)) 222(*CRYPTO_get_dynlock_lock_callback(void))(int mode,
223 struct CRYPTO_dynlock_value *l, const char *file, int line)
449{ 224{
450 if (threadid_callback) 225 return NULL;
451 return 0;
452 threadid_callback = func;
453 return 1;
454} 226}
455 227
456void (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *) 228void
229(*CRYPTO_get_dynlock_destroy_callback(void))(
230 struct CRYPTO_dynlock_value *l, const char *file, int line)
457{ 231{
458 return threadid_callback; 232 return NULL;
459} 233}
460 234
461void 235void
462CRYPTO_THREADID_current(CRYPTO_THREADID *id) 236CRYPTO_THREADID_current(CRYPTO_THREADID *id)
463{ 237{
464 if (threadid_callback) { 238 memset(id, 0, sizeof(*id));
465 threadid_callback(id); 239 id->val = (unsigned long)pthread_self();
466 return;
467 }
468#ifndef OPENSSL_NO_DEPRECATED
469 /* If the deprecated callback was set, fall back to that */
470 if (id_callback) {
471 CRYPTO_THREADID_set_numeric(id, id_callback());
472 return;
473 }
474#endif
475 /* Else pick a backup */
476 /* For everything else, default to using the address of 'errno' */
477 CRYPTO_THREADID_set_pointer(id, (void*)&errno);
478} 240}
479 241
480int 242int
@@ -495,129 +257,6 @@ CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
495 return id->val; 257 return id->val;
496} 258}
497 259
498#ifndef OPENSSL_NO_DEPRECATED
499unsigned long (*CRYPTO_get_id_callback(void))(void)
500{
501 return (id_callback);
502}
503
504void
505CRYPTO_set_id_callback(unsigned long (*func)(void))
506{
507 id_callback = func;
508}
509
510unsigned long
511CRYPTO_thread_id(void)
512{
513 unsigned long ret = 0;
514
515 if (id_callback == NULL) {
516 ret = (unsigned long)getpid();
517 } else
518 ret = id_callback();
519 return (ret);
520}
521#endif
522
523void
524CRYPTO_lock(int mode, int type, const char *file, int line)
525{
526#ifdef LOCK_DEBUG
527 {
528 CRYPTO_THREADID id;
529 char *rw_text, *operation_text;
530
531 if (mode & CRYPTO_LOCK)
532 operation_text = "lock ";
533 else if (mode & CRYPTO_UNLOCK)
534 operation_text = "unlock";
535 else
536 operation_text = "ERROR ";
537
538 if (mode & CRYPTO_READ)
539 rw_text = "r";
540 else if (mode & CRYPTO_WRITE)
541 rw_text = "w";
542 else
543 rw_text = "ERROR";
544
545 CRYPTO_THREADID_current(&id);
546 fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n",
547 CRYPTO_THREADID_hash(&id), rw_text, operation_text,
548 CRYPTO_get_lock_name(type), file, line);
549 }
550#endif
551 if (type < 0) {
552 if (dynlock_lock_callback != NULL) {
553 struct CRYPTO_dynlock_value *pointer =
554 CRYPTO_get_dynlock_value(type);
555
556 OPENSSL_assert(pointer != NULL);
557
558 dynlock_lock_callback(mode, pointer, file, line);
559
560 CRYPTO_destroy_dynlockid(type);
561 }
562 } else if (locking_callback != NULL)
563 locking_callback(mode, type, file, line);
564}
565
566int
567CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
568 int line)
569{
570 int ret = 0;
571
572 if (add_lock_callback != NULL) {
573#ifdef LOCK_DEBUG
574 int before= *pointer;
575#endif
576
577 ret = add_lock_callback(pointer, amount, type, file, line);
578#ifdef LOCK_DEBUG
579 {
580 CRYPTO_THREADID id;
581 CRYPTO_THREADID_current(&id);
582 fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
583 CRYPTO_THREADID_hash(&id), before, amount, ret,
584 CRYPTO_get_lock_name(type),
585 file, line);
586 }
587#endif
588 } else {
589 CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE, type, file, line);
590
591 ret= *pointer + amount;
592#ifdef LOCK_DEBUG
593 {
594 CRYPTO_THREADID id;
595 CRYPTO_THREADID_current(&id);
596 fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
597 CRYPTO_THREADID_hash(&id), *pointer, amount, ret,
598 CRYPTO_get_lock_name(type), file, line);
599 }
600#endif
601 *pointer = ret;
602 CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE, type, file, line);
603 }
604 return (ret);
605}
606
607const char *
608CRYPTO_get_lock_name(int type)
609{
610 if (type < 0)
611 return("dynamic");
612 else if (type < CRYPTO_NUM_LOCKS)
613 return (lock_names[type]);
614 else if (type - CRYPTO_NUM_LOCKS > sk_OPENSSL_STRING_num(app_locks))
615 return("ERROR");
616 else
617 return (sk_OPENSSL_STRING_value(app_locks,
618 type - CRYPTO_NUM_LOCKS));
619}
620
621#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ 260#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
622 defined(__INTEL__) || \ 261 defined(__INTEL__) || \
623 defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) 262 defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)