]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/crypto/cryptlib.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / crypto / cryptlib.c
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)
121 static double SSLeay_MSVC5_hack = 0.0; /* and for VC1.5 */
122 #endif
123
124 static void (MS_FAR *locking_callback) (int mode, int type,
125                                         const char *file, int line) = NULL;
126 static int (MS_FAR *add_lock_callback) (int *pointer, int amount,
127                                         int type, const char *file,
128                                         int line) = NULL;
129 static unsigned long (MS_FAR *id_callback) (void) = NULL;
130
131 int CRYPTO_num_locks(void)
132 {
133     return CRYPTO_NUM_LOCKS;
134 }
135
136 void (*CRYPTO_get_locking_callback(void)) (int mode, int type,
137                                            const char *file, int line) {
138     return (locking_callback);
139 }
140
141 int (*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
146 void CRYPTO_set_locking_callback(void (*func) (int mode, int type,
147                                                const char *file, int line))
148 {
149     locking_callback = func;
150 }
151
152 void 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
158 unsigned long (*CRYPTO_get_id_callback(void)) (void) {
159     return (id_callback);
160 }
161
162 void CRYPTO_set_id_callback(unsigned long (*func) (void))
163 {
164     id_callback = func;
165 }
166
167 unsigned 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
186 static void (*do_dynlock_cb) (int mode, int type, const char *file, int line);
187
188 void 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
195 void 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
227 int 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
264 unsigned long OPENSSL_ia32cap_P = 0;
265 unsigned 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
272 void 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
295 unsigned long *OPENSSL_ia32cap_loc(void)
296 {
297     return NULL;
298 }
299 #endif
300 int OPENSSL_NONPIC_relocated = 0;
301 #if !defined(OPENSSL_CPUID_SETUP)
302 void 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
313 static int DllInit(void) __attribute__ ((constructor));
314 #  elif defined(_MSC_VER)
315 static 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
322 static int (*p) (void) = DllInit;
323 #   pragma data_seg()
324 #  endif
325
326 static 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
378 BOOL 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
416 int 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
462 int OPENSSL_isservice(void)
463 {
464     return 0;
465 }
466 # endif
467
468 void 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
565 void 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
574 int OPENSSL_isservice(void)
575 {
576     return 0;
577 }
578 #endif
579
580 void 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
588 void *OPENSSL_stderr(void)
589 {
590     return stderr;
591 }
592
593 #ifndef OPENSSL_FIPS
594
595 int 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