Line data Source code
1 : /* crypto/cryptlib.c */
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 "cryptlib.h"
118 : #include <openssl/safestack.h>
119 :
120 : #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
121 : static double SSLeay_MSVC5_hack = 0.0; /* and for VC1.5 */
122 : #endif
123 :
124 : DECLARE_STACK_OF(CRYPTO_dynlock)
125 :
126 : /* real #defines in crypto.h, keep these upto date */
127 : static const char *const lock_names[CRYPTO_NUM_LOCKS] = {
128 : "<<ERROR>>",
129 : "err",
130 : "ex_data",
131 : "x509",
132 : "x509_info",
133 : "x509_pkey",
134 : "x509_crl",
135 : "x509_req",
136 : "dsa",
137 : "rsa",
138 : "evp_pkey",
139 : "x509_store",
140 : "ssl_ctx",
141 : "ssl_cert",
142 : "ssl_session",
143 : "ssl_sess_cert",
144 : "ssl",
145 : "ssl_method",
146 : "rand",
147 : "rand2",
148 : "debug_malloc",
149 : "BIO",
150 : "gethostbyname",
151 : "getservbyname",
152 : "readdir",
153 : "RSA_blinding",
154 : "dh",
155 : "debug_malloc2",
156 : "dso",
157 : "dynlock",
158 : "engine",
159 : "ui",
160 : "ecdsa",
161 : "ec",
162 : "ecdh",
163 : "bn",
164 : "ec_pre_comp",
165 : "store",
166 : "comp",
167 : "fips",
168 : "fips2",
169 : #if CRYPTO_NUM_LOCKS != 41
170 : # error "Inconsistency between crypto.h and cryptlib.c"
171 : #endif
172 : };
173 :
174 : /*
175 : * This is for applications to allocate new type names in the non-dynamic
176 : * array of lock names. These are numbered with positive numbers.
177 : */
178 : static STACK_OF(OPENSSL_STRING) *app_locks = NULL;
179 :
180 : /*
181 : * For applications that want a more dynamic way of handling threads, the
182 : * following stack is used. These are externally numbered with negative
183 : * numbers.
184 : */
185 : static STACK_OF(CRYPTO_dynlock) *dyn_locks = NULL;
186 :
187 : static void (MS_FAR *locking_callback) (int mode, int type,
188 : const char *file, int line) = 0;
189 : static int (MS_FAR *add_lock_callback) (int *pointer, int amount,
190 : int type, const char *file,
191 : int line) = 0;
192 : #ifndef OPENSSL_NO_DEPRECATED
193 : static unsigned long (MS_FAR *id_callback) (void) = 0;
194 : #endif
195 : static void (MS_FAR *threadid_callback) (CRYPTO_THREADID *) = 0;
196 : static struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback)
197 : (const char *file, int line) = 0;
198 : static void (MS_FAR *dynlock_lock_callback) (int mode,
199 : struct CRYPTO_dynlock_value *l,
200 : const char *file, int line) = 0;
201 : static void (MS_FAR *dynlock_destroy_callback) (struct CRYPTO_dynlock_value
202 : *l, const char *file,
203 : int line) = 0;
204 :
205 0 : int CRYPTO_get_new_lockid(char *name)
206 : {
207 : char *str;
208 : int i;
209 :
210 : #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
211 : /*
212 : * A hack to make Visual C++ 5.0 work correctly when linking as a DLL
213 : * using /MT. Without this, the application cannot use any floating point
214 : * printf's. It also seems to be needed for Visual C 1.5 (win16)
215 : */
216 : SSLeay_MSVC5_hack = (double)name[0] * (double)name[1];
217 : #endif
218 :
219 0 : if ((app_locks == NULL)
220 0 : && ((app_locks = sk_OPENSSL_STRING_new_null()) == NULL)) {
221 0 : CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, ERR_R_MALLOC_FAILURE);
222 0 : return (0);
223 : }
224 0 : if ((str = BUF_strdup(name)) == NULL) {
225 0 : CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, ERR_R_MALLOC_FAILURE);
226 0 : return (0);
227 : }
228 0 : i = sk_OPENSSL_STRING_push(app_locks, str);
229 0 : if (!i)
230 0 : OPENSSL_free(str);
231 : else
232 0 : i += CRYPTO_NUM_LOCKS; /* gap of one :-) */
233 0 : return (i);
234 : }
235 :
236 5203 : int CRYPTO_num_locks(void)
237 : {
238 5203 : return CRYPTO_NUM_LOCKS;
239 : }
240 :
241 0 : int CRYPTO_get_new_dynlockid(void)
242 : {
243 : int i = 0;
244 : CRYPTO_dynlock *pointer = NULL;
245 :
246 0 : if (dynlock_create_callback == NULL) {
247 0 : CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,
248 : CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK);
249 0 : return (0);
250 : }
251 0 : CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
252 0 : if ((dyn_locks == NULL)
253 0 : && ((dyn_locks = sk_CRYPTO_dynlock_new_null()) == NULL)) {
254 0 : CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
255 0 : CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
256 0 : return (0);
257 : }
258 0 : CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
259 :
260 0 : pointer = (CRYPTO_dynlock *) OPENSSL_malloc(sizeof(CRYPTO_dynlock));
261 0 : if (pointer == NULL) {
262 0 : CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
263 0 : return (0);
264 : }
265 0 : pointer->references = 1;
266 0 : pointer->data = dynlock_create_callback(__FILE__, __LINE__);
267 0 : if (pointer->data == NULL) {
268 0 : OPENSSL_free(pointer);
269 0 : CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
270 0 : return (0);
271 : }
272 :
273 0 : CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
274 : /* First, try to find an existing empty slot */
275 0 : i = sk_CRYPTO_dynlock_find(dyn_locks, NULL);
276 : /* If there was none, push, thereby creating a new one */
277 0 : if (i == -1)
278 : /*
279 : * Since sk_push() returns the number of items on the stack, not the
280 : * location of the pushed item, we need to transform the returned
281 : * number into a position, by decreasing it.
282 : */
283 0 : i = sk_CRYPTO_dynlock_push(dyn_locks, pointer) - 1;
284 : else
285 : /*
286 : * If we found a place with a NULL pointer, put our pointer in it.
287 : */
288 0 : (void)sk_CRYPTO_dynlock_set(dyn_locks, i, pointer);
289 0 : CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
290 :
291 0 : if (i == -1) {
292 0 : dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
293 0 : OPENSSL_free(pointer);
294 : } else
295 0 : i += 1; /* to avoid 0 */
296 0 : return -i;
297 : }
298 :
299 0 : void CRYPTO_destroy_dynlockid(int i)
300 : {
301 : CRYPTO_dynlock *pointer = NULL;
302 0 : if (i)
303 0 : i = -i - 1;
304 0 : if (dynlock_destroy_callback == NULL)
305 : return;
306 :
307 0 : CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
308 :
309 0 : if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) {
310 0 : CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
311 0 : return;
312 : }
313 0 : pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
314 0 : if (pointer != NULL) {
315 0 : --pointer->references;
316 : #ifdef REF_CHECK
317 : if (pointer->references < 0) {
318 : fprintf(stderr,
319 : "CRYPTO_destroy_dynlockid, bad reference count\n");
320 : abort();
321 : } else
322 : #endif
323 0 : if (pointer->references <= 0) {
324 0 : (void)sk_CRYPTO_dynlock_set(dyn_locks, i, NULL);
325 : } else
326 : pointer = NULL;
327 : }
328 0 : CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
329 :
330 0 : if (pointer) {
331 0 : dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
332 0 : OPENSSL_free(pointer);
333 : }
334 : }
335 :
336 0 : struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i)
337 : {
338 : CRYPTO_dynlock *pointer = NULL;
339 0 : if (i)
340 0 : i = -i - 1;
341 :
342 0 : CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
343 :
344 0 : if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks))
345 0 : pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
346 0 : if (pointer)
347 0 : pointer->references++;
348 :
349 0 : CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
350 :
351 0 : if (pointer)
352 0 : return pointer->data;
353 : return NULL;
354 : }
355 :
356 0 : struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))
357 : (const char *file, int line) {
358 0 : return (dynlock_create_callback);
359 : }
360 :
361 0 : void (*CRYPTO_get_dynlock_lock_callback(void)) (int mode,
362 : struct CRYPTO_dynlock_value
363 : *l, const char *file,
364 : int line) {
365 0 : return (dynlock_lock_callback);
366 : }
367 :
368 0 : void (*CRYPTO_get_dynlock_destroy_callback(void))
369 : (struct CRYPTO_dynlock_value *l, const char *file, int line) {
370 0 : return (dynlock_destroy_callback);
371 : }
372 :
373 0 : void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func)
374 : (const char *file, int line))
375 : {
376 0 : dynlock_create_callback = func;
377 0 : }
378 :
379 0 : void CRYPTO_set_dynlock_lock_callback(void (*func) (int mode,
380 : struct
381 : CRYPTO_dynlock_value *l,
382 : const char *file,
383 : int line))
384 : {
385 0 : dynlock_lock_callback = func;
386 0 : }
387 :
388 0 : void CRYPTO_set_dynlock_destroy_callback(void (*func)
389 : (struct CRYPTO_dynlock_value *l,
390 : const char *file, int line))
391 : {
392 0 : dynlock_destroy_callback = func;
393 0 : }
394 :
395 0 : void (*CRYPTO_get_locking_callback(void)) (int mode, int type,
396 : const char *file, int line) {
397 0 : return (locking_callback);
398 : }
399 :
400 0 : int (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type,
401 : const char *file, int line) {
402 0 : return (add_lock_callback);
403 : }
404 :
405 121 : void CRYPTO_set_locking_callback(void (*func) (int mode, int type,
406 : const char *file, int line))
407 : {
408 : /*
409 : * Calling this here ensures initialisation before any threads are
410 : * started.
411 : */
412 121 : OPENSSL_init();
413 121 : locking_callback = func;
414 121 : }
415 :
416 0 : void CRYPTO_set_add_lock_callback(int (*func) (int *num, int mount, int type,
417 : const char *file, int line))
418 : {
419 0 : add_lock_callback = func;
420 0 : }
421 :
422 : /*
423 : * the memset() here and in set_pointer() seem overkill, but for the sake of
424 : * CRYPTO_THREADID_cmp() this avoids any platform silliness that might cause
425 : * two "equal" THREADID structs to not be memcmp()-identical.
426 : */
427 0 : void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val)
428 : {
429 : memset(id, 0, sizeof(*id));
430 36272 : id->val = val;
431 0 : }
432 :
433 : static const unsigned char hash_coeffs[] = { 3, 5, 7, 11, 13, 17, 19, 23 };
434 :
435 0 : void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr)
436 : {
437 : unsigned char *dest = (void *)&id->val;
438 : unsigned int accum = 0;
439 : unsigned char dnum = sizeof(id->val);
440 :
441 : memset(id, 0, sizeof(*id));
442 252 : id->ptr = ptr;
443 : if (sizeof(id->val) >= sizeof(id->ptr)) {
444 : /*
445 : * 'ptr' can be embedded in 'val' without loss of uniqueness
446 : */
447 252 : id->val = (unsigned long)id->ptr;
448 0 : return;
449 : }
450 : /*
451 : * hash ptr ==> val. Each byte of 'val' gets the mod-256 total of a
452 : * linear function over the bytes in 'ptr', the co-efficients of which
453 : * are a sequence of low-primes (hash_coeffs is an 8-element cycle) - the
454 : * starting prime for the sequence varies for each byte of 'val' (unique
455 : * polynomials unless pointers are >64-bit). For added spice, the totals
456 : * accumulate rather than restarting from zero, and the index of the
457 : * 'val' byte is added each time (position dependence). If I was a
458 : * black-belt, I'd scan big-endian pointers in reverse to give low-order
459 : * bits more play, but this isn't crypto and I'd prefer nobody mistake it
460 : * as such. Plus I'm lazy.
461 : */
462 : while (dnum--) {
463 : const unsigned char *src = (void *)&id->ptr;
464 : unsigned char snum = sizeof(id->ptr);
465 : while (snum--)
466 : accum += *(src++) * hash_coeffs[(snum + dnum) & 7];
467 : accum += dnum;
468 : *(dest++) = accum & 255;
469 : }
470 : }
471 :
472 0 : int CRYPTO_THREADID_set_callback(void (*func) (CRYPTO_THREADID *))
473 : {
474 0 : if (threadid_callback)
475 : return 0;
476 0 : threadid_callback = func;
477 0 : return 1;
478 : }
479 :
480 0 : void (*CRYPTO_THREADID_get_callback(void)) (CRYPTO_THREADID *) {
481 0 : return threadid_callback;
482 : }
483 :
484 36523 : void CRYPTO_THREADID_current(CRYPTO_THREADID *id)
485 : {
486 36523 : if (threadid_callback) {
487 0 : threadid_callback(id);
488 0 : return;
489 : }
490 : #ifndef OPENSSL_NO_DEPRECATED
491 : /* If the deprecated callback was set, fall back to that */
492 36523 : if (id_callback) {
493 36271 : CRYPTO_THREADID_set_numeric(id, id_callback());
494 : return;
495 : }
496 : #endif
497 : /* Else pick a backup */
498 : #ifdef OPENSSL_SYS_WIN16
499 : CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentTask());
500 : #elif defined(OPENSSL_SYS_WIN32)
501 : CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
502 : #elif defined(OPENSSL_SYS_BEOS)
503 : CRYPTO_THREADID_set_numeric(id, (unsigned long)find_thread(NULL));
504 : #else
505 : /* For everything else, default to using the address of 'errno' */
506 252 : CRYPTO_THREADID_set_pointer(id, (void *)&errno);
507 : #endif
508 : }
509 :
510 28972 : int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b)
511 : {
512 28972 : return memcmp(a, b, sizeof(*a));
513 : }
514 :
515 22168 : void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src)
516 : {
517 : memcpy(dest, src, sizeof(*src));
518 22168 : }
519 :
520 21881 : unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
521 : {
522 21881 : return id->val;
523 : }
524 :
525 : #ifndef OPENSSL_NO_DEPRECATED
526 0 : unsigned long (*CRYPTO_get_id_callback(void)) (void) {
527 0 : return (id_callback);
528 : }
529 :
530 121 : void CRYPTO_set_id_callback(unsigned long (*func) (void))
531 : {
532 121 : id_callback = func;
533 121 : }
534 :
535 0 : unsigned long CRYPTO_thread_id(void)
536 : {
537 : unsigned long ret = 0;
538 :
539 0 : if (id_callback == NULL) {
540 : # ifdef OPENSSL_SYS_WIN16
541 : ret = (unsigned long)GetCurrentTask();
542 : # elif defined(OPENSSL_SYS_WIN32)
543 : ret = (unsigned long)GetCurrentThreadId();
544 : # elif defined(GETPID_IS_MEANINGLESS)
545 : ret = 1L;
546 : # elif defined(OPENSSL_SYS_BEOS)
547 : ret = (unsigned long)find_thread(NULL);
548 : # else
549 0 : ret = (unsigned long)getpid();
550 : # endif
551 : } else
552 0 : ret = id_callback();
553 0 : return (ret);
554 : }
555 : #endif
556 :
557 7300098 : void CRYPTO_lock(int mode, int type, const char *file, int line)
558 : {
559 : #ifdef LOCK_DEBUG
560 : {
561 : CRYPTO_THREADID id;
562 : char *rw_text, *operation_text;
563 :
564 : if (mode & CRYPTO_LOCK)
565 : operation_text = "lock ";
566 : else if (mode & CRYPTO_UNLOCK)
567 : operation_text = "unlock";
568 : else
569 : operation_text = "ERROR ";
570 :
571 : if (mode & CRYPTO_READ)
572 : rw_text = "r";
573 : else if (mode & CRYPTO_WRITE)
574 : rw_text = "w";
575 : else
576 : rw_text = "ERROR";
577 :
578 : CRYPTO_THREADID_current(&id);
579 : fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n",
580 : CRYPTO_THREADID_hash(&id), rw_text, operation_text,
581 : CRYPTO_get_lock_name(type), file, line);
582 : }
583 : #endif
584 7300098 : if (type < 0) {
585 0 : if (dynlock_lock_callback != NULL) {
586 0 : struct CRYPTO_dynlock_value *pointer
587 : = CRYPTO_get_dynlock_value(type);
588 :
589 0 : OPENSSL_assert(pointer != NULL);
590 :
591 0 : dynlock_lock_callback(mode, pointer, file, line);
592 :
593 0 : CRYPTO_destroy_dynlockid(type);
594 : }
595 7300098 : } else if (locking_callback != NULL)
596 531675 : locking_callback(mode, type, file, line);
597 7300208 : }
598 :
599 116626 : int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
600 : int line)
601 : {
602 : int ret = 0;
603 :
604 116626 : if (add_lock_callback != NULL) {
605 : #ifdef LOCK_DEBUG
606 : int before = *pointer;
607 : #endif
608 :
609 0 : ret = add_lock_callback(pointer, amount, type, file, line);
610 : #ifdef LOCK_DEBUG
611 : {
612 : CRYPTO_THREADID id;
613 : CRYPTO_THREADID_current(&id);
614 : fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
615 : CRYPTO_THREADID_hash(&id), before, amount, ret,
616 : CRYPTO_get_lock_name(type), file, line);
617 : }
618 : #endif
619 : } else {
620 116626 : CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, type, file, line);
621 :
622 116633 : ret = *pointer + amount;
623 : #ifdef LOCK_DEBUG
624 : {
625 : CRYPTO_THREADID id;
626 : CRYPTO_THREADID_current(&id);
627 : fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
628 : CRYPTO_THREADID_hash(&id),
629 : *pointer, amount, ret,
630 : CRYPTO_get_lock_name(type), file, line);
631 : }
632 : #endif
633 116633 : *pointer = ret;
634 116633 : CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, type, file, line);
635 : }
636 116631 : return (ret);
637 : }
638 :
639 0 : const char *CRYPTO_get_lock_name(int type)
640 : {
641 0 : if (type < 0)
642 : return ("dynamic");
643 0 : else if (type < CRYPTO_NUM_LOCKS)
644 0 : return (lock_names[type]);
645 0 : else if (type - CRYPTO_NUM_LOCKS > sk_OPENSSL_STRING_num(app_locks))
646 : return ("ERROR");
647 : else
648 0 : return (sk_OPENSSL_STRING_value(app_locks, type - CRYPTO_NUM_LOCKS));
649 : }
650 :
651 : #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
652 : defined(__INTEL__) || \
653 : defined(__x86_64) || defined(__x86_64__) || \
654 : defined(_M_AMD64) || defined(_M_X64)
655 :
656 : extern unsigned int OPENSSL_ia32cap_P[4];
657 0 : unsigned long *OPENSSL_ia32cap_loc(void)
658 : {
659 : if (sizeof(long) == 4)
660 : /*
661 : * If 32-bit application pulls address of OPENSSL_ia32cap_P[0]
662 : * clear second element to maintain the illusion that vector
663 : * is 32-bit.
664 : */
665 : OPENSSL_ia32cap_P[1] = 0;
666 :
667 0 : OPENSSL_ia32cap_P[2] = 0;
668 :
669 0 : return (unsigned long *)OPENSSL_ia32cap_P;
670 : }
671 :
672 : # if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
673 : # define OPENSSL_CPUID_SETUP
674 : # if defined(_WIN32)
675 : typedef unsigned __int64 IA32CAP;
676 : # else
677 : typedef unsigned long long IA32CAP;
678 : # endif
679 : void OPENSSL_cpuid_setup(void)
680 : {
681 : static int trigger = 0;
682 : IA32CAP OPENSSL_ia32_cpuid(unsigned int *);
683 : IA32CAP vec;
684 : char *env;
685 :
686 : if (trigger)
687 : return;
688 :
689 : trigger = 1;
690 : if ((env = getenv("OPENSSL_ia32cap"))) {
691 : int off = (env[0] == '~') ? 1 : 0;
692 : # if defined(_WIN32)
693 : if (!sscanf(env + off, "%I64i", &vec))
694 : vec = strtoul(env + off, NULL, 0);
695 : # else
696 : if (!sscanf(env + off, "%lli", (long long *)&vec))
697 : vec = strtoul(env + off, NULL, 0);
698 : # endif
699 : if (off)
700 : vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~vec;
701 : else if (env[0] == ':')
702 : vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
703 :
704 : OPENSSL_ia32cap_P[2] = 0;
705 : if ((env = strchr(env, ':'))) {
706 : unsigned int vecx;
707 : env++;
708 : off = (env[0] == '~') ? 1 : 0;
709 : vecx = strtoul(env + off, NULL, 0);
710 : if (off)
711 : OPENSSL_ia32cap_P[2] &= ~vecx;
712 : else
713 : OPENSSL_ia32cap_P[2] = vecx;
714 : }
715 : } else
716 : vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
717 :
718 : /*
719 : * |(1<<10) sets a reserved bit to signal that variable
720 : * was initialized already... This is to avoid interference
721 : * with cpuid snippets in ELF .init segment.
722 : */
723 : OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10);
724 : OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32);
725 : }
726 : # else
727 : unsigned int OPENSSL_ia32cap_P[4];
728 : # endif
729 :
730 : #else
731 : unsigned long *OPENSSL_ia32cap_loc(void)
732 : {
733 : return NULL;
734 : }
735 : #endif
736 : int OPENSSL_NONPIC_relocated = 0;
737 : #if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ)
738 121 : void OPENSSL_cpuid_setup(void)
739 : {
740 121 : }
741 : #endif
742 :
743 : #if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL)
744 : # ifdef __CYGWIN__
745 : /* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
746 : # include <windows.h>
747 : /*
748 : * this has side-effect of _WIN32 getting defined, which otherwise is
749 : * mutually exclusive with __CYGWIN__...
750 : */
751 : # endif
752 :
753 : /*
754 : * All we really need to do is remove the 'error' state when a thread
755 : * detaches
756 : */
757 :
758 : BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
759 : {
760 : switch (fdwReason) {
761 : case DLL_PROCESS_ATTACH:
762 : OPENSSL_cpuid_setup();
763 : # if defined(_WIN32_WINNT)
764 : {
765 : IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *) hinstDLL;
766 : IMAGE_NT_HEADERS *nt_headers;
767 :
768 : if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
769 : nt_headers = (IMAGE_NT_HEADERS *) ((char *)dos_header
770 : + dos_header->e_lfanew);
771 : if (nt_headers->Signature == IMAGE_NT_SIGNATURE &&
772 : hinstDLL !=
773 : (HINSTANCE) (nt_headers->OptionalHeader.ImageBase))
774 : OPENSSL_NONPIC_relocated = 1;
775 : }
776 : }
777 : # endif
778 : break;
779 : case DLL_THREAD_ATTACH:
780 : break;
781 : case DLL_THREAD_DETACH:
782 : break;
783 : case DLL_PROCESS_DETACH:
784 : break;
785 : }
786 : return (TRUE);
787 : }
788 : #endif
789 :
790 : #if defined(_WIN32) && !defined(__CYGWIN__)
791 : # include <tchar.h>
792 : # include <signal.h>
793 : # ifdef __WATCOMC__
794 : # if defined(_UNICODE) || defined(__UNICODE__)
795 : # define _vsntprintf _vsnwprintf
796 : # else
797 : # define _vsntprintf _vsnprintf
798 : # endif
799 : # endif
800 : # ifdef _MSC_VER
801 : # define alloca _alloca
802 : # endif
803 :
804 : # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
805 : int OPENSSL_isservice(void)
806 : {
807 : HWINSTA h;
808 : DWORD len;
809 : WCHAR *name;
810 : static union {
811 : void *p;
812 : int (*f) (void);
813 : } _OPENSSL_isservice = {
814 : NULL
815 : };
816 :
817 : if (_OPENSSL_isservice.p == NULL) {
818 : HANDLE h = GetModuleHandle(NULL);
819 : if (h != NULL)
820 : _OPENSSL_isservice.p = GetProcAddress(h, "_OPENSSL_isservice");
821 : if (_OPENSSL_isservice.p == NULL)
822 : _OPENSSL_isservice.p = (void *)-1;
823 : }
824 :
825 : if (_OPENSSL_isservice.p != (void *)-1)
826 : return (*_OPENSSL_isservice.f) ();
827 :
828 : h = GetProcessWindowStation();
829 : if (h == NULL)
830 : return -1;
831 :
832 : if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) ||
833 : GetLastError() != ERROR_INSUFFICIENT_BUFFER)
834 : return -1;
835 :
836 : if (len > 512)
837 : return -1; /* paranoia */
838 : len++, len &= ~1; /* paranoia */
839 : name = (WCHAR *)alloca(len + sizeof(WCHAR));
840 : if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len))
841 : return -1;
842 :
843 : len++, len &= ~1; /* paranoia */
844 : name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */
845 : # if 1
846 : /*
847 : * This doesn't cover "interactive" services [working with real
848 : * WinSta0's] nor programs started non-interactively by Task Scheduler
849 : * [those are working with SAWinSta].
850 : */
851 : if (wcsstr(name, L"Service-0x"))
852 : return 1;
853 : # else
854 : /* This covers all non-interactive programs such as services. */
855 : if (!wcsstr(name, L"WinSta0"))
856 : return 1;
857 : # endif
858 : else
859 : return 0;
860 : }
861 : # else
862 : int OPENSSL_isservice(void)
863 : {
864 : return 0;
865 : }
866 : # endif
867 :
868 : void OPENSSL_showfatal(const char *fmta, ...)
869 : {
870 : va_list ap;
871 : TCHAR buf[256];
872 : const TCHAR *fmt;
873 : # ifdef STD_ERROR_HANDLE /* what a dirty trick! */
874 : HANDLE h;
875 :
876 : if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL &&
877 : GetFileType(h) != FILE_TYPE_UNKNOWN) {
878 : /* must be console application */
879 : int len;
880 : DWORD out;
881 :
882 : va_start(ap, fmta);
883 : len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap);
884 : WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL);
885 : va_end(ap);
886 : return;
887 : }
888 : # endif
889 :
890 : if (sizeof(TCHAR) == sizeof(char))
891 : fmt = (const TCHAR *)fmta;
892 : else
893 : do {
894 : int keepgoing;
895 : size_t len_0 = strlen(fmta) + 1, i;
896 : WCHAR *fmtw;
897 :
898 : fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
899 : if (fmtw == NULL) {
900 : fmt = (const TCHAR *)L"no stack?";
901 : break;
902 : }
903 : # ifndef OPENSSL_NO_MULTIBYTE
904 : if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0))
905 : # endif
906 : for (i = 0; i < len_0; i++)
907 : fmtw[i] = (WCHAR)fmta[i];
908 :
909 : for (i = 0; i < len_0; i++) {
910 : if (fmtw[i] == L'%')
911 : do {
912 : keepgoing = 0;
913 : switch (fmtw[i + 1]) {
914 : case L'0':
915 : case L'1':
916 : case L'2':
917 : case L'3':
918 : case L'4':
919 : case L'5':
920 : case L'6':
921 : case L'7':
922 : case L'8':
923 : case L'9':
924 : case L'.':
925 : case L'*':
926 : case L'-':
927 : i++;
928 : keepgoing = 1;
929 : break;
930 : case L's':
931 : fmtw[i + 1] = L'S';
932 : break;
933 : case L'S':
934 : fmtw[i + 1] = L's';
935 : break;
936 : case L'c':
937 : fmtw[i + 1] = L'C';
938 : break;
939 : case L'C':
940 : fmtw[i + 1] = L'c';
941 : break;
942 : }
943 : } while (keepgoing);
944 : }
945 : fmt = (const TCHAR *)fmtw;
946 : } while (0);
947 :
948 : va_start(ap, fmta);
949 : _vsntprintf(buf, sizeof(buf) / sizeof(TCHAR) - 1, fmt, ap);
950 : buf[sizeof(buf) / sizeof(TCHAR) - 1] = _T('\0');
951 : va_end(ap);
952 :
953 : # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
954 : /* this -------------v--- guards NT-specific calls */
955 : if (check_winnt() && OPENSSL_isservice() > 0) {
956 : HANDLE h = RegisterEventSource(0, _T("OPENSSL"));
957 : const TCHAR *pmsg = buf;
958 : ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 0, 0, 1, 0, &pmsg, 0);
959 : DeregisterEventSource(h);
960 : } else
961 : # endif
962 : MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONSTOP);
963 : }
964 : #else
965 0 : void OPENSSL_showfatal(const char *fmta, ...)
966 : {
967 : va_list ap;
968 :
969 0 : va_start(ap, fmta);
970 0 : vfprintf(stderr, fmta, ap);
971 0 : va_end(ap);
972 0 : }
973 :
974 0 : int OPENSSL_isservice(void)
975 : {
976 0 : return 0;
977 : }
978 : #endif
979 :
980 0 : void OpenSSLDie(const char *file, int line, const char *assertion)
981 : {
982 : OPENSSL_showfatal
983 0 : ("%s(%d): OpenSSL internal error, assertion failed: %s\n", file, line,
984 : assertion);
985 : #if !defined(_WIN32) || defined(__CYGWIN__)
986 0 : abort();
987 : #else
988 : /*
989 : * Win32 abort() customarily shows a dialog, but we just did that...
990 : */
991 : # if !defined(_WIN32_WCE)
992 : raise(SIGABRT);
993 : # endif
994 : _exit(3);
995 : #endif
996 : }
997 :
998 0 : void *OPENSSL_stderr(void)
999 : {
1000 0 : return stderr;
1001 : }
1002 :
1003 6713 : int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
1004 : {
1005 : size_t i;
1006 : const unsigned char *a = in_a;
1007 : const unsigned char *b = in_b;
1008 : unsigned char x = 0;
1009 :
1010 111193 : for (i = 0; i < len; i++)
1011 104480 : x |= a[i] ^ b[i];
1012 :
1013 6713 : return x;
1014 : }
|