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