1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 
11 /* ---- HELPER MACROS ---- */
12 #ifdef ENDIAN_NEUTRAL
13 
14 #define STORE32L(x, y)                                                                     \
15   do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
16        (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
17 
18 #define LOAD32L(x, y)                            \
19   do { x = ((ulong32)((y)[3] & 255)<<24) | \
20            ((ulong32)((y)[2] & 255)<<16) | \
21            ((ulong32)((y)[1] & 255)<<8)  | \
22            ((ulong32)((y)[0] & 255)); } while(0)
23 
24 #define STORE64L(x, y)                                                                     \
25   do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255);   \
26        (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255);   \
27        (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
28        (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
29 
30 #define LOAD64L(x, y)                                                       \
31   do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
32            (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
33            (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
34            (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
35 
36 #define STORE32H(x, y)                                                                     \
37   do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255);   \
38        (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
39 
40 #define LOAD32H(x, y)                            \
41   do { x = ((ulong32)((y)[0] & 255)<<24) | \
42            ((ulong32)((y)[1] & 255)<<16) | \
43            ((ulong32)((y)[2] & 255)<<8)  | \
44            ((ulong32)((y)[3] & 255)); } while(0)
45 
46 #define STORE64H(x, y)                                                                     \
47 do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);     \
48      (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);     \
49      (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);     \
50      (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
51 
52 #define LOAD64H(x, y)                                                      \
53 do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
54          (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
55          (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
56          (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0)
57 
58 
59 #elif defined(ENDIAN_LITTLE)
60 
61 #ifdef LTC_HAVE_BSWAP_BUILTIN
62 
63 #define STORE32H(x, y)                          \
64 do { ulong32 __t = __builtin_bswap32 ((x));     \
65       XMEMCPY ((y), &__t, 4); } while(0)
66 
67 #define LOAD32H(x, y)                           \
68 do { XMEMCPY (&(x), (y), 4);                    \
69       (x) = __builtin_bswap32 ((x)); } while(0)
70 
71 #elif !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__))))
72 
73 #define STORE32H(x, y)           \
74 asm __volatile__ (               \
75    "bswapl %0     \n\t"          \
76    "movl   %0,(%1)\n\t"          \
77    "bswapl %0     \n\t"          \
78       ::"r"(x), "r"(y));
79 
80 #define LOAD32H(x, y)          \
81 asm __volatile__ (             \
82    "movl (%1),%0\n\t"          \
83    "bswapl %0\n\t"             \
84    :"=r"(x): "r"(y));
85 
86 #else
87 
88 #define STORE32H(x, y)                                                                     \
89   do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255);   \
90        (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
91 
92 #define LOAD32H(x, y)                            \
93   do { x = ((ulong32)((y)[0] & 255)<<24) | \
94            ((ulong32)((y)[1] & 255)<<16) | \
95            ((ulong32)((y)[2] & 255)<<8)  | \
96            ((ulong32)((y)[3] & 255)); } while(0)
97 
98 #endif
99 
100 #ifdef LTC_HAVE_BSWAP_BUILTIN
101 
102 #define STORE64H(x, y)                          \
103 do { ulong64 __t = __builtin_bswap64 ((x));     \
104       XMEMCPY ((y), &__t, 8); } while(0)
105 
106 #define LOAD64H(x, y)                           \
107 do { XMEMCPY (&(x), (y), 8);                    \
108       (x) = __builtin_bswap64 ((x)); } while(0)
109 
110 /* x86_64 processor */
111 #elif !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__))
112 
113 #define STORE64H(x, y)           \
114 asm __volatile__ (               \
115    "bswapq %0     \n\t"          \
116    "movq   %0,(%1)\n\t"          \
117    "bswapq %0     \n\t"          \
118    ::"r"(x), "r"(y): "memory");
119 
120 #define LOAD64H(x, y)          \
121 asm __volatile__ (             \
122    "movq (%1),%0\n\t"          \
123    "bswapq %0\n\t"             \
124    :"=r"(x): "r"(y): "memory");
125 
126 #else
127 
128 #define STORE64H(x, y)                                                                     \
129 do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);     \
130      (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);     \
131      (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);     \
132      (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
133 
134 #define LOAD64H(x, y)                                                      \
135 do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
136          (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
137          (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
138          (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0)
139 
140 #endif
141 
142 #ifdef ENDIAN_32BITWORD
143 
144 #define STORE32L(x, y)        \
145   do { ulong32  __t = (x); XMEMCPY(y, &__t, 4); } while(0)
146 
147 #define LOAD32L(x, y)         \
148   do { XMEMCPY(&(x), y, 4); } while(0)
149 
150 #define STORE64L(x, y)                                                                     \
151   do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255);   \
152        (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255);   \
153        (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
154        (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
155 
156 #define LOAD64L(x, y)                                                       \
157   do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
158            (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
159            (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
160            (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
161 
162 #else /* 64-bit words then  */
163 
164 #define STORE32L(x, y)        \
165   do { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } while(0)
166 
167 #define LOAD32L(x, y)         \
168   do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0)
169 
170 #define STORE64L(x, y)        \
171   do { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } while(0)
172 
173 #define LOAD64L(x, y)         \
174   do { XMEMCPY(&(x), y, 8); } while(0)
175 
176 #endif /* ENDIAN_64BITWORD */
177 
178 #elif defined(ENDIAN_BIG)
179 
180 #define STORE32L(x, y)                                                                     \
181   do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
182        (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
183 
184 #define LOAD32L(x, y)                            \
185   do { x = ((ulong32)((y)[3] & 255)<<24) | \
186            ((ulong32)((y)[2] & 255)<<16) | \
187            ((ulong32)((y)[1] & 255)<<8)  | \
188            ((ulong32)((y)[0] & 255)); } while(0)
189 
190 #define STORE64L(x, y)                                                                     \
191 do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255);     \
192      (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255);     \
193      (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);     \
194      (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
195 
196 #define LOAD64L(x, y)                                                      \
197 do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
198          (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
199          (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
200          (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
201 
202 #ifdef ENDIAN_32BITWORD
203 
204 #define STORE32H(x, y)        \
205   do { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } while(0)
206 
207 #define LOAD32H(x, y)         \
208   do { XMEMCPY(&(x), y, 4); } while(0)
209 
210 #define STORE64H(x, y)                                                                     \
211   do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);   \
212        (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);   \
213        (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);   \
214        (y)[6] = (unsigned char)(((x)>>8)&255);  (y)[7] = (unsigned char)((x)&255); } while(0)
215 
216 #define LOAD64H(x, y)                                                       \
217   do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
218            (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
219            (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
220            (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } while(0)
221 
222 #else /* 64-bit words then  */
223 
224 #define STORE32H(x, y)        \
225   do { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } while(0)
226 
227 #define LOAD32H(x, y)         \
228   do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0)
229 
230 #define STORE64H(x, y)        \
231   do { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } while(0)
232 
233 #define LOAD64H(x, y)         \
234   do { XMEMCPY(&(x), y, 8); } while(0)
235 
236 #endif /* ENDIAN_64BITWORD */
237 #endif /* ENDIAN_BIG */
238 
239 #define BSWAP(x)  ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL)  | \
240                     ((x>>8)&0x0000FF00UL)  | ((x<<8)&0x00FF0000UL) )
241 
242 
243 /* 32-bit Rotates */
244 #if defined(_MSC_VER)
245 #define LTC_ROx_ASM
246 
247 /* instrinsic rotate */
248 #include <stdlib.h>
249 #pragma intrinsic(_lrotr,_lrotl)
250 #define ROR(x,n) _lrotr(x,n)
251 #define ROL(x,n) _lrotl(x,n)
252 #define RORc(x,n) _lrotr(x,n)
253 #define ROLc(x,n) _lrotl(x,n)
254 
255 #elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
256 #define LTC_ROx_ASM
257 
ROL(ulong32 word,int i)258 static inline ulong32 ROL(ulong32 word, int i)
259 {
260    asm ("roll %%cl,%0"
261       :"=r" (word)
262       :"0" (word),"c" (i));
263    return word;
264 }
265 
ROR(ulong32 word,int i)266 static inline ulong32 ROR(ulong32 word, int i)
267 {
268    asm ("rorl %%cl,%0"
269       :"=r" (word)
270       :"0" (word),"c" (i));
271    return word;
272 }
273 
274 #ifndef LTC_NO_ROLC
275 
276 #define ROLc(word,i) ({ \
277    ulong32 __ROLc_tmp = (word); \
278    __asm__ ("roll %2, %0" : \
279             "=r" (__ROLc_tmp) : \
280             "0" (__ROLc_tmp), \
281             "I" (i)); \
282             __ROLc_tmp; \
283    })
284 #define RORc(word,i) ({ \
285    ulong32 __RORc_tmp = (word); \
286    __asm__ ("rorl %2, %0" : \
287             "=r" (__RORc_tmp) : \
288             "0" (__RORc_tmp), \
289             "I" (i)); \
290             __RORc_tmp; \
291    })
292 
293 #else
294 
295 #define ROLc ROL
296 #define RORc ROR
297 
298 #endif
299 
300 #elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
301 #define LTC_ROx_ASM
302 
ROL(ulong32 word,int i)303 static inline ulong32 ROL(ulong32 word, int i)
304 {
305    asm ("rotlw %0,%0,%2"
306       :"=r" (word)
307       :"0" (word),"r" (i));
308    return word;
309 }
310 
ROR(ulong32 word,int i)311 static inline ulong32 ROR(ulong32 word, int i)
312 {
313    asm ("rotlw %0,%0,%2"
314       :"=r" (word)
315       :"0" (word),"r" (32-i));
316    return word;
317 }
318 
319 #ifndef LTC_NO_ROLC
320 
ROLc(ulong32 word,const int i)321 static inline ulong32 ROLc(ulong32 word, const int i)
322 {
323    asm ("rotlwi %0,%0,%2"
324       :"=r" (word)
325       :"0" (word),"I" (i));
326    return word;
327 }
328 
RORc(ulong32 word,const int i)329 static inline ulong32 RORc(ulong32 word, const int i)
330 {
331    asm ("rotrwi %0,%0,%2"
332       :"=r" (word)
333       :"0" (word),"I" (i));
334    return word;
335 }
336 
337 #else
338 
339 #define ROLc ROL
340 #define RORc ROR
341 
342 #endif
343 
344 
345 #else
346 
347 /* rotates the hard way */
348 #define ROL(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
349 #define ROR(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
350 #define ROLc(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
351 #define RORc(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
352 
353 #endif
354 
355 
356 /* 64-bit Rotates */
357 #if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(_WIN64) && !defined(LTC_NO_ASM)
358 
ROL64(ulong64 word,int i)359 static inline ulong64 ROL64(ulong64 word, int i)
360 {
361    asm("rolq %%cl,%0"
362       :"=r" (word)
363       :"0" (word),"c" (i));
364    return word;
365 }
366 
ROR64(ulong64 word,int i)367 static inline ulong64 ROR64(ulong64 word, int i)
368 {
369    asm("rorq %%cl,%0"
370       :"=r" (word)
371       :"0" (word),"c" (i));
372    return word;
373 }
374 
375 #ifndef LTC_NO_ROLC
376 
377 #define ROL64c(word,i) ({ \
378    ulong64 __ROL64c_tmp = word; \
379    __asm__ ("rolq %2, %0" : \
380             "=r" (__ROL64c_tmp) : \
381             "0" (__ROL64c_tmp), \
382             "J" (i)); \
383             __ROL64c_tmp; \
384    })
385 #define ROR64c(word,i) ({ \
386    ulong64 __ROR64c_tmp = word; \
387    __asm__ ("rorq %2, %0" : \
388             "=r" (__ROR64c_tmp) : \
389             "0" (__ROR64c_tmp), \
390             "J" (i)); \
391             __ROR64c_tmp; \
392    })
393 
394 #else /* LTC_NO_ROLC */
395 
396 #define ROL64c ROL64
397 #define ROR64c ROR64
398 
399 #endif
400 
401 #else /* Not x86_64  */
402 
403 #define ROL64(x, y) \
404     ( (((x)<<((ulong64)(y)&63)) | \
405       (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
406 
407 #define ROR64(x, y) \
408     ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
409       ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
410 
411 #define ROL64c(x, y) \
412     ( (((x)<<((ulong64)(y)&63)) | \
413       (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
414 
415 #define ROR64c(x, y) \
416     ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
417       ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
418 
419 #endif
420 
421 #ifndef MAX
422    #define MAX(x, y) ( ((x)>(y))?(x):(y) )
423 #endif
424 
425 #ifndef MIN
426    #define MIN(x, y) ( ((x)<(y))?(x):(y) )
427 #endif
428 
429 #ifndef LTC_UNUSED_PARAM
430    #define LTC_UNUSED_PARAM(x) (void)(x)
431 #endif
432 
433 /* there is no snprintf before Visual C++ 2015 */
434 #if defined(_MSC_VER) && _MSC_VER < 1900
435 #define snprintf _snprintf
436 #endif
437 
438 /* ref:         $Format:%D$ */
439 /* git commit:  $Format:%H$ */
440 /* commit time: $Format:%ai$ */
441