Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/cryptlib.c
Line
Count
Source (jump to first uncovered line)
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
int CRYPTO_get_new_lockid(char *name)
206
0
{
207
0
    char *str;
208
0
    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
0
    }
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
0
    }
228
0
    i = sk_OPENSSL_STRING_push(app_locks, str);
229
0
    if (!i)
230
0
        OPENSSL_free(str);
231
0
    else
232
0
        i += CRYPTO_NUM_LOCKS;  /* gap of one :-) */
233
0
    return (i);
234
0
}
235
236
int CRYPTO_num_locks(void)
237
0
{
238
0
    return CRYPTO_NUM_LOCKS;
239
0
}
240
241
int CRYPTO_get_new_dynlockid(void)
242
0
{
243
0
    int i = 0;
244
0
    CRYPTO_dynlock *pointer = NULL;
245
246
0
    if (dynlock_create_callback == NULL) {
247
0
        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,
248
0
                  CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK);
249
0
        return (0);
250
0
    }
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
0
    }
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
0
    }
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
0
    }
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
0
    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
0
    } else
295
0
        i += 1;                 /* to avoid 0 */
296
0
    return -i;
297
0
}
298
299
void CRYPTO_destroy_dynlockid(int i)
300
0
{
301
0
    CRYPTO_dynlock *pointer = NULL;
302
0
    if (i)
303
0
        i = -i - 1;
304
0
    if (dynlock_destroy_callback == NULL)
305
0
        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
0
    }
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
0
        } else
326
0
            pointer = NULL;
327
0
    }
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
0
    }
334
0
}
335
336
struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i)
337
0
{
338
0
    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
0
    return NULL;
354
0
}
355
356
struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))
357
0
 (const char *file, int line) {
358
0
    return (dynlock_create_callback);
359
0
}
360
361
void (*CRYPTO_get_dynlock_lock_callback(void)) (int mode,
362
                                                struct CRYPTO_dynlock_value
363
                                                *l, const char *file,
364
0
                                                int line) {
365
0
    return (dynlock_lock_callback);
366
0
}
367
368
void (*CRYPTO_get_dynlock_destroy_callback(void))
369
0
 (struct CRYPTO_dynlock_value *l, const char *file, int line) {
370
0
    return (dynlock_destroy_callback);
371
0
}
372
373
void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func)
374
                                         (const char *file, int line))
375
0
{
376
0
    dynlock_create_callback = func;
377
0
}
378
379
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
0
{
385
0
    dynlock_lock_callback = func;
386
0
}
387
388
void CRYPTO_set_dynlock_destroy_callback(void (*func)
389
                                          (struct CRYPTO_dynlock_value *l,
390
                                           const char *file, int line))
391
0
{
392
0
    dynlock_destroy_callback = func;
393
0
}
394
395
void (*CRYPTO_get_locking_callback(void)) (int mode, int type,
396
0
                                           const char *file, int line) {
397
0
    return (locking_callback);
398
0
}
399
400
int (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type,
401
0
                                           const char *file, int line) {
402
0
    return (add_lock_callback);
403
0
}
404
405
void CRYPTO_set_locking_callback(void (*func) (int mode, int type,
406
                                               const char *file, int line))
407
0
{
408
    /*
409
     * Calling this here ensures initialisation before any threads are
410
     * started.
411
     */
412
0
    OPENSSL_init();
413
0
    locking_callback = func;
414
0
}
415
416
void CRYPTO_set_add_lock_callback(int (*func) (int *num, int mount, int type,
417
                                               const char *file, int line))
