1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
9 * License: public domain -or- http://www.wtfpl.net/txt/copying/
14 LTC_SHA1 code by Tom St Denis
22 #define MIN(x, y) ( ((x)<(y))?(x):(y) )
26 #define hash_state SHA1_CTX
27 #define sha1_init SHA1_Init
28 #define sha1_process SHA1_Update
29 #define sha1_done SHA1_Final
31 #define STORE32H(x, y) \
32 do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
33 (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
35 #define LOAD32H(x, y) \
36 do { x = ((uint32_t)((y)[0] & 255)<<24) | \
37 ((uint32_t)((y)[1] & 255)<<16) | \
38 ((uint32_t)((y)[2] & 255)<<8) | \
39 ((uint32_t)((y)[3] & 255)); } while(0)
41 #define STORE64H(x, y) \
42 do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
43 (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
44 (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
45 (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
49 #define LTC_ROx_BUILTIN
51 /* instrinsic rotate */
53 #pragma intrinsic(_rotr,_rotl)
54 #define ROL(x,n) _rotl(x,n)
55 #define ROLc(x,n) ROL(x,n)
57 #elif defined(LTC_HAVE_ROTATE_BUILTIN)
58 #define LTC_ROx_BUILTIN
60 #define ROL(x,n) __builtin_rotateleft32(x,n)
61 #define ROLc(x,n) ROL(x,n)
63 #elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
66 static inline uint32_t ROL(uint32_t word
, int i
)
76 #define ROLc(word,i) ({ \
77 uint32_t ROLc_tmp = (word); \
78 __asm__ ("roll %2, %0" : \
91 #elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
94 static inline uint32_t ROL(uint32_t word
, int i
)
104 static inline uint32_t ROLc(uint32_t word
, const int i
)
106 asm ("rotlwi %0,%0,%2"
108 :"0" (word
),"I" (i
));
120 /* rotates the hard way */
121 #define ROL(x, y) ( (((uint32_t)(x)<<(uint32_t)((y)&31)) | (((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
122 #define ROLc(x, y) ( (((uint32_t)(x)<<(uint32_t)((y)&31)) | (((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
126 /* a simple macro for making hash "process" functions */
127 #define HASH_PROCESS(func_name, compress_name, block_size) \
128 int func_name(hash_state *md, const void *_in, size_t inlen) \
130 const unsigned char *in = (const unsigned char *)_in; \
133 if (!md || !in) return 0; \
134 if (md->curlen > sizeof(md->buf)) { \
137 if ((md->length + inlen) < md->length) { \
140 while (inlen > 0) { \
141 if (md->curlen == 0 && inlen >= block_size) { \
142 if ((err = compress_name(md, in)) != CRYPT_OK) { \
145 md->length += block_size * 8; \
147 inlen -= block_size; \
149 n = MIN(inlen, (block_size - md->curlen)); \
150 memcpy(md->buf + md->curlen, in, (size_t)n); \
154 if (md->curlen == block_size) { \
155 if ((err = compress_name(md, md->buf)) != CRYPT_OK) { \
158 md->length += 8*block_size; \
166 #define F0(x,y,z) (z ^ (x & (y ^ z)))
167 #define F1(x,y,z) (x ^ y ^ z)
168 #define F2(x,y,z) ((x & y) | (z & (x | y)))
169 #define F3(x,y,z) (x ^ y ^ z)
171 static int sha1_compress(hash_state
*md
, const unsigned char *buf
)
173 uint32_t a
,b
,c
,d
,e
,W
[80],i
;
174 #ifdef LTC_SMALL_CODE
178 /* copy the state into 512-bits into W[0..15] */
179 for (i
= 0; i
< 16; i
++) {
180 LOAD32H(W
[i
], buf
+ (4*i
));
191 for (i
= 16; i
< 80; i
++) {
192 W
[i
] = ROL(W
[i
-3] ^ W
[i
-8] ^ W
[i
-14] ^ W
[i
-16], 1);
197 #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);
198 #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);
199 #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);
200 #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);
202 #ifdef LTC_SMALL_CODE
204 for (i
= 0; i
< 20; ) {
205 FF0(a
,b
,c
,d
,e
,i
++); t
= e
; e
= d
; d
= c
; c
= b
; b
= a
; a
= t
;
209 FF1(a
,b
,c
,d
,e
,i
++); t
= e
; e
= d
; d
= c
; c
= b
; b
= a
; a
= t
;
213 FF2(a
,b
,c
,d
,e
,i
++); t
= e
; e
= d
; d
= c
; c
= b
; b
= a
; a
= t
;
217 FF3(a
,b
,c
,d
,e
,i
++); t
= e
; e
= d
; d
= c
; c
= b
; b
= a
; a
= t
;
222 for (i
= 0; i
< 20; ) {
264 md
->state
[0] = md
->state
[0] + a
;
265 md
->state
[1] = md
->state
[1] + b
;
266 md
->state
[2] = md
->state
[2] + c
;
267 md
->state
[3] = md
->state
[3] + d
;
268 md
->state
[4] = md
->state
[4] + e
;
274 Initialize the hash state
275 @param md The hash state you wish to initialize
276 @return CRYPT_OK if successful
278 int sha1_init(hash_state
*md
)
284 md
->state
[0] = 0x67452301UL
;
285 md
->state
[1] = 0xefcdab89UL
;
286 md
->state
[2] = 0x98badcfeUL
;
287 md
->state
[3] = 0x10325476UL
;
288 md
->state
[4] = 0xc3d2e1f0UL
;
293 Process a block of memory though the hash
294 @param md The hash state
295 @param in The data to hash
296 @param inlen The length of the data (octets)
297 @return CRYPT_OK if successful
299 HASH_PROCESS(sha1_process
, sha1_compress
, 64)
302 Terminate the hash to get the digest
303 @param md The hash state
304 @param out [out] The destination of the hash (20 bytes)
305 @return CRYPT_OK if successful
307 int sha1_done(unsigned char *out
, hash_state
*md
)
311 if (!md
|| !out
) return 0;
313 if (md
->curlen
>= sizeof(md
->buf
)) {
317 /* increase the length of the message */
318 md
->length
+= md
->curlen
* 8;
320 /* append the '1' bit */
321 md
->buf
[md
->curlen
++] = (unsigned char)0x80;
323 /* if the length is currently above 56 bytes we append zeros
324 * then compress. Then we can fall back to padding zeros and length
325 * encoding like normal.
327 if (md
->curlen
> 56) {
328 while (md
->curlen
< 64) {
329 md
->buf
[md
->curlen
++] = (unsigned char)0;
331 sha1_compress(md
, md
->buf
);
335 /* pad upto 56 bytes of zeroes */
336 while (md
->curlen
< 56) {
337 md
->buf
[md
->curlen
++] = (unsigned char)0;
341 STORE64H(md
->length
, md
->buf
+56);
342 sha1_compress(md
, md
->buf
);
345 for (i
= 0; i
< 5; i
++) {
346 STORE32H(md
->state
[i
], out
+(4*i
));
351 unsigned char *SHA1(const void *data
, size_t len
, unsigned char *md
)
355 if (!SHA1_Init(&c
)) return NULL
;
356 if (!SHA1_Update(&c
, data
, len
)) return NULL
;
357 if (!SHA1_Final(md
, &c
)) return NULL
;