aboutsummaryrefslogtreecommitdiff
path: root/fips/fips_canister.c
diff options
context:
space:
mode:
Diffstat (limited to 'fips/fips_canister.c')
-rw-r--r--fips/fips_canister.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/fips/fips_canister.c b/fips/fips_canister.c
new file mode 100644
index 000000000000..64580694c48e
--- /dev/null
+++ b/fips/fips_canister.c
@@ -0,0 +1,186 @@
+/* ====================================================================
+ * Copyright (c) 2005 The OpenSSL Project. Rights for redistribution
+ * and usage in source and binary forms are granted according to the
+ * OpenSSL license.
+ */
+
+#include <stdio.h>
+#if defined(__DECC)
+# include <c_asm.h>
+# pragma __nostandard
+#endif
+
+#include "e_os.h"
+
+#if !defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
+# if (defined(__sun) && (defined(__sparc) || defined(__sparcv9))) || \
+ (defined(__sgi) && (defined(__mips) || defined(mips))) || \
+ (defined(__osf__) && defined(__alpha)) || \
+ (defined(__linux) && (defined(__arm) || defined(__arm__))) || \
+ (defined(__i386) || defined(__i386__)) || \
+ (defined(__x86_64) || defined(__x86_64__)) || \
+ (defined(vax) || defined(__vax__))
+# define POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION
+# endif
+#endif
+
+#if defined(__xlC__) && __xlC__>=0x600 && (defined(_POWER) || defined(_ARCH_PPC))
+static void *instruction_pointer_xlc(void);
+# pragma mc_func instruction_pointer_xlc {\
+ "7c0802a6" /* mflr r0 */ \
+ "48000005" /* bl $+4 */ \
+ "7c6802a6" /* mflr r3 */ \
+ "7c0803a6" /* mtlr r0 */ }
+# pragma reg_killed_by instruction_pointer_xlc gr0 gr3
+# define INSTRUCTION_POINTER_IMPLEMENTED(ret) (ret=instruction_pointer_xlc());
+#endif
+
+#ifdef FIPS_START
+#define FIPS_ref_point FIPS_text_start
+/* Some compilers put string literals into a separate segment. As we
+ * are mostly interested to hash AES tables in .rodata, we declare
+ * reference points accordingly. In case you wonder, the values are
+ * big-endian encoded variable names, just to prevent these arrays
+ * from being merged by linker. */
+const unsigned int FIPS_rodata_start[]=
+ { 0x46495053, 0x5f726f64, 0x6174615f, 0x73746172 };
+#else
+#define FIPS_ref_point FIPS_text_end
+const unsigned int FIPS_rodata_end[]=
+ { 0x46495053, 0x5f726f64, 0x6174615f, 0x656e645b };
+#endif
+
+/*
+ * I declare reference function as static in order to avoid certain
+ * pitfalls in -dynamic linker behaviour...
+ */
+static void *instruction_pointer(void)
+{ void *ret=NULL;
+/* These are ABI-neutral CPU-specific snippets. ABI-neutrality means
+ * that they are designed to work under any OS running on particular
+ * CPU, which is why you don't find any #ifdef THIS_OR_THAT_OS in
+ * this function. */
+#if defined(INSTRUCTION_POINTER_IMPLEMENTED)
+ INSTRUCTION_POINTER_IMPLEMENTED(ret);
+#elif defined(__GNUC__) && __GNUC__>=2
+# if defined(__alpha) || defined(__alpha__)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ __asm __volatile ( "br %0,1f\n1:" : "=r"(ret) );
+# elif defined(__i386) || defined(__i386__)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ __asm __volatile ( "call 1f\n1: popl %0" : "=r"(ret) );
+ ret = (void *)((size_t)ret&~3UL); /* align for better performance */
+# elif defined(__ia64) || defined(__ia64__)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ __asm __volatile ( "mov %0=ip" : "=r"(ret) );
+# elif defined(__hppa) || defined(__hppa__) || defined(__pa_risc)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ __asm __volatile ( "blr %%r0,%0\n\tnop" : "=r"(ret) );
+ ret = (void *)((size_t)ret&~3UL); /* mask privilege level */
+# elif defined(__mips) || defined(__mips__)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ void *scratch;
+ __asm __volatile ( "move %1,$31\n\t" /* save ra */
+ "bal .+8; nop\n\t"
+ "move %0,$31\n\t"
+ "move $31,%1" /* restore ra */
+ : "=r"(ret),"=r"(scratch) );
+# elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \
+ defined(__POWERPC__) || defined(_POWER) || defined(__PPC__) || \
+ defined(__PPC64__) || defined(__powerpc64__)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ void *scratch;
+ __asm __volatile ( "mfspr %1,8\n\t" /* save lr */
+ "bl $+4\n\t"
+ "mfspr %0,8\n\t" /* mflr ret */
+ "mtspr 8,%1" /* restore lr */
+ : "=r"(ret),"=r"(scratch) );
+# elif defined(__s390__) || defined(__s390x__)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ __asm __volatile ( "bras %0,1f\n1:" : "=r"(ret) );
+ ret = (void *)((size_t)ret&~3UL);
+# elif defined(__sparc) || defined(__sparc__) || defined(__sparcv9)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ void *scratch;
+ __asm __volatile ( "mov %%o7,%1\n\t"
+ "call .+8; nop\n\t"
+ "mov %%o7,%0\n\t"
+ "mov %1,%%o7"
+ : "=r"(ret),"=r"(scratch) );
+# elif defined(__x86_64) || defined(__x86_64__)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ __asm __volatile ( "leaq 0(%%rip),%0" : "=r"(ret) );
+ ret = (void *)((size_t)ret&~3UL); /* align for better performance */
+# endif
+#elif defined(__DECC) && defined(__alpha)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ ret = (void *)(size_t)asm("br %v0,1f\n1:");
+#elif defined(_MSC_VER) && defined(_M_IX86)
+# define INSTRUCTION_POINTER_IMPLEMENTED
+ void *scratch;
+ _asm {
+ call self
+ self: pop eax
+ mov scratch,eax
+ }
+ ret = (void *)((size_t)scratch&~3UL);
+#endif
+ return ret;
+}
+
+/*
+ * This function returns pointer to an instruction in the vicinity of
+ * its entry point, but not outside this object module. This guarantees
+ * that sequestered code is covered...
+ */
+void *FIPS_ref_point()
+{
+#if defined(INSTRUCTION_POINTER_IMPLEMENTED)
+ return instruction_pointer();
+/* Below we essentially cover vendor compilers which do not support
+ * inline assembler... */
+#elif defined(_AIX)
+ struct { void *ip,*gp,*env; } *p = (void *)instruction_pointer;
+ return p->ip;
+#elif defined(_HPUX_SOURCE)
+# if defined(__hppa) || defined(__hppa__)
+ struct { void *i[4]; } *p = (void *)FIPS_ref_point;
+
+ if (sizeof(p) == 8) /* 64-bit */
+ return p->i[2];
+ else if ((size_t)p & 2)
+ { p = (void *)((size_t)p&~3UL);
+ return p->i[0];
+ }
+ else
+ return (void *)p;
+# elif defined(__ia64) || defined(__ia64__)
+ struct { unsigned long long ip,gp; } *p=(void *)instruction_pointer;
+ return (void *)(size_t)p->ip;
+# endif
+#elif (defined(__VMS) || defined(VMS)) && !(defined(vax) || defined(__vax__))
+ /* applies to both alpha and ia64 */
+ struct { unsigned __int64 opaque,ip; } *p=(void *)instruction_pointer;
+ return (void *)(size_t)p->ip;
+#elif defined(__VOS__)
+ /* applies to both pa-risc and ia32 */
+ struct { void *dp,*ip,*gp; } *p = (void *)instruction_pointer;
+ return p->ip;
+#elif defined(_WIN32)
+# if defined(_WIN64) && defined(_M_IA64)
+ struct { void *ip,*gp; } *p = (void *)FIPS_ref_point;
+ return p->ip;
+# else
+ return (void *)FIPS_ref_point;
+# endif
+/*
+ * In case you wonder why there is no #ifdef __linux. All Linux targets
+ * are GCC-based and therefore are covered by instruction_pointer above
+ * [well, some are covered by by the one below]...
+ */
+#elif defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
+ return (void *)instruction_pointer;
+#else
+ return NULL;
+#endif
+}