cryptlib.c revision 296465
1/* crypto/cryptlib.c */
2/* ====================================================================
3 * Copyright (c) 1998-2003 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)
121static double SSLeay_MSVC5_hack = 0.0; /* and for VC1.5 */
122#endif
123
124static void (MS_FAR *locking_callback) (int mode, int type,
125                                        const char *file, int line) = NULL;
126static int (MS_FAR *add_lock_callback) (int *pointer, int amount,
127                                        int type, const char *file,
128                                        int line) = NULL;
129static unsigned long (MS_FAR *id_callback) (void) = NULL;
130
131int CRYPTO_num_locks(void)
132{
133    return CRYPTO_NUM_LOCKS;
134}
135
136void (*CRYPTO_get_locking_callback(void)) (int mode, int type,
137                                           const char *file, int line) {
138    return (locking_callback);
139}
140
141int (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type,
142                                           const char *file, int line) {
143    return (add_lock_callback);
144}
145
146void CRYPTO_set_locking_callback(void (*func) (int mode, int type,
147                                               const char *file, int line))
148{
149    locking_callback = func;
150}
151
152void CRYPTO_set_add_lock_callback(int (*func) (int *num, int mount, int type,
153                                               const char *file, int line))
154{
155    add_lock_callback = func;
156}
157
158unsigned long (*CRYPTO_get_id_callback(void)) (void) {
159    return (id_callback);
160}
161
162void CRYPTO_set_id_callback(unsigned long (*func) (void))
163{
164    id_callback = func;
165}
166
167unsigned long CRYPTO_thread_id(void)
168{
169    unsigned long ret = 0;
170
171    if (id_callback == NULL) {
172#ifdef OPENSSL_SYS_WIN16
173        ret = (unsigned long)GetCurrentTask();
174#elif defined(OPENSSL_SYS_WIN32)
175        ret = (unsigned long)GetCurrentThreadId();
176#elif defined(GETPID_IS_MEANINGLESS)
177        ret = 1L;
178#else
179        ret = (unsigned long)getpid();
180#endif
181    } else
182        ret = id_callback();
183    return (ret);
184}
185
186static void (*do_dynlock_cb) (int mode, int type, const char *file, int line);
187
188void int_CRYPTO_set_do_dynlock_callback(void (*dyn_cb)
189                                         (int mode, int type,
190                                          const char *file, int line))
191{
192    do_dynlock_cb = dyn_cb;
193}
194
195void CRYPTO_lock(int mode, int type, const char *file, int line)
196{
197#ifdef LOCK_DEBUG
198    {
199        char *rw_text, *operation_text;
200
201        if (mode & CRYPTO_LOCK)
202            operation_text = "lock  ";
203        else if (mode & CRYPTO_UNLOCK)
204            operation_text = "unlock";
205        else
206            operation_text = "ERROR ";
207
208        if (mode & CRYPTO_READ)
209            rw_text = "r";
210        else if (mode & CRYPTO_WRITE)
211            rw_text = "w";
212        else
213            rw_text = "ERROR";
214
215        fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n",
216                CRYPTO_thread_id(), rw_text, operation_text,
217                CRYPTO_get_lock_name(type), file, line);
218    }
219#endif
220    if (type < 0) {
221        if (do_dynlock_cb)
222            do_dynlock_cb(mode, type, file, line);
223    } else if (locking_callback != NULL)
224        locking_callback(mode, type, file, line);
225}
226
227int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
228                    int line)
229{
230    int ret = 0;
231
232    if (add_lock_callback != NULL) {
233#ifdef LOCK_DEBUG
234        int before = *pointer;
235#endif
236
237        ret = add_lock_callback(pointer, amount, type, file, line);
238#ifdef LOCK_DEBUG
239        fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
240                CRYPTO_thread_id(),
241                before, amount, ret, CRYPTO_get_lock_name(type), file, line);
242#endif
243    } else {
244        CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, type, file, line);
245
246        ret = *pointer + amount;
247#ifdef LOCK_DEBUG
248        fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
249                CRYPTO_thread_id(),
250                *pointer, amount, ret,
251                CRYPTO_get_lock_name(type), file, line);
252#endif
253        *pointer = ret;
254        CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, type, file, line);
255    }
256    return (ret);
257}
258
259#if     defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
260        defined(__INTEL__) || \
261        defined(__x86_64) || defined(__x86_64__) || \
262        defined(_M_AMD64) || defined(_M_X64)
263
264unsigned long OPENSSL_ia32cap_P = 0;
265unsigned long *OPENSSL_ia32cap_loc(void)
266{
267    return &OPENSSL_ia32cap_P;
268}
269
270# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
271#  define OPENSSL_CPUID_SETUP
272void OPENSSL_cpuid_setup(void)
273{
274    static int trigger = 0;
275    unsigned long OPENSSL_ia32_cpuid(void);
276    char *env;
277
278    if (trigger)
279        return;
280
281    trigger = 1;
282    if ((env = getenv("OPENSSL_ia32cap")))
283        OPENSSL_ia32cap_P = strtoul(env, NULL, 0) | (1 << 10);
284    else
285        OPENSSL_ia32cap_P = OPENSSL_ia32_cpuid() | (1 << 10);
286    /*
287     * |(1<<10) sets a reserved bit to signal that variable
288     * was initialized already... This is to avoid interference
289     * with cpuid snippets in ELF .init segment.
290     */
291}
292# endif
293
294#else
295unsigned long *OPENSSL_ia32cap_loc(void)
296{
297    return NULL;
298}
299#endif
300int OPENSSL_NONPIC_relocated = 0;
301#if !defined(OPENSSL_CPUID_SETUP)
302void OPENSSL_cpuid_setup(void)
303{
304}
305#endif
306
307#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL)
308
309# ifdef OPENSSL_FIPS
310
311#  include <tlhelp32.h>
312#  if defined(__GNUC__) && __GNUC__>=2
313static int DllInit(void) __attribute__ ((constructor));
314#  elif defined(_MSC_VER)
315static int DllInit(void);
316#   ifdef _WIN64
317#    pragma section(".CRT$XCU",read)
318__declspec(allocate(".CRT$XCU"))
319#   else
320#    pragma data_seg(".CRT$XCU")
321#   endif
322static int (*p) (void) = DllInit;
323#   pragma data_seg()
324#  endif
325
326static int DllInit(void)
327{
328#  if defined(_WIN32_WINNT)
329    union {
330        int (*f) (void);
331        BYTE *p;
332    } t = {
333        DllInit
334    };
335    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
336    IMAGE_DOS_HEADER *dos_header;
337    IMAGE_NT_HEADERS *nt_headers;
338    MODULEENTRY32 me32 = { sizeof(me32) };
339
340    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
341    if (hModuleSnap != INVALID_HANDLE_VALUE &&
342        Module32First(hModuleSnap, &me32))
343        do {
344            if (t.p >= me32.modBaseAddr &&
345                t.p < me32.modBaseAddr + me32.modBaseSize) {
346                dos_header = (IMAGE_DOS_HEADER *) me32.modBaseAddr;
347                if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
348                    nt_headers = (IMAGE_NT_HEADERS *)
349                        ((BYTE *) dos_header + dos_header->e_lfanew);
350                    if (nt_headers->Signature == IMAGE_NT_SIGNATURE &&
351                        me32.modBaseAddr !=
352                        (BYTE *) nt_headers->OptionalHeader.ImageBase)
353                        OPENSSL_NONPIC_relocated = 1;
354                }
355                break;
356            }
357        } while (Module32Next(hModuleSnap, &me32));
358
359    if (hModuleSnap != INVALID_HANDLE_VALUE)
360        CloseHandle(hModuleSnap);
361#  endif
362    OPENSSL_cpuid_setup();
363    return 0;
364}
365
366# else
367
368#  ifdef __CYGWIN__
369/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
370#   include <windows.h>
371#  endif
372
373/*
374 * All we really need to do is remove the 'error' state when a thread
375 * detaches
376 */
377
378BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
379{
380    switch (fdwReason) {
381    case DLL_PROCESS_ATTACH:
382        OPENSSL_cpuid_setup();
383#  if defined(_WIN32_WINNT)
384        {
385            IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *) hinstDLL;
386            IMAGE_NT_HEADERS *nt_headers;
387
388            if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
389                nt_headers = (IMAGE_NT_HEADERS *) ((char *)dos_header
390                                                   + dos_header->e_lfanew);
391                if (nt_headers->Signature == IMAGE_NT_SIGNATURE &&
392                    hinstDLL !=
393                    (HINSTANCE) (nt_headers->OptionalHeader.ImageBase))
394                    OPENSSL_NONPIC_relocated = 1;
395            }
396        }
397#  endif
398        break;
399    case DLL_THREAD_ATTACH:
400        break;
401    case DLL_THREAD_DETACH:
402        break;
403    case DLL_PROCESS_DETACH:
404        break;
405    }
406    return (TRUE);
407}
408# endif
409
410#endif
411
412#if defined(_WIN32) && !defined(__CYGWIN__)
413# include <tchar.h>
414
415# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
416int OPENSSL_isservice(void)
417{
418    HWINSTA h;
419    DWORD len;
420    WCHAR *name;
421
422    (void)GetDesktopWindow();   /* return value is ignored */
423
424    h = GetProcessWindowStation();
425    if (h == NULL)
426        return -1;
427
428    if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) ||
429        GetLastError() != ERROR_INSUFFICIENT_BUFFER)
430        return -1;
431
432    if (len > 512)
433        return -1;              /* paranoia */
434    len++, len &= ~1;           /* paranoia */
435#  ifdef _MSC_VER
436    name = (WCHAR *)_alloca(len + sizeof(WCHAR));
437#  else
438    name = (WCHAR *)alloca(len + sizeof(WCHAR));
439#  endif
440    if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len))
441        return -1;
442
443    len++, len &= ~1;           /* paranoia */
444    name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */
445#  if 1
446    /*
447     * This doesn't cover "interactive" services [working with real
448     * WinSta0's] nor programs started non-interactively by Task Scheduler
449     * [those are working with SAWinSta].
450     */
451    if (wcsstr(name, L"Service-0x"))
452        return 1;
453#  else
454    /* This covers all non-interactive programs such as services. */
455    if (!wcsstr(name, L"WinSta0"))
456        return 1;
457#  endif
458    else
459        return 0;
460}
461# else
462int OPENSSL_isservice(void)
463{
464    return 0;
465}
466# endif
467
468void OPENSSL_showfatal(const char *fmta, ...)
469{
470    va_list ap;
471    TCHAR buf[256];
472    const TCHAR *fmt;
473# ifdef STD_ERROR_HANDLE        /* what a dirty trick! */
474    HANDLE h;
475
476    if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL &&
477        GetFileType(h) != FILE_TYPE_UNKNOWN) {
478        /* must be console application */
479        va_start(ap, fmta);
480        vfprintf(stderr, fmta, ap);
481        va_end(ap);
482        return;
483    }
484# endif
485
486    if (sizeof(TCHAR) == sizeof(char))
487        fmt = (const TCHAR *)fmta;
488    else
489        do {
490            int keepgoing;
491            size_t len_0 = strlen(fmta) + 1, i;
492            WCHAR *fmtw;
493
494# ifdef _MSC_VER
495            fmtw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR));
496# else
497            fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
498# endif
499            if (fmtw == NULL) {
500                fmt = (const TCHAR *)L"no stack?";
501                break;
502            }
503# ifndef OPENSSL_NO_MULTIBYTE
504            if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0))
505# endif
506                for (i = 0; i < len_0; i++)
507                    fmtw[i] = (WCHAR)fmta[i];
508
509            for (i = 0; i < len_0; i++) {
510                if (fmtw[i] == L'%')
511                    do {
512                        keepgoing = 0;
513                        switch (fmtw[i + 1]) {
514                        case L'0':
515                        case L'1':
516                        case L'2':
517                        case L'3':
518                        case L'4':
519                        case L'5':
520                        case L'6':
521                        case L'7':
522                        case L'8':
523                        case L'9':
524                        case L'.':
525                        case L'*':
526                        case L'-':
527                            i++;
528                            keepgoing = 1;
529                            break;
530                        case L's':
531                            fmtw[i + 1] = L'S';
532                            break;
533                        case L'S':
534                            fmtw[i + 1] = L's';
535                            break;
536                        case L'c':
537                            fmtw[i + 1] = L'C';
538                            break;
539                        case L'C':
540                            fmtw[i + 1] = L'c';
541                            break;
542                        }
543                    } while (keepgoing);
544            }
545            fmt = (const TCHAR *)fmtw;
546        } while (0);
547
548    va_start(ap, fmta);
549    _vsntprintf(buf, sizeof(buf) / sizeof(TCHAR) - 1, fmt, ap);
550    buf[sizeof(buf) / sizeof(TCHAR) - 1] = _T('\0');
551    va_end(ap);
552
553# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
554    /* this -------------v--- guards NT-specific calls */
555    if (check_winnt() && OPENSSL_isservice() > 0) {
556        HANDLE h = RegisterEventSource(0, _T("OPENSSL"));
557        const TCHAR *pmsg = buf;
558        ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 0, 0, 1, 0, &pmsg, 0);
559        DeregisterEventSource(h);
560    } else
561# endif
562        MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONSTOP);
563}
564#else
565void OPENSSL_showfatal(const char *fmta, ...)
566{
567    va_list ap;
568
569    va_start(ap, fmta);
570    vfprintf(stderr, fmta, ap);
571    va_end(ap);
572}
573
574int OPENSSL_isservice(void)
575{
576    return 0;
577}
578#endif
579
580void OpenSSLDie(const char *file, int line, const char *assertion)
581{
582    OPENSSL_showfatal
583        ("%s(%d): OpenSSL internal error, assertion failed: %s\n", file, line,
584         assertion);
585    abort();
586}
587
588void *OPENSSL_stderr(void)
589{
590    return stderr;
591}
592
593#ifndef OPENSSL_FIPS
594
595int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
596{
597    size_t i;
598    const unsigned char *a = in_a;
599    const unsigned char *b = in_b;
600    unsigned char x = 0;
601
602    for (i = 0; i < len; i++)
603        x |= a[i] ^ b[i];
604
605    return x;
606}
607#endif
608