418
0
{
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
void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val)
428
0
{
429
0
    memset(id, 0, sizeof(*id));
430
0
    id->val = val;
431
0
}
432
433
static const unsigned char hash_coeffs[] = { 3, 5, 7, 11, 13, 17, 19, 23 };
434
435
void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr)
436
385k
{
437
385k
    unsigned char *dest = (void *)&id->val;
438
385k
    unsigned int accum = 0;
439
385k
    unsigned char dnum = sizeof(id->val);
440
441
385k
    memset(id, 0, sizeof(*id));
442
385k
    id->ptr = ptr;
443
385k
    if (sizeof(id->val) >= sizeof(id->ptr)) {
444
        /*
445
         * 'ptr' can be embedded in 'val' without loss of uniqueness
446
         */
447
385k
        id->val = (unsigned long)id->ptr;
448
385k
        return;
449
385k
    }
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
0
    while (dnum--) {
463
0
        const unsigned char *src = (void *)&id->ptr;
464
0
        unsigned char snum = sizeof(id->ptr);
465
0
        while (snum--)
466
0
            accum += *(src++) * hash_coeffs[(snum + dnum) & 7];
467
0
        accum += dnum;
468
0
        *(dest++) = accum & 255;
469
0
    }
470
0
}
471
472
#ifdef OPENSSL_FIPS
473
extern int FIPS_crypto_threadid_set_callback(void (*func) (CRYPTO_THREADID *));
474
#endif
475
476
int CRYPTO_THREADID_set_callback(void (*func) (CRYPTO_THREADID *))
477
0
{
478
0
    if (threadid_callback)
479
0
        return 0;
480
0
    threadid_callback = func;
481
#ifdef OPENSSL_FIPS
482
    FIPS_crypto_threadid_set_callback(func);
483
#endif
484
0
    return 1;
485
0
}
486
487
0
void (*CRYPTO_THREADID_get_callback(void)) (CRYPTO_THREADID *) {
488
0
    return threadid_callback;
489
0
}
490
491
void CRYPTO_THREADID_current(CRYPTO_THREADID *id)
492
385k
{
493
385k
    if (threadid_callback) {
494
0
        threadid_callback(id);
495
0
        return;
496
0
    }
497
385k
#ifndef OPENSSL_NO_DEPRECATED
498
    /* If the deprecated callback was set, fall back to that */
499
385k
    if (id_callback) {
500
0
        CRYPTO_THREADID_set_numeric(id, id_callback());
501
0
        return;
502
0
    }
503
385k
#endif
504
    /* Else pick a backup */
505
#ifdef OPENSSL_SYS_WIN16
506
    CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentTask());
507
#elif defined(OPENSSL_SYS_WIN32)
508
    CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
509
#elif defined(OPENSSL_SYS_BEOS)
510
    CRYPTO_THREADID_set_numeric(id, (unsigned long)find_thread(NULL));
511
#else
512
    /* For everything else, default to using the address of 'errno' */
513
385k
    CRYPTO_THREADID_set_pointer(id, (void *)&errno);
514
385k
#endif
515
385k
}
516
517
int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b)
518
188k
{
519
188k
    return memcmp(a, b, sizeof(*a));
520
188k
}
521
522
void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src)
523
207k
{
524
207k
    memcpy(dest, src, sizeof(*src));
525
207k
}
526
527
unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
528
200k
{
529
200k
    return id->val;
530
200k
}
531
532
#ifndef OPENSSL_NO_DEPRECATED
533
0
unsigned long (*CRYPTO_get_id_callback(void)) (void) {
534
0
    return (id_callback);
535
0
}
536
537
void CRYPTO_set_id_callback(unsigned long (*func) (void))
538
0
{
539
0
    id_callback = func;
540
0
}
541
542
unsigned long CRYPTO_thread_id(void)
543
0
{
544
0
    unsigned long ret = 0;
545
546
0
    if (id_callback == NULL) {
547
# ifdef OPENSSL_SYS_WIN16
548
        ret = (unsigned long)GetCurrentTask();
549
# elif defined(OPENSSL_SYS_WIN32)
550
        ret = (unsigned long)GetCurrentThreadId();
551
# elif defined(GETPID_IS_MEANINGLESS)
552
        ret = 1L;
553
# elif defined(OPENSSL_SYS_BEOS)
554
        ret = (unsigned long)find_thread(NULL);
555
# else
556
0
        ret = (unsigned long)getpid();
557
0
# endif
558
0
    } else
559
0
        ret = id_callback();
560
0
    return (ret);
561
0
}
562
#endif
563
564
void CRYPTO_lock(int mode, int type, const char *file, int line)
565
6.31M
{
566
#ifdef LOCK_DEBUG
567
    {
568
        CRYPTO_THREADID id;
569
        char *rw_text, *operation_text;
570
571
        if (mode & CRYPTO_LOCK)
572
            operation_text = "lock  ";
573
        else if (mode & CRYPTO_UNLOCK)
574
            operation_text = "unlock";
575
        else
576
            operation_text = "ERROR ";
577
578
        if (mode & CRYPTO_READ)
579
            rw_text = "r";
580
        else if (mode & CRYPTO_WRITE)
581
            rw_text = "w";
582
        else
583
            rw_text = "ERROR";
584
585
        CRYPTO_THREADID_current(&id);
586
        fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n",
587
                CRYPTO_THREADID_hash(&id), rw_text, operation_text,
588
                CRYPTO_get_lock_name(type), file, line);
589
    }
