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