source: trunk/sys/libcrypto/cryptlib.c @ 240

Last change on this file since 240 was 1, checked in by alain, 8 years ago

First import

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