590
#endif
591
6.31M
    if (type < 0) {
592
0
        if (dynlock_lock_callback != NULL) {
593
0
            struct CRYPTO_dynlock_value *pointer
594
0
                = CRYPTO_get_dynlock_value(type);
595
596
0
            OPENSSL_assert(pointer != NULL);
597
598
0
            dynlock_lock_callback(mode, pointer, file, line);
599
600
0
            CRYPTO_destroy_dynlockid(type);
601
0
        }
602
6.31M
    } else if (locking_callback != NULL)
603
0
        locking_callback(mode, type, file, line);
604
6.31M
}
605
606
int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
607
                    int line)
608
838k
{
609
838k
    int ret = 0;
610
611
838k
    if (add_lock_callback != NULL) {
612
#ifdef LOCK_DEBUG
613
        int before = *pointer;
614
#endif
615
616
0
        ret = add_lock_callback(pointer, amount, type, file, line);
617
#ifdef LOCK_DEBUG
618
        {
619
            CRYPTO_THREADID id;
620
            CRYPTO_THREADID_current(&id);
621
            fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
622
                    CRYPTO_THREADID_hash(&id), before, amount, ret,
623
                    CRYPTO_get_lock_name(type), file, line);
624
        }
625
#endif
626
838k
    } else {
627
838k
        CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, type, file, line);
628
629
838k
        ret = *pointer + amount;
630
#ifdef LOCK_DEBUG
631
        {
632
            CRYPTO_THREADID id;
633
            CRYPTO_THREADID_current(&id);
634
            fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
635
                    CRYPTO_THREADID_hash(&id),
636
                    *pointer, amount, ret,
637
                    CRYPTO_get_lock_name(type), file, line);
638
        }
639
#endif
640
838k
        *pointer = ret;
641
838k
        CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, type, file, line);
642
838k
    }
643
838k
    return (ret);
644
838k
}
645
646
const char *CRYPTO_get_lock_name(int type)
647
0
{
648
0
    if (type < 0)
649
0
        return ("dynamic");
650
0
    else if (type < CRYPTO_NUM_LOCKS)
651
0
        return (lock_names[type]);
652
0
    else if (type - CRYPTO_NUM_LOCKS > sk_OPENSSL_STRING_num(app_locks))
653
0
        return ("ERROR");
654
0
    else
655
0
        return (sk_OPENSSL_STRING_value(app_locks, type - CRYPTO_NUM_LOCKS));
656
0
}
657
658
#if     defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
659
        defined(__INTEL__) || \
660
        defined(__x86_64) || defined(__x86_64__) || \
661
        defined(_M_AMD64) || defined(_M_X64)
