And so it begins...
[oweals/openssl.git] / fips-1.0 / fips_canister.c
1 /* ====================================================================
2  * Copyright (c) 2005 The OpenSSL Project. Rights for redistribution
3  * and usage in source and binary forms are granted according to the
4  * OpenSSL license.
5  */
6
7 #include <stdio.h>
8 #if defined(__DECC)
9 # include <c_asm.h>
10 # pragma __nostandard
11 #endif
12
13 #include "e_os.h"
14
15 #if !defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
16 # if    (defined(__sun) && (defined(__sparc) || defined(__sparcv9)))    || \
17         (defined(__sgi) && (defined(__mips) || defined(mips)))          || \
18         (defined(__osf__) && defined(__alpha))                          || \
19         (defined(__linux) && (defined(__arm) || defined(__arm__)))      || \
20         (defined(__i386) || defined(__i386__))                          || \
21         (defined(__x86_64) || defined(__x86_64__))                      || \
22         (defined(vax) || defined(__vax__))
23 #  define POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION
24 # endif
25 #endif
26
27 #if defined(__xlC__) && __xlC__>=0x600 && (defined(_POWER) || defined(_ARCH_PPC))
28 static void *instruction_pointer_xlc(void);
29 # pragma mc_func instruction_pointer_xlc {\
30         "7c0802a6"      /* mflr r0  */  \
31         "48000005"      /* bl   $+4 */  \
32         "7c6802a6"      /* mflr r3  */  \
33         "7c0803a6"      /* mtlr r0  */  }
34 # pragma reg_killed_by instruction_pointer_xlc gr0 gr3
35 # define INSTRUCTION_POINTER_IMPLEMENTED(ret) (ret=instruction_pointer_xlc());
36 #endif
37
38 #ifdef FIPS_START
39 #define FIPS_ref_point FIPS_text_start
40 /* Some compilers put string literals into a separate segment. As we
41  * are mostly interested to hash AES tables in .rodata, we declare
42  * reference points accordingly. In case you wonder, the values are
43  * big-endian encoded variable names, just to prevent these arrays
44  * from being merged by linker. */
45 const unsigned int FIPS_rodata_start[]=
46         { 0x46495053, 0x5f726f64, 0x6174615f, 0x73746172 };
47 #else
48 #define FIPS_ref_point FIPS_text_end
49 const unsigned int FIPS_rodata_end[]=
50         { 0x46495053, 0x5f726f64, 0x6174615f, 0x656e645b };
51 #endif
52
53 /*
54  * I declare reference function as static in order to avoid certain
55  * pitfalls in -dynamic linker behaviour...
56  */
57 static void *instruction_pointer(void)
58 { void *ret=NULL;
59 /* These are ABI-neutral CPU-specific snippets. ABI-neutrality means
60  * that they are designed to work under any OS running on particular
61  * CPU, which is why you don't find any #ifdef THIS_OR_THAT_OS in
62  * this function. */
63 #if     defined(INSTRUCTION_POINTER_IMPLEMENTED)
64     INSTRUCTION_POINTER_IMPLEMENTED(ret);
65 #elif   defined(__GNUC__) && __GNUC__>=2
66 # if    defined(__alpha) || defined(__alpha__)
67 #   define INSTRUCTION_POINTER_IMPLEMENTED
68     __asm __volatile (  "br     %0,1f\n1:" : "=r"(ret) );
69 # elif  defined(__i386) || defined(__i386__)
70 #   define INSTRUCTION_POINTER_IMPLEMENTED
71     __asm __volatile (  "call 1f\n1:    popl %0" : "=r"(ret) );
72     ret = (void *)((size_t)ret&~3UL); /* align for better performance */
73 # elif  defined(__ia64) || defined(__ia64__)
74 #   define INSTRUCTION_POINTER_IMPLEMENTED
75     __asm __volatile (  "mov    %0=ip" : "=r"(ret) );
76 # elif  defined(__hppa) || defined(__hppa__) || defined(__pa_risc)
77 #   define INSTRUCTION_POINTER_IMPLEMENTED
78     __asm __volatile (  "blr    %%r0,%0\n\tnop" : "=r"(ret) );
79     ret = (void *)((size_t)ret&~3UL); /* mask privilege level */
80 # elif  defined(__mips) || defined(__mips__)
81 #   define INSTRUCTION_POINTER_IMPLEMENTED
82     void *scratch;
83     __asm __volatile (  "move   %1,$31\n\t"     /* save ra */
84                         "bal    .+8; nop\n\t"
85                         "move   %0,$31\n\t"
86                         "move   $31,%1"         /* restore ra */
87                         : "=r"(ret),"=r"(scratch) );
88 # elif  defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \
89         defined(__POWERPC__) || defined(_POWER) || defined(__PPC__) || \
90         defined(__PPC64__) || defined(__powerpc64__)
91 #   define INSTRUCTION_POINTER_IMPLEMENTED
92     void *scratch;
93     __asm __volatile (  "mfspr  %1,8\n\t"       /* save lr */
94                         "bl     $+4\n\t"
95                         "mfspr  %0,8\n\t"       /* mflr ret */
96                         "mtspr  8,%1"           /* restore lr */
97                         : "=r"(ret),"=r"(scratch) );
98 # elif  defined(__sparc) || defined(__sparc__) || defined(__sparcv9)
99 #   define INSTRUCTION_POINTER_IMPLEMENTED
100     void *scratch;
101     __asm __volatile (  "mov    %%o7,%1\n\t"
102                         "call   .+8; nop\n\t"
103                         "mov    %%o7,%0\n\t"
104                         "mov    %1,%%o7"
105                         : "=r"(ret),"=r"(scratch) );
106 # elif  defined(__x86_64) || defined(__x86_64__)
107 #   define INSTRUCTION_POINTER_IMPLEMENTED
108     __asm __volatile (  "leaq   0(%%rip),%0" : "=r"(ret) );
109     ret = (void *)((size_t)ret&~3UL); /* align for better performance */
110 # endif
111 #elif   defined(__DECC) && defined(__alpha)
112 #   define INSTRUCTION_POINTER_IMPLEMENTED
113     ret = (void *)(size_t)asm("br %v0,1f\n1:");
114 #elif   defined(_MSC_VER) && defined(_M_IX86)
115 #   define INSTRUCTION_POINTER_IMPLEMENTED
116     void *scratch;
117     _asm {
118             call    self
119     self:   pop     eax
120             mov     scratch,eax
121          }
122     ret = (void *)((size_t)scratch&~3UL);
123 #endif
124   return ret;
125 }
126
127 /*
128  * This function returns pointer to an instruction in the vicinity of
129  * its entry point, but not outside this object module. This guarantees
130  * that sequestered code is covered...
131  */
132 void *FIPS_ref_point()
133 {
134 #if     defined(INSTRUCTION_POINTER_IMPLEMENTED)
135     return instruction_pointer();
136 /* Below we essentially cover vendor compilers which do not support
137  * inline assembler... */
138 #elif   defined(_AIX)
139     struct { void *ip,*gp,*env; } *p = (void *)instruction_pointer;
140     return p->ip;
141 #elif   defined(_HPUX_SOURCE)
142 # if    defined(__hppa) || defined(__hppa__)
143     struct { void *i[4]; } *p = (void *)FIPS_ref_point;
144
145     if (sizeof(p) == 8) /* 64-bit */
146         return p->i[2];
147     else if ((size_t)p & 2)
148     {   p = (void *)((size_t)p&~3UL);
149         return p->i[0];
150     }
151     else
152         return (void *)p;
153 # elif  defined(__ia64) || defined(__ia64__)
154     struct { unsigned long long ip,gp; } *p=(void *)instruction_pointer;
155     return (void *)(size_t)p->ip;
156 # endif
157 #elif   (defined(__VMS) || defined(VMS)) && !(defined(vax) || defined(__vax__))
158     /* applies to both alpha and ia64 */
159     struct { unsigned __int64 opaque,ip; } *p=(void *)instruction_pointer;
160     return (void *)(size_t)p->ip;
161 #elif   defined(__VOS__)
162     /* applies to both pa-risc and ia32 */
163     struct { void *dp,*ip,*gp; } *p = (void *)instruction_pointer;
164     return p->ip;
165 #elif   defined(_WIN32)
166 # if    defined(_WIN64) && defined(_M_IA64)
167     struct { void *ip,*gp; } *p = (void *)FIPS_ref_point;
168     return p->ip;
169 # else
170     return (void *)FIPS_ref_point;
171 # endif
172 /*
173  * In case you wonder why there is no #ifdef __linux. All Linux targets
174  * are GCC-based and therefore are covered by instruction_pointer above
175  * [well, some are covered by by the one below]...
176  */ 
177 #elif   defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
178     return (void *)instruction_pointer;
179 #else
180     return NULL;
181 #endif
182 }