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