662
663
extern unsigned int OPENSSL_ia32cap_P[4];
664
unsigned long *OPENSSL_ia32cap_loc(void)
665
0
{
666
0
    if (sizeof(long) == 4)
667
        /*
668
         * If 32-bit application pulls address of OPENSSL_ia32cap_P[0]
669
         * clear second element to maintain the illusion that vector
670
         * is 32-bit.
671
         */
672
0
        OPENSSL_ia32cap_P[1] = 0;
673
674
0
    OPENSSL_ia32cap_P[2] = 0;
675
676
0
    return (unsigned long *)OPENSSL_ia32cap_P;
677
0
}
678
679
# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
680
#  define OPENSSL_CPUID_SETUP
681
#  if defined(_WIN32)
682
typedef unsigned __int64 IA32CAP;
683
#  else
684
typedef unsigned long long IA32CAP;
685
#  endif
686
void OPENSSL_cpuid_setup(void)
687
78
{
688
78
    static int trigger = 0;
689
78
    IA32CAP OPENSSL_ia32_cpuid(unsigned int *);
690
78
    IA32CAP vec;
691
78
    char *env;
692
693
78
    if (trigger)
694
38
        return;
695
696
40
    trigger = 1;
697
40
    if ((env = getenv("OPENSSL_ia32cap"))) {
698
0
        int off = (env[0] == '~') ? 1 : 0;
699
#  if defined(_WIN32)
700
        if (!sscanf(env + off, "%I64i", &vec))
701
            vec = strtoul(env + off, NULL, 0);
702
#  else
703
0
        if (!sscanf(env + off, "%lli", (long long *)&vec))
704
0
            vec = strtoul(env + off, NULL, 0);
705
0
#  endif
706
0
        if (off)
707
0
            vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~vec;
708
0
        else if (env[0] == ':')
709
0
            vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
710
711
0
        OPENSSL_ia32cap_P[2] = 0;
712
0
        if ((env = strchr(env, ':'))) {
713
0
            unsigned int vecx;
714
0
            env++;
715
0
            off = (env[0] == '~') ? 1 : 0;
716
0
            vecx = strtoul(env + off, NULL, 0);
717
0
            if (off)
718
0
                OPENSSL_ia32cap_P[2] &= ~vecx;
719
0
            else
720
0
                OPENSSL_ia32cap_P[2] = vecx;
721
0
        }
722
0
    } else
723
40
        vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
724
725
    /*
726
     * |(1<<10) sets a reserved bit to signal that variable
727
     * was initialized already... This is to avoid interference
728
     * with cpuid snippets in ELF .init segment.
729
     */
730
40
    OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10);
731
40
    OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32);
732
40
}
733
# else
734
unsigned int OPENSSL_ia32cap_P[4];
735
# endif
736
737
#else
738
unsigned long *OPENSSL_ia32cap_loc(void)
739
{
740
    return NULL;
741
}
742
#endif
743
int OPENSSL_NONPIC_relocated = 0;
744
#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ)
745
void OPENSSL_cpuid_setup(void)
746
{
747
}
748
#endif
749
750
#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL)
751
# ifdef __CYGWIN__
752
/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
753
#  include <windows.h>
754
/*
755
 * this has side-effect of _WIN32 getting defined, which otherwise is
756
 * mutually exclusive with __CYGWIN__...
757
 */
758
# endif
759
760
/*
761
 * All we really need to do is remove the 'error' state when a thread
762
 * detaches
763
 */
764
765
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
766
{
767
    switch (fdwReason) {
768
    case DLL_PROCESS_ATTACH:
769
        OPENSSL_cpuid_setup();
770
# if defined(_WIN32_WINNT)
771
        {
772
            IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *) hinstDLL;
773
            IMAGE_NT_HEADERS *nt_headers;
774
775
            if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
776
                nt_headers = (IMAGE_NT_HEADERS *) ((char *)dos_header
777
                                                   + dos_header->e_lfanew);
778
                if (nt_headers->Signature == IMAGE_NT_SIGNATURE &&
779
                    hinstDLL !=
780
                    (HINSTANCE) (nt_headers->OptionalHeader.ImageBase))
781
                    OPENSSL_NONPIC_relocated = 1;
782
            }
783
        }
