fips_canister.c 6.7 KB

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