docs: various nitpicky doc updates
[girocco.git] / src / lt1.c
blob3351fd9b71bb9b61278888b84d4a778099279e45
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
7 * guarantee it works.
9 * License: public domain -or- http://www.wtfpl.net/txt/copying/
12 /**
13 @file sha1.c
14 LTC_SHA1 code by Tom St Denis
17 #include "lt1.h"
18 #include <stdlib.h>
19 #include <string.h>
21 #ifndef MIN
22 #define MIN(x, y) ( ((x)<(y))?(x):(y) )
23 #endif
25 #define CRYPT_OK 1
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)
47 /* 32-bit Rotates */
48 #if defined(_MSC_VER)
49 #define LTC_ROx_BUILTIN
51 /* instrinsic rotate */
52 #include <stdlib.h>
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)
64 #define LTC_ROx_ASM
66 static inline uint32_t ROL(uint32_t word, int i)
68 asm ("roll %%cl,%0"
69 :"=r" (word)
70 :"0" (word),"c" (i));
71 return word;
74 #ifndef LTC_NO_ROLC
76 #define ROLc(word,i) ({ \
77 uint32_t ROLc_tmp = (word); \
78 __asm__ ("roll %2, %0" : \
79 "=r" (ROLc_tmp) : \
80 "0" (ROLc_tmp), \
81 "I" (i)); \
82 ROLc_tmp; \
85 #else
87 #define ROLc ROL
89 #endif
91 #elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
92 #define LTC_ROx_ASM
94 static inline uint32_t ROL(uint32_t word, int i)
96 asm ("rotlw %0,%0,%2"
97 :"=r" (word)
98 :"0" (word),"r" (i));
99 return word;
102 #ifndef LTC_NO_ROLC
104 static inline uint32_t ROLc(uint32_t word, const int i)
106 asm ("rotlwi %0,%0,%2"
107 :"=r" (word)
108 :"0" (word),"I" (i));
109 return word;
112 #else
114 #define ROLc ROL
116 #endif
118 #else
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)
124 #endif
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; \
131 size_t n; \
132 int err; \
133 if (!md || !in) return 0; \
134 if (md->curlen > sizeof(md->buf)) { \
135 return 0; \
137 if ((md->length + inlen) < md->length) { \
138 return 0; \
140 while (inlen > 0) { \
141 if (md->curlen == 0 && inlen >= block_size) { \
142 if ((err = compress_name(md, in)) != CRYPT_OK) { \
143 return err; \
145 md->length += block_size * 8; \
146 in += block_size; \
147 inlen -= block_size; \
148 } else { \
149 n = MIN(inlen, (block_size - md->curlen)); \
150 memcpy(md->buf + md->curlen, in, (size_t)n); \
151 md->curlen += n; \
152 in += n; \
153 inlen -= n; \
154 if (md->curlen == block_size) { \
155 if ((err = compress_name(md, md->buf)) != CRYPT_OK) { \
156 return err; \
158 md->length += 8*block_size; \
159 md->curlen = 0; \
163 return CRYPT_OK; \
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
175 uint32_t t;
176 #endif
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));
183 /* copy state */
184 a = md->state[0];
185 b = md->state[1];
186 c = md->state[2];
187 d = md->state[3];
188 e = md->state[4];
190 /* expand it */
191 for (i = 16; i < 80; i++) {
192 W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
195 /* compress */
196 /* round one */
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;
208 for (; i < 40; ) {
209 FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
212 for (; i < 60; ) {
213 FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
216 for (; i < 80; ) {
217 FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
220 #else
222 for (i = 0; i < 20; ) {
223 FF0(a,b,c,d,e,i++);
224 FF0(e,a,b,c,d,i++);
225 FF0(d,e,a,b,c,i++);
226 FF0(c,d,e,a,b,i++);
227 FF0(b,c,d,e,a,i++);
230 /* round two */
231 for (; i < 40; ) {
232 FF1(a,b,c,d,e,i++);
233 FF1(e,a,b,c,d,i++);
234 FF1(d,e,a,b,c,i++);
235 FF1(c,d,e,a,b,i++);
236 FF1(b,c,d,e,a,i++);
239 /* round three */
240 for (; i < 60; ) {
241 FF2(a,b,c,d,e,i++);
242 FF2(e,a,b,c,d,i++);
243 FF2(d,e,a,b,c,i++);
244 FF2(c,d,e,a,b,i++);
245 FF2(b,c,d,e,a,i++);
248 /* round four */
249 for (; i < 80; ) {
250 FF3(a,b,c,d,e,i++);
251 FF3(e,a,b,c,d,i++);
252 FF3(d,e,a,b,c,i++);
253 FF3(c,d,e,a,b,i++);
254 FF3(b,c,d,e,a,i++);
256 #endif
258 #undef FF0
259 #undef FF1
260 #undef FF2
261 #undef FF3
263 /* store */
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;
270 return CRYPT_OK;
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)
280 if (!md) return 0;
282 md->curlen = 0;
283 md->length = 0;
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;
289 return CRYPT_OK;
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)
309 int i;
311 if (!md || !out) return 0;
313 if (md->curlen >= sizeof(md->buf)) {
314 return 0;
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);
332 md->curlen = 0;
335 /* pad upto 56 bytes of zeroes */
336 while (md->curlen < 56) {
337 md->buf[md->curlen++] = (unsigned char)0;
340 /* store length */
341 STORE64H(md->length, md->buf+56);
342 sha1_compress(md, md->buf);
344 /* copy output */
345 for (i = 0; i < 5; i++) {
346 STORE32H(md->state[i], out+(4*i));
348 return CRYPT_OK;
351 unsigned char *SHA1(const void *data, size_t len, unsigned char *md)
353 SHA1_CTX c;
355 if (!SHA1_Init(&c)) return NULL;
356 if (!SHA1_Update(&c, data, len)) return NULL;
357 if (!SHA1_Final(md, &c)) return NULL;
358 return md;