784
# endif
785
        break;
786
    case DLL_THREAD_ATTACH:
787
        break;
788
    case DLL_THREAD_DETACH:
789
        break;
790
    case DLL_PROCESS_DETACH:
791
        break;
792
    }
793
    return (TRUE);
794
}
795
#endif
796
797
#if defined(_WIN32) && !defined(__CYGWIN__)
798
# include <tchar.h>
799
# include <signal.h>
800
# ifdef __WATCOMC__
801
#  if defined(_UNICODE) || defined(__UNICODE__)
802
#   define _vsntprintf _vsnwprintf
803
#  else
804
#   define _vsntprintf _vsnprintf
805
#  endif
806
# endif
807
# ifdef _MSC_VER
808
#  define alloca _alloca
809
# endif
810
811
# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
812
int OPENSSL_isservice(void)
813
{
814
    HWINSTA h;
815
    DWORD len;
816
    WCHAR *name;
817
    static union {
818
        void *p;
819
        int (*f) (void);
820
    } _OPENSSL_isservice = {
821
        NULL
822
    };
823
824
    if (_OPENSSL_isservice.p == NULL) {
825
        HANDLE h = GetModuleHandle(NULL);
826
        if (h != NULL)
827
            _OPENSSL_isservice.p = GetProcAddress(h, "_OPENSSL_isservice");
828
        if (_OPENSSL_isservice.p == NULL)
829
            _OPENSSL_isservice.p = (void *)-1;
830
    }
831
832
    if (_OPENSSL_isservice.p != (void *)-1)
833
        return (*_OPENSSL_isservice.f) ();
834
835
    h = GetProcessWindowStation();
836
    if (h == NULL)
837
        return -1;
838
839
    if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) ||
840
        GetLastError() != ERROR_INSUFFICIENT_BUFFER)
841
        return -1;
842
843
    if (len > 512)
844
        return -1;              /* paranoia */
845
    len++, len &= ~1;           /* paranoia */
846
    name = (WCHAR *)alloca(len + sizeof(WCHAR));
847
    if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len))
848
        return -1;
849
850
    len++, len &= ~1;           /* paranoia */
851
    name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */
852
#  if 1
853
    /*
854
     * This doesn't cover "interactive" services [working with real
855
     * WinSta0's] nor programs started non-interactively by Task Scheduler
856
     * [those are working with SAWinSta].
857
     */
858
    if (wcsstr(name, L"Service-0x"))
859
        return 1;
860
#  else
861
    /* This covers all non-interactive programs such as services. */
862
    if (!wcsstr(name, L"WinSta0"))
863
        return 1;
864
#  endif
865
    else
866
        return 0;
867
}
868
# else
869
int OPENSSL_isservice(void)
870
{
871
    return 0;
872
}
873
# endif
874
875
void OPENSSL_showfatal(const char *fmta, ...)
876
{
877
    va_list ap;
878
    TCHAR buf[256];
879
    const TCHAR *fmt;
880
# ifdef STD_ERROR_HANDLE        /* what a dirty trick! */
881
    HANDLE h;
882
883
    if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL &&
884
        GetFileType(h) != FILE_TYPE_UNKNOWN) {
885
        /* must be console application */
886
        int len;
887
        DWORD out;
888
889
        va_start(ap, fmta);
890
        len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap);
891
        WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL);
892
        va_end(ap);
893
        return;
894
    }
895
# endif
896
897
    if (sizeof(TCHAR) == sizeof(char))
898
        fmt = (const TCHAR *)fmta;
899
    else
900
        do {
901
            int keepgoing;
902
            size_t len_0 = strlen(fmta) + 1, i;
903
            WCHAR *fmtw;
904
905
            fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
906
            if (fmtw == NULL) {
907
                fmt = (const TCHAR *)L"no stack?";
908
                break;
909
            }
910
# ifndef OPENSSL_NO_MULTIBYTE
911
            if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0))
912
# endif
913
                for (i = 0; i < len_0; i++)
