Crypto++  8.4
Free C++ class library of cryptographic schemes
ppc_power8.cpp
1 // ppc_power8.cpp - written and placed in the public domain by
2 // Jeffrey Walton, Uri Blumenthal and Marcel Raad.
3 //
4 // This source file uses intrinsics and built-ins to gain access to
5 // Power8 instructions. A separate source file is needed because
6 // additional CXXFLAGS are required to enable the appropriate
7 // instructions sets in some build configurations.
8 
9 #include "pch.h"
10 #include "config.h"
11 
12 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
13 # include <signal.h>
14 # include <setjmp.h>
15 #endif
16 
17 #if defined(_ARCH_PWR8) || defined(__CRYPTO__)
18 # include "ppc_simd.h"
19 #endif
20 
21 // Squash MS LNK4221 and libtool warnings
22 extern const char PPC_POWER8_FNAME[] = __FILE__;
23 
24 NAMESPACE_BEGIN(CryptoPP)
25 
26 // ************************* Feature Probes ************************* //
27 
28 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
29 extern "C" {
30  typedef void (*SigHandler)(int);
31 
32  static jmp_buf s_jmpSIGILL;
33  static void SigIllHandler(int)
34  {
35  longjmp(s_jmpSIGILL, 1);
36  }
37 }
38 #endif // CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
39 
40 #if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
41 
42 bool CPU_ProbePower8()
43 {
44 #if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
45  return false;
46 #elif (_ARCH_PWR8) && defined(CRYPTOPP_POWER8_AVAILABLE)
47 # if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
48 
49  // longjmp and clobber warnings. Volatile is required.
50  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
51  volatile int result = true;
52 
53  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
54  if (oldHandler == SIG_ERR)
55  return false;
56 
57  volatile sigset_t oldMask;
58  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
59  {
60  signal(SIGILL, oldHandler);
61  return false;
62  }
63 
64  if (setjmp(s_jmpSIGILL))
65  result = false;
66  else
67  {
68  // POWER8 added 64-bit SIMD operations
69  const word64 x = W64LIT(0xffffffffffffffff);
70  word64 w1[2] = {x, x}, w2[2] = {4, 6}, w3[2];
71 
72  // Specifically call the VSX loads and stores with 64-bit types
73  #if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__)) || defined(__clang__)
74  const uint64x2_p v1 = vec_xl(0, (unsigned long long*)w1);
75  const uint64x2_p v2 = vec_xl(0, (unsigned long long*)w2);
76  const uint64x2_p v3 = vec_add(v1, v2); // 64-bit add
77  vec_xst(v3, 0, (unsigned long long*)w3);
78  #else
79  const uint64x2_p v1 = (uint64x2_p)vec_vsx_ld(0, (const byte*)w1);
80  const uint64x2_p v2 = (uint64x2_p)vec_vsx_ld(0, (const byte*)w2);
81  const uint64x2_p v3 = vec_add(v1, v2); // 64-bit add
82  vec_vsx_st((uint8x16_p)v3, 0, (byte*)w3);
83  #endif
84 
85  // Relies on integer wrap
86  result = (w3[0] == 3 && w3[1] == 5);
87  }
88 
89  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
90  signal(SIGILL, oldHandler);
91  return result;
92 # endif
93 #else
94  return false;
95 #endif // _ARCH_PWR8
96 }
97 
98 bool CPU_ProbeAES()
99 {
100 #if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
101  return false;
102 #elif (__CRYPTO__) && defined(CRYPTOPP_POWER8_AES_AVAILABLE)
103 # if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
104 
105  // longjmp and clobber warnings. Volatile is required.
106  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
107  volatile int result = true;
108 
109  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
110  if (oldHandler == SIG_ERR)
111  return false;
112 
113  volatile sigset_t oldMask;
114  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
115  {
116  signal(SIGILL, oldHandler);
117  return false;
118  }
119 
120  if (setjmp(s_jmpSIGILL))
121  result = false;
122  else
123  {
124  byte key[16] = {0xA0, 0xFA, 0xFE, 0x17, 0x88, 0x54, 0x2c, 0xb1,
125  0x23, 0xa3, 0x39, 0x39, 0x2a, 0x6c, 0x76, 0x05};
126  byte state[16] = {0x19, 0x3d, 0xe3, 0xb3, 0xa0, 0xf4, 0xe2, 0x2b,
127  0x9a, 0xc6, 0x8d, 0x2a, 0xe9, 0xf8, 0x48, 0x08};
128  byte r[16] = {255}, z[16] = {};
129 
130  uint8x16_p k = (uint8x16_p)VecLoad(0, key);
131  uint8x16_p s = (uint8x16_p)VecLoad(0, state);
132  s = VecEncrypt(s, k);
133  s = VecEncryptLast(s, k);
134  s = VecDecrypt(s, k);
135  s = VecDecryptLast(s, k);
136  VecStore(s, r);
137 
138  result = (0 != std::memcmp(r, z, 16));
139  }
140 
141  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
142  signal(SIGILL, oldHandler);
143  return result;
144 # endif
145 #else
146  return false;
147 #endif // __CRYPTO__
148 }
149 
150 bool CPU_ProbeSHA256()
151 {
152 #if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
153  return false;
154 #elif (__CRYPTO__) && defined(CRYPTOPP_POWER8_SHA_AVAILABLE)
155 # if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
156 
157  // longjmp and clobber warnings. Volatile is required.
158  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
159  volatile int result = false;
160 
161  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
162  if (oldHandler == SIG_ERR)
163  return false;
164 
165  volatile sigset_t oldMask;
166  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
167  {
168  signal(SIGILL, oldHandler);
169  return false;
170  }
171 
172  if (setjmp(s_jmpSIGILL))
173  result = false;
174  else
175  {
176  byte r[16], z[16] = {0};
177  uint8x16_p x = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
178 
179  x = VecSHA256<0,0>(x);
180  x = VecSHA256<0,0xf>(x);
181  x = VecSHA256<1,0>(x);
182  x = VecSHA256<1,0xf>(x);
183  VecStore(x, r);
184 
185  result = (0 == std::memcmp(r, z, 16));
186  }
187 
188  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
189  signal(SIGILL, oldHandler);
190  return result;
191 # endif
192 #else
193  return false;
194 #endif // CRYPTOPP_ALTIVEC_AVAILABLE
195 }
196 
197 bool CPU_ProbeSHA512()
198 {
199 #if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
200  return false;
201 #elif (__CRYPTO__) && defined(CRYPTOPP_POWER8_SHA_AVAILABLE)
202 # if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
203 
204  // longjmp and clobber warnings. Volatile is required.
205  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
206  volatile int result = false;
207 
208  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
209  if (oldHandler == SIG_ERR)
210  return false;
211 
212  volatile sigset_t oldMask;
213  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
214  {
215  signal(SIGILL, oldHandler);
216  return false;
217  }
218 
219  if (setjmp(s_jmpSIGILL))
220  result = false;
221  else
222  {
223  byte r[16], z[16] = {0};
224  uint8x16_p x = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
225 
226  x = VecSHA512<0,0>(x);
227  x = VecSHA512<0,0xf>(x);
228  x = VecSHA512<1,0>(x);
229  x = VecSHA512<1,0xf>(x);
230  VecStore(x, r);
231 
232  result = (0 == std::memcmp(r, z, 16));
233  }
234 
235  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
236  signal(SIGILL, oldHandler);
237  return result;
238 # endif
239 #else
240  return false;
241 #endif // CRYPTOPP_POWER8_AVAILABLE
242 }
243 
244 #endif // PPC32 or PPC64
245 
246 NAMESPACE_END
Library configuration file.
#define W64LIT(x)
Declare an unsigned word64.
Definition: config_int.h:119
unsigned long long word64
64-bit unsigned datatype
Definition: config_int.h:91
Crypto++ library namespace.
Precompiled header file.
Support functions for PowerPC and vector operations.
__vector unsigned char uint8x16_p
Vector of 8-bit elements.
Definition: ppc_simd.h:192
__vector unsigned long long uint64x2_p
Vector of 64-bit elements.
Definition: ppc_simd.h:212
T1 VecEncryptLast(const T1 state, const T2 key)
Final round of AES encryption.
Definition: ppc_simd.h:2634
T1 VecEncrypt(const T1 state, const T2 key)
One round of AES encryption.
Definition: ppc_simd.h:2609
T1 VecDecryptLast(const T1 state, const T2 key)
Final round of AES decryption.
Definition: ppc_simd.h:2684
T1 VecDecrypt(const T1 state, const T2 key)
One round of AES decryption.
Definition: ppc_simd.h:2659
void VecStore(const T data, byte dest[16])
Stores a vector to a byte array.
Definition: ppc_simd.h:895
uint32x4_p VecLoad(const byte src[16])
Loads a vector from a byte array.
Definition: ppc_simd.h:369