xref: /dragonfly/crypto/libressl/crypto/cryptlib.c (revision 6052a76a)
1 /* $OpenBSD: cryptlib.c,v 1.36 2015/09/13 10:02:49 miod Exp $ */
2 /* ====================================================================
3  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    openssl-core@openssl.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This product includes cryptographic software written by Eric Young
51  * (eay@cryptsoft.com).  This product includes software written by Tim
52  * Hudson (tjh@cryptsoft.com).
53  *
54  */
55 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
56  * All rights reserved.
57  *
58  * This package is an SSL implementation written
59  * by Eric Young (eay@cryptsoft.com).
60  * The implementation was written so as to conform with Netscapes SSL.
61  *
62  * This library is free for commercial and non-commercial use as long as
63  * the following conditions are aheared to.  The following conditions
64  * apply to all code found in this distribution, be it the RC4, RSA,
65  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
66  * included with this distribution is covered by the same copyright terms
67  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
68  *
69  * Copyright remains Eric Young's, and as such any Copyright notices in
70  * the code are not to be removed.
71  * If this package is used in a product, Eric Young should be given attribution
72  * as the author of the parts of the library used.
73  * This can be in the form of a textual message at program startup or
74  * in documentation (online or textual) provided with the package.
75  *
76  * Redistribution and use in source and binary forms, with or without
77  * modification, are permitted provided that the following conditions
78  * are met:
79  * 1. Redistributions of source code must retain the copyright
80  *    notice, this list of conditions and the following disclaimer.
81  * 2. Redistributions in binary form must reproduce the above copyright
82  *    notice, this list of conditions and the following disclaimer in the
83  *    documentation and/or other materials provided with the distribution.
84  * 3. All advertising materials mentioning features or use of this software
85  *    must display the following acknowledgement:
86  *    "This product includes cryptographic software written by
87  *     Eric Young (eay@cryptsoft.com)"
88  *    The word 'cryptographic' can be left out if the rouines from the library
89  *    being used are not cryptographic related :-).
90  * 4. If you include any Windows specific code (or a derivative thereof) from
91  *    the apps directory (application code) you must include an acknowledgement:
92  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
93  *
94  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
95  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
96  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
97  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
98  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
99  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
100  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
101  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
102  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
103  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
104  * SUCH DAMAGE.
105  *
106  * The licence and distribution terms for any publically available version or
107  * derivative of this code cannot be changed.  i.e. this code cannot simply be
108  * copied and put under another distribution licence
109  * [including the GNU Public Licence.]
110  */
111 /* ====================================================================
112  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
113  * ECDH support in OpenSSL originally developed by
114  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
115  */
116 
117 #include <limits.h>
118 #include <stdarg.h>
119 #include <stdint.h>
120 #include <string.h>
121 #include <unistd.h>
122 
123 #include <openssl/opensslconf.h>
124 
125 #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 
131 DECLARE_STACK_OF(CRYPTO_dynlock)
132 
133 /* real #defines in crypto.h, keep these upto date */
134 static 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.  */
183 static 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.  */
188 static STACK_OF(CRYPTO_dynlock) *dyn_locks = NULL;
189 
190 static void (*locking_callback)(int mode, int type,
191     const char *file, int line) = 0;
192 static int (*add_lock_callback)(int *pointer, int amount,
193     int type, const char *file, int line) = 0;
194 #ifndef OPENSSL_NO_DEPRECATED
195 static unsigned long (*id_callback)(void) = 0;
196 #endif
197 static void (*threadid_callback)(CRYPTO_THREADID *) = 0;
198 static struct CRYPTO_dynlock_value *(*dynlock_create_callback)(
199     const char *file, int line) = 0;
200 static void (*dynlock_lock_callback)(int mode,
201     struct CRYPTO_dynlock_value *l, const char *file, int line) = 0;
202 static void (*dynlock_destroy_callback)(struct CRYPTO_dynlock_value *l,
203     const char *file, int line) = 0;
204 
205 int
206 CRYPTO_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 		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, ERR_R_MALLOC_FAILURE);
214 		return (0);
215 	}
216 	if (name == NULL || (str = strdup(name)) == NULL) {
217 		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, 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 
228 int
229 CRYPTO_num_locks(void)
230 {
231 	return CRYPTO_NUM_LOCKS;
232 }
233 
234 int
235 CRYPTO_get_new_dynlockid(void)
236 {
237 	int i = 0;
238 	CRYPTO_dynlock *pointer = NULL;
239 
240 	if (dynlock_create_callback == NULL) {
241 		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,
242 		    CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK);
243 		return (0);
244 	}
245 	CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
246 	if ((dyn_locks == NULL) &&
247 	    ((dyn_locks = sk_CRYPTO_dynlock_new_null()) == NULL)) {
248 		CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
249 		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,
250 		    ERR_R_MALLOC_FAILURE);
251 		return (0);
252 	}
253 	CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
254 
255 	pointer = malloc(sizeof(CRYPTO_dynlock));
256 	if (pointer == NULL) {
257 		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,
258 		    ERR_R_MALLOC_FAILURE);
259 		return (0);
260 	}
261 	pointer->references = 1;
262 	pointer->data = dynlock_create_callback(__FILE__, __LINE__);
263 	if (pointer->data == NULL) {
264 		free(pointer);
265 		CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,
266 		    ERR_R_MALLOC_FAILURE);
267 		return (0);
268 	}
269 
270 	CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
271 	/* First, try to find an existing empty slot */
272 	i = sk_CRYPTO_dynlock_find(dyn_locks, NULL);
273 	/* If there was none, push, thereby creating a new one */
274 	if (i == -1)
275 		/* Since sk_push() returns the number of items on the
276 		   stack, not the location of the pushed item, we need
277 		   to transform the returned number into a position,
278 		   by decreasing it.  */
279 		i = sk_CRYPTO_dynlock_push(dyn_locks, pointer) - 1;
280 	else
281 		/* If we found a place with a NULL pointer, put our pointer
282 		   in it.  */
283 		(void)sk_CRYPTO_dynlock_set(dyn_locks, i, pointer);
284 	CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
285 
286 	if (i == -1) {
287 		dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
288 		free(pointer);
289 	} else
290 		i += 1; /* to avoid 0 */
291 	return -i;
292 }
293 
294 void
295 CRYPTO_destroy_dynlockid(int i)
296 {
297 	CRYPTO_dynlock *pointer = NULL;
298 
299 	if (i)
300 		i = -i - 1;
301 	if (dynlock_destroy_callback == NULL)
302 		return;
303 
304 	CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
305 
306 	if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) {
307 		CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
308 		return;
309 	}
310 	pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
311 	if (pointer != NULL) {
312 		--pointer->references;
313 		if (pointer->references <= 0) {
314 			(void)sk_CRYPTO_dynlock_set(dyn_locks, i, NULL);
315 		} else
316 			pointer = NULL;
317 	}
318 	CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
319 
320 	if (pointer) {
321 		dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
322 		free(pointer);
323 	}
324 }
325 
326 struct CRYPTO_dynlock_value *
327 CRYPTO_get_dynlock_value(int i)
328 {
329 	CRYPTO_dynlock *pointer = NULL;
330 
331 	if (i)
332 		i = -i - 1;
333 
334 	CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
335 
336 	if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks))
337 		pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
338 	if (pointer)
339 		pointer->references++;
340 
341 	CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
342 
343 	if (pointer)
344 		return pointer->data;
345 	return NULL;
346 }
347 
348 struct CRYPTO_dynlock_value *
349 (*CRYPTO_get_dynlock_create_callback(void))(const char *file, int line)
350 {
351 	return (dynlock_create_callback);
352 }
353 
354 void
355 (*CRYPTO_get_dynlock_lock_callback(void))(int mode,
356     struct CRYPTO_dynlock_value *l, const char *file, int line)
357 {
358 	return (dynlock_lock_callback);
359 }
360 
361 void
362 (*CRYPTO_get_dynlock_destroy_callback(void))(struct CRYPTO_dynlock_value *l,
363     const char *file, int line)
364 {
365 	return (dynlock_destroy_callback);
366 }
367 
368 void
369 CRYPTO_set_dynlock_create_callback(
370     struct CRYPTO_dynlock_value *(*func)(const char *file, int line))
371 {
372 	dynlock_create_callback = func;
373 }
374 
375 void
376 CRYPTO_set_dynlock_lock_callback(void (*func)(int mode,
377     struct CRYPTO_dynlock_value *l, const char *file, int line))
378 {
379 	dynlock_lock_callback = func;
380 }
381 
382 void
383 CRYPTO_set_dynlock_destroy_callback(
384     void (*func)(struct CRYPTO_dynlock_value *l, const char *file, int line))
385 {
386 	dynlock_destroy_callback = func;
387 }
388 
389 void
390 (*CRYPTO_get_locking_callback(void))(int mode, int type, const char *file,
391     int line)
392 {
393 	return (locking_callback);
394 }
395 
396 int
397 (*CRYPTO_get_add_lock_callback(void))(int *num, int mount, int type,
398     const char *file, int line)
399 {
400 	return (add_lock_callback);
401 }
402 
403 void
404 CRYPTO_set_locking_callback(void (*func)(int mode, int type,
405     const char *file, int line))
406 {
407 	/* Calling this here ensures initialisation before any threads
408 	 * are started.
409 	 */
410 	OPENSSL_init();
411 	locking_callback = func;
412 }
413 
414 void
415 CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int type,
416     const char *file, int line))
417 {
418 	add_lock_callback = func;
419 }
420 
421 /* the memset() here and in set_pointer() seem overkill, but for the sake of
422  * CRYPTO_THREADID_cmp() this avoids any platform silliness that might cause two
423  * "equal" THREADID structs to not be memcmp()-identical. */
424 void
425 CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val)
426 {
427 	memset(id, 0, sizeof(*id));
428 	id->val = val;
429 }
430 
431 void
432 CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr)
433 {
434 	memset(id, 0, sizeof(*id));
435 	id->ptr = ptr;
436 #if ULONG_MAX >= UINTPTR_MAX
437 	/*s u 'ptr' can be embedded in 'val' without loss of uniqueness */
438 	id->val = (uintptr_t)id->ptr;
439 #else
440 	{
441 		SHA256_CTX ctx;
442 		uint8_t results[SHA256_DIGEST_LENGTH];
443 
444 		SHA256_Init(&ctx);
445 		SHA256_Update(&ctx, (char *)(&id->ptr), sizeof(id->ptr));
446 		SHA256_Final(results, &ctx);
447 		memcpy(&id->val, results, sizeof(id->val));
448 	}
449 #endif
450 }
451 
452 int
453 CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *))
454 {
455 	if (threadid_callback)
456 		return 0;
457 	threadid_callback = func;
458 	return 1;
459 }
460 
461 void (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *)
462 {
463 	return threadid_callback;
464 }
465 
466 void
467 CRYPTO_THREADID_current(CRYPTO_THREADID *id)
468 {
469 	if (threadid_callback) {
470 		threadid_callback(id);
471 		return;
472 	}
473 #ifndef OPENSSL_NO_DEPRECATED
474 	/* If the deprecated callback was set, fall back to that */
475 	if (id_callback) {
476 		CRYPTO_THREADID_set_numeric(id, id_callback());
477 		return;
478 	}
479 #endif
480 	/* Else pick a backup */
481 	/* For everything else, default to using the address of 'errno' */
482 	CRYPTO_THREADID_set_pointer(id, (void*)&errno);
483 }
484 
485 int
486 CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b)
487 {
488 	return memcmp(a, b, sizeof(*a));
489 }
490 
491 void
492 CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src)
493 {
494 	memcpy(dest, src, sizeof(*src));
495 }
496 
497 unsigned long
498 CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
499 {
500 	return id->val;
501 }
502 
503 #ifndef OPENSSL_NO_DEPRECATED
504 unsigned long (*CRYPTO_get_id_callback(void))(void)
505 {
506 	return (id_callback);
507 }
508 
509 void
510 CRYPTO_set_id_callback(unsigned long (*func)(void))
511 {
512 	id_callback = func;
513 }
514 
515 unsigned long
516 CRYPTO_thread_id(void)
517 {
518 	unsigned long ret = 0;
519 
520 	if (id_callback == NULL) {
521 		ret = (unsigned long)getpid();
522 	} else
523 		ret = id_callback();
524 	return (ret);
525 }
526 #endif
527 
528 void
529 CRYPTO_lock(int mode, int type, const char *file, int line)
530 {
531 #ifdef LOCK_DEBUG
532 	{
533 		CRYPTO_THREADID id;
534 		char *rw_text, *operation_text;
535 
536 		if (mode & CRYPTO_LOCK)
537 			operation_text = "lock  ";
538 		else if (mode & CRYPTO_UNLOCK)
539 			operation_text = "unlock";
540 		else
541 			operation_text = "ERROR ";
542 
543 		if (mode & CRYPTO_READ)
544 			rw_text = "r";
545 		else if (mode & CRYPTO_WRITE)
546 			rw_text = "w";
547 		else
548 			rw_text = "ERROR";
549 
550 		CRYPTO_THREADID_current(&id);
551 		fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n",
552 		    CRYPTO_THREADID_hash(&id), rw_text, operation_text,
553 		    CRYPTO_get_lock_name(type), file, line);
554 	}
555 #endif
556 	if (type < 0) {
557 		if (dynlock_lock_callback != NULL) {
558 			struct CRYPTO_dynlock_value *pointer =
559 			    CRYPTO_get_dynlock_value(type);
560 
561 			OPENSSL_assert(pointer != NULL);
562 
563 			dynlock_lock_callback(mode, pointer, file, line);
564 
565 			CRYPTO_destroy_dynlockid(type);
566 		}
567 	} else if (locking_callback != NULL)
568 		locking_callback(mode, type, file, line);
569 }
570 
571 int
572 CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
573     int line)
574 {
575 	int ret = 0;
576 
577 	if (add_lock_callback != NULL) {
578 #ifdef LOCK_DEBUG
579 		int before= *pointer;
580 #endif
581 
582 		ret = add_lock_callback(pointer, amount, type, file, line);
583 #ifdef LOCK_DEBUG
584 		{
585 			CRYPTO_THREADID id;
586 			CRYPTO_THREADID_current(&id);
587 			fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
588 			    CRYPTO_THREADID_hash(&id), before, amount, ret,
589 			    CRYPTO_get_lock_name(type),
590 			    file, line);
591 		}
592 #endif
593 	} else {
594 		CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE, type, file, line);
595 
596 		ret= *pointer + amount;
597 #ifdef LOCK_DEBUG
598 		{
599 			CRYPTO_THREADID id;
600 			CRYPTO_THREADID_current(&id);
601 			fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
602 			    CRYPTO_THREADID_hash(&id), *pointer, amount, ret,
603 			    CRYPTO_get_lock_name(type), file, line);
604 		}
605 #endif
606 		*pointer = ret;
607 		CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE, type, file, line);
608 	}
609 	return (ret);
610 }
611 
612 const char *
613 CRYPTO_get_lock_name(int type)
614 {
615 	if (type < 0)
616 		return("dynamic");
617 	else if (type < CRYPTO_NUM_LOCKS)
618 		return (lock_names[type]);
619 	else if (type - CRYPTO_NUM_LOCKS > sk_OPENSSL_STRING_num(app_locks))
620 		return("ERROR");
621 	else
622 		return (sk_OPENSSL_STRING_value(app_locks,
623 		    type - CRYPTO_NUM_LOCKS));
624 }
625 
626 #if	defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
627 	defined(__INTEL__) || \
628 	defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
629 
630 unsigned int  OPENSSL_ia32cap_P[2];
631 
632 uint64_t
633 OPENSSL_cpu_caps(void)
634 {
635 	return *(uint64_t *)OPENSSL_ia32cap_P;
636 }
637 
638 #if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
639 #define OPENSSL_CPUID_SETUP
640 typedef unsigned long long IA32CAP;
641 void
642 OPENSSL_cpuid_setup(void)
643 {
644 	static int trigger = 0;
645 	IA32CAP OPENSSL_ia32_cpuid(void);
646 	IA32CAP vec;
647 
648 	if (trigger)
649 		return;
650 	trigger = 1;
651 
652 	vec = OPENSSL_ia32_cpuid();
653 
654 	/*
655 	 * |(1<<10) sets a reserved bit to signal that variable
656 	 * was initialized already... This is to avoid interference
657 	 * with cpuid snippets in ELF .init segment.
658 	 */
659 	OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10);
660 	OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32);
661 }
662 #endif
663 
664 #else
665 unsigned long *
666 OPENSSL_ia32cap_loc(void)
667 {
668 	return NULL;
669 }
670 
671 uint64_t
672 OPENSSL_cpu_caps(void)
673 {
674 	return 0;
675 }
676 #endif
677 
678 #if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ)
679 void
680 OPENSSL_cpuid_setup(void)
681 {
682 }
683 #endif
684 
685 static void
686 OPENSSL_showfatal(const char *fmta, ...)
687 {
688 	va_list ap;
689 
690 	va_start(ap, fmta);
691 	vfprintf(stderr, fmta, ap);
692 	va_end(ap);
693 }
694 
695 void
696 OpenSSLDie(const char *file, int line, const char *assertion)
697 {
698 	OPENSSL_showfatal(
699 	    "%s(%d): OpenSSL internal error, assertion failed: %s\n",
700 	    file, line, assertion);
701 	abort();
702 }
703 
704 int
705 CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
706 {
707 	size_t i;
708 	const unsigned char *a = in_a;
709 	const unsigned char *b = in_b;
710 	unsigned char x = 0;
711 
712 	for (i = 0; i < len; i++)
713 		x |= a[i] ^ b[i];
714 
715 	return x;
716 }
717