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