914
                    fmtw[i] = (WCHAR)fmta[i];
915
916
            for (i = 0; i < len_0; i++) {
917
                if (fmtw[i] == L'%')
918
                    do {
919
                        keepgoing = 0;
920
                        switch (fmtw[i + 1]) {
921
                        case L'0':
922
                        case L'1':
923
                        case L'2':
924
                        case L'3':
925
                        case L'4':
926
                        case L'5':
927
                        case L'6':
928
                        case L'7':
929
                        case L'8':
930
                        case L'9':
931
                        case L'.':
932
                        case L'*':
933
                        case L'-':
934
                            i++;
935
                            keepgoing = 1;
936
                            break;
937
                        case L's':
938
                            fmtw[i + 1] = L'S';
939
                            break;
940
                        case L'S':
941
                            fmtw[i + 1] = L's';
942
                            break;
943
                        case L'c':
944
                            fmtw[i + 1] = L'C';
945
                            break;
946
                        case L'C':
947
                            fmtw[i + 1] = L'c';
948
                            break;
949
                        }
950
                    } while (keepgoing);
951
            }
952
            fmt = (const TCHAR *)fmtw;
953
        } while (0);
954
955
    va_start(ap, fmta);
956
    _vsntprintf(buf, sizeof(buf) / sizeof(TCHAR) - 1, fmt, ap);
957
    buf[sizeof(buf) / sizeof(TCHAR) - 1] = _T('\0');
958
    va_end(ap);
959
960
# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
961
    /* this -------------v--- guards NT-specific calls */
962
    if (check_winnt() && OPENSSL_isservice() > 0) {
963
        HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL"));
964
965
        if (hEventLog != NULL) {
966
            const TCHAR *pmsg = buf;
967
968
            if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL,
969
                             1, 0, &pmsg, NULL)) {
970
#if defined(DEBUG)
971
                /*
972
                 * We are in a situation where we tried to report a critical
973
                 * error and this failed for some reason. As a last resort,
974
                 * in debug builds, send output to the debugger or any other
975
                 * tool like DebugView which can monitor the output.
976
                 */
977
                OutputDebugString(pmsg);
978
#endif
979
            }
980
981
            (void)DeregisterEventSource(hEventLog);
982
        }
983
    } else
984
# endif
985
        MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR);
986
}
987
#else
988
void OPENSSL_showfatal(const char *fmta, ...)
989
0
{
990
0
    va_list ap;
991
992
0
    va_start(ap, fmta);
993
0
    vfprintf(stderr, fmta, ap);
994
0
    va_end(ap);
995
0
}
996
997
int OPENSSL_isservice(void)
998
0
{
999
0
    return 0;
1000
0
}
1001
#endif
1002
1003
void OpenSSLDie(const char *file, int line, const char *assertion)
1004
0
{
1005
0
    OPENSSL_showfatal
1006
0
        ("%s(%d): OpenSSL internal error, assertion failed: %s\n", file, line,
1007
0
         assertion);
1008
0
#if !defined(_WIN32) || defined(__CYGWIN__)
1009
0
    abort();
1010
#else
1011
    /*
1012
     * Win32 abort() customarily shows a dialog, but we just did that...
1013
     */
1014
# if !defined(_WIN32_WCE)
1015
    raise(SIGABRT);
1016
# endif
1017
    _exit(3);
1018
#endif
1019
0
}
1020
1021
void *OPENSSL_stderr(void)
1022
0
{
1023
0
    return stderr;
1024
0
}
1025
1026
int CRYPTO_memcmp(const volatile void *in_a, const volatile void *in_b, size_t len)
1027
0
{
1028
0
    size_t i;
1029
0
    const volatile unsigned char *a = in_a;
1030
0
    const volatile unsigned char *b = in_b;
1031
0
    unsigned char x = 0;
1032
1033
0
    for (i = 0; i < len; i++)
1034
0
        x |= a[i] ^ b[i];
1035
1036
0
    return x;
1037
0
}