Fix protocol downgrade bug in case of fragmented packets
[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 const void         *FIPS_text_start(void);
14 const void         *FIPS_text_end(void);
15
16 #include "e_os.h"
17
18 #if !defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
19 # if    (defined(__sun) && (defined(__sparc) || defined(__sparcv9)))    || \
20         (defined(__sgi) && (defined(__mips) || defined(mips)))          || \
21         (defined(__osf__) && defined(__alpha))                          || \
22         (defined(__linux) && (defined(__arm) || defined(__arm__)))      || \
23         (defined(__i386) || defined(__i386__))                          || \
24         (defined(__x86_64) || defined(__x86_64__))                      || \
25         (defined(vax) || defined(__vax__))
26 #  define POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION
27 # endif
28 #endif
29
30 #if !defined(FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE)
31 # if    (defined(__ANDROID__) && (defined(__arm__) || defined(__arm)    || \
32                                   defined(__i386__)|| defined(__i386))) || \
33         (defined(__vxworks)   && (defined(__ppc__) || defined(__ppc)    || \
34                                   defined(__mips__)|| defined(__mips))) || \
35         (defined(__linux)     && ((defined(__PPC__) && !defined(__PPC64__)) || \
36                                   defined(__arm__) || defined(__arm)))  || \
37         (defined(__APPLE__) /* verified on all MacOS X & iOS flavors */)|| \
38         (defined(_WIN32)      && defined(_MSC_VER))
39 #  define FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE
40 # endif
41 #endif
42
43 #if defined(__xlC__) && __xlC__>=0x600 && (defined(_POWER) || defined(_ARCH_PPC))
44 static void *instruction_pointer_xlc(void);
45 # pragma mc_func instruction_pointer_xlc {\
46         "7c0802a6"      /* mflr r0  */  \
47         "48000005"      /* bl   $+4 */  \
48         "7c6802a6"      /* mflr r3  */  \
49         "7c0803a6"      /* mtlr r0  */  }
50 # pragma reg_killed_by instruction_pointer_xlc gr0 gr3
51 # define INSTRUCTION_POINTER_IMPLEMENTED(ret) (ret=instruction_pointer_xlc());
52 #endif
53
54 #ifdef FIPS_START
55 # define FIPS_ref_point FIPS_text_start
56 # ifdef FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE
57 #  define instruction_pointer   FIPS_text_startX
58 # endif
59 /* Some compilers put string literals into a separate segment. As we
60  * are mostly interested to hash AES tables in .rodata, we declare
61  * reference points accordingly. In case you wonder, the values are
62  * big-endian encoded variable names, just to prevent these arrays
63  * from being merged by linker. */
64 # if defined(_MSC_VER)
65 #  pragma code_seg("fipstx")
66 #  pragma code_seg()
67    __declspec(allocate("fipstx"))
68 const unsigned int FIPS_text_startX[]=
69         { 0x46495053, 0x5f746578, 0x745f7374, 0x61727458 };
70 #  pragma const_seg("fipsro$a")
71 #  pragma const_seg()
72    __declspec(allocate("fipsro$a"))
73 # endif
74 const unsigned int FIPS_rodata_start[]=
75         { 0x46495053, 0x5f726f64, 0x6174615f, 0x73746172 };
76 #else
77 # define FIPS_ref_point FIPS_text_end
78 # ifdef FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE
79 #  define instruction_pointer   FIPS_text_endX
80 # endif
81 # if defined(_MSC_VER)
82 #  pragma code_seg("fipstx$z")
83 #  pragma code_seg()
84    __declspec(allocate("fipstx$z"))
85 const unsigned int FIPS_text_endX[]=
86         { 0x46495053, 0x5f746578, 0x745f656e, 0x64585b5d };
87 #  pragma const_seg("fipsro$z")
88 #  pragma const_seg()
89    __declspec(allocate("fipsro$z"))
90 # endif
91 const unsigned int FIPS_rodata_end[]=
92         { 0x46495053, 0x5f726f64, 0x6174615f, 0x656e645b };
93 #endif
94
95 #if !defined(_MSC_VER) || !defined(instruction_pointer)
96 /*
97  * I declare reference function as static in order to avoid certain
98  * pitfalls in -dynamic linker behaviour...
99  */
100 static void *instruction_pointer(void)
101 { void *ret=NULL;
102 /* These are ABI-neutral CPU-specific snippets. ABI-neutrality means
103  * that they are designed to work under any OS running on particular
104  * CPU, which is why you don't find any #ifdef THIS_OR_THAT_OS in
105  * this function. */
106 #if     defined(INSTRUCTION_POINTER_IMPLEMENTED)
107     INSTRUCTION_POINTER_IMPLEMENTED(ret);
108 #elif   defined(__GNUC__) && __GNUC__>=2
109 # if    defined(__alpha) || defined(__alpha__)
110 #   define INSTRUCTION_POINTER_IMPLEMENTED
111     __asm __volatile (  "br     %0,1f\n1:" : "=r"(ret) );
112 # elif  defined(__i386) || defined(__i386__)
113 #   define INSTRUCTION_POINTER_IMPLEMENTED
114     __asm __volatile (  "call 1f\n1:    popl %0" : "=r"(ret) );
115     ret = (void *)((size_t)ret&~3UL); /* align for better performance */
116 # elif  defined(__ia64) || defined(__ia64__)
117 #   define INSTRUCTION_POINTER_IMPLEMENTED
118     __asm __volatile (  "mov    %0=ip" : "=r"(ret) );
119 # elif  defined(__hppa) || defined(__hppa__) || defined(__pa_risc)
120 #   define INSTRUCTION_POINTER_IMPLEMENTED
121     __asm __volatile (  "blr    %%r0,%0\n\tnop" : "=r"(ret) );
122     ret = (void *)((size_t)ret&~3UL); /* mask privilege level */
123 # elif  defined(__mips) || defined(__mips__)
124 #   define INSTRUCTION_POINTER_IMPLEMENTED
125     void *scratch;
126     __asm __volatile (  "move   %1,$31\n\t"     /* save ra */
127                         "bal    .+8; nop\n\t"
128                         "move   %0,$31\n\t"
129                         "move   $31,%1"         /* restore ra */
130                         : "=r"(ret),"=r"(scratch) );
131 # elif  defined(__ppc__) || defined(__ppc) || \
132         defined(__powerpc) || defined(__powerpc__) || \
133         defined(__POWERPC__) || defined(_POWER) || defined(__PPC__) || \
134         defined(__PPC64__) || defined(__ppc64__) || defined(__powerpc64__)
135 #   define INSTRUCTION_POINTER_IMPLEMENTED
136     void *scratch;
137     __asm __volatile (  "mfspr  %1,8\n\t"       /* save lr */
138                         "bl     $+4\n\t"
139                         "mfspr  %0,8\n\t"       /* mflr ret */
140                         "mtspr  8,%1"           /* restore lr */
141                         : "=r"(ret),"=r"(scratch) );
142 # elif  defined(__s390__) || defined(__s390x__)
143 #   define INSTRUCTION_POINTER_IMPLEMENTED
144     __asm __volatile (  "bras   %0,1f\n1:" : "=r"(ret) );
145     ret = (void *)((size_t)ret&~3UL);
146 # elif  defined(__sparc) || defined(__sparc__) || defined(__sparcv9)
147 #   define INSTRUCTION_POINTER_IMPLEMENTED
148     void *scratch;
149     __asm __volatile (  "mov    %%o7,%1\n\t"
150                         "call   .+8; nop\n\t"
151                         "mov    %%o7,%0\n\t"
152                         "mov    %1,%%o7"
153                         : "=r"(ret),"=r"(scratch) );
154 # elif  defined(__x86_64) || defined(__x86_64__)
155 #   define INSTRUCTION_POINTER_IMPLEMENTED
156     __asm __volatile (  "leaq   0(%%rip),%0" : "=r"(ret) );
157     ret = (void *)((size_t)ret&~3UL); /* align for better performance */
158 # elif defined(__arm) || defined(__arm__)
159 #   define INSTRUCTION_POINTER_IMPLEMENTED
160     __asm __volatile (  "sub    %0,pc,#8" : "=r"(ret) );
161 # endif
162 #elif   defined(__DECC) && defined(__alpha)
163 #   define INSTRUCTION_POINTER_IMPLEMENTED
164     ret = (void *)(size_t)asm("br %v0,1f\n1:");
165 #elif   defined(_MSC_VER) && defined(_M_IX86)
166 #   define INSTRUCTION_POINTER_IMPLEMENTED
167     void *scratch;
168     _asm {
169             call    self
170     self:   pop     eax
171             mov     scratch,eax
172          }
173     ret = (void *)((size_t)scratch&~3UL);
174 #endif
175   return ret;
176 }
177 #endif
178
179 /*
180  * This function returns pointer to an instruction in the vicinity of
181  * its entry point, but not outside this object module. This guarantees
182  * that sequestered code is covered...
183  */
184 const void *FIPS_ref_point()
185 {
186 #if     defined(FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE)
187 # if defined(__thumb__) || defined(__thumb)
188     return (void *)((size_t)instruction_pointer&~1);
189 # else
190     return (void *)instruction_pointer;
191 # endif
192 #elif   defined(INSTRUCTION_POINTER_IMPLEMENTED)
193     return instruction_pointer();
194 /* Below we essentially cover vendor compilers which do not support
195  * inline assembler... */
196 #elif   defined(_AIX)
197     struct { void *ip,*gp,*env; } *p = (void *)instruction_pointer;
198     return p->ip;
199 #elif   defined(_HPUX_SOURCE)
200 # if    defined(__hppa) || defined(__hppa__)
201     struct { void *i[4]; } *p = (void *)FIPS_ref_point;
202
203     if (sizeof(p) == 8) /* 64-bit */
204         return p->i[2];
205     else if ((size_t)p & 2)
206     {   p = (void *)((size_t)p&~3UL);
207         return p->i[0];
208     }
209     else
210         return (void *)p;
211 # elif  defined(__ia64) || defined(__ia64__)
212     struct { unsigned long long ip,gp; } *p=(void *)instruction_pointer;
213     return (void *)(size_t)p->ip;
214 # endif
215 #elif   (defined(__VMS) || defined(VMS)) && !(defined(vax) || defined(__vax__))
216     /* applies to both alpha and ia64 */
217     struct { unsigned __int64 opaque,ip; } *p=(void *)instruction_pointer;
218     return (void *)(size_t)p->ip;
219 #elif   defined(__VOS__)
220     /* applies to both pa-risc and ia32 */
221     struct { void *dp,*ip,*gp; } *p = (void *)instruction_pointer;
222     return p->ip;
223 #elif   defined(_WIN32)
224 # if    defined(_WIN64) && defined(_M_IA64)
225     struct { void *ip,*gp; } *p = (void *)FIPS_ref_point;
226     return p->ip;
227 # else
228     return (void *)FIPS_ref_point;
229 # endif
230 /*
231  * In case you wonder why there is no #ifdef __linux. All Linux targets
232  * are GCC-based and therefore are covered by instruction_pointer above
233  * [well, some are covered by by the one below]...
234  */ 
235 #elif   defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
236     return (void *)instruction_pointer;
237 #else
238     return NULL;
239 #endif
240 }