]> pd.if.org Git - uuid/blob - sha1.c
Added tap tests for postgres extension.
[uuid] / sha1.c
1 /*
2  * Adapted from libtomcrypt by Tom St Denis
3  *
4  * by Nathan Wagner and released into the public domain
5  */
6
7 #define ENDIAN_NEUTRAL 1
8 #define LTC_SMALL_CODE 1
9
10 #include "tomcrypt_macros.h"
11 #include "hash.h"
12
13 #define F0(x,y,z)  (z ^ (x & (y ^ z)))
14 #define F1(x,y,z)  (x ^ y ^ z)
15 #define F2(x,y,z)  ((x & y) | (z & (x | y)))
16 #define F3(x,y,z)  (x ^ y ^ z)
17
18 static int  sha1_compress(hash_state *md, unsigned char *buf)
19 {
20     ulong32 a,b,c,d,e,W[80],i;
21 #ifdef LTC_SMALL_CODE
22     ulong32 t;
23 #endif
24
25     /* copy the state into 512-bits into W[0..15] */
26     for (i = 0; i < 16; i++) {
27         LOAD32H(W[i], buf + (4*i));
28     }
29
30     /* copy state */
31     a = md->sha1.state[0];
32     b = md->sha1.state[1];
33     c = md->sha1.state[2];
34     d = md->sha1.state[3];
35     e = md->sha1.state[4];
36
37     /* expand it */
38     for (i = 16; i < 80; i++) {
39         W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); 
40     }
41
42     /* compress */
43     /* round one */
44     #define FF0(a,b,c,d,e,i) e = (ROL(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROL(b, 30);
45     #define FF1(a,b,c,d,e,i) e = (ROL(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROL(b, 30);
46     #define FF2(a,b,c,d,e,i) e = (ROL(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROL(b, 30);
47     #define FF3(a,b,c,d,e,i) e = (ROL(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROL(b, 30);
48  
49 #ifdef LTC_SMALL_CODE
50  
51     for (i = 0; i < 20; ) {
52        FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
53     }
54
55     for (; i < 40; ) {
56        FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
57     }
58
59     for (; i < 60; ) {
60        FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
61     }
62
63     for (; i < 80; ) {
64        FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
65     }
66
67 #else
68
69     for (i = 0; i < 20; ) {
70        FF0(a,b,c,d,e,i++);
71        FF0(e,a,b,c,d,i++);
72        FF0(d,e,a,b,c,i++);
73        FF0(c,d,e,a,b,i++);
74        FF0(b,c,d,e,a,i++);
75     }
76
77     /* round two */
78     for (; i < 40; )  { 
79        FF1(a,b,c,d,e,i++);
80        FF1(e,a,b,c,d,i++);
81        FF1(d,e,a,b,c,i++);
82        FF1(c,d,e,a,b,i++);
83        FF1(b,c,d,e,a,i++);
84     }
85
86     /* round three */
87     for (; i < 60; )  { 
88        FF2(a,b,c,d,e,i++);
89        FF2(e,a,b,c,d,i++);
90        FF2(d,e,a,b,c,i++);
91        FF2(c,d,e,a,b,i++);
92        FF2(b,c,d,e,a,i++);
93     }
94
95     /* round four */
96     for (; i < 80; )  { 
97        FF3(a,b,c,d,e,i++);
98        FF3(e,a,b,c,d,i++);
99        FF3(d,e,a,b,c,i++);
100        FF3(c,d,e,a,b,i++);
101        FF3(b,c,d,e,a,i++);
102     }
103 #endif
104
105     #undef FF0
106     #undef FF1
107     #undef FF2
108     #undef FF3
109
110     /* store */
111     md->sha1.state[0] = md->sha1.state[0] + a;
112     md->sha1.state[1] = md->sha1.state[1] + b;
113     md->sha1.state[2] = md->sha1.state[2] + c;
114     md->sha1.state[3] = md->sha1.state[3] + d;
115     md->sha1.state[4] = md->sha1.state[4] + e;
116
117     return CRYPT_OK;
118 }
119
120 int sha1_init(hash_state * md)
121 {
122    LTC_ARGCHK(md != NULL);
123    md->sha1.state[0] = 0x67452301UL;
124    md->sha1.state[1] = 0xefcdab89UL;
125    md->sha1.state[2] = 0x98badcfeUL;
126    md->sha1.state[3] = 0x10325476UL;
127    md->sha1.state[4] = 0xc3d2e1f0UL;
128    md->sha1.curlen = 0;
129    md->sha1.length = 0;
130    return CRYPT_OK;
131 }
132
133 HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)
134
135 int sha1_done(hash_state * md, unsigned char *out) {
136     int i;
137
138     LTC_ARGCHK(md  != NULL);
139     LTC_ARGCHK(out != NULL);
140
141     if (md->sha1.curlen >= sizeof(md->sha1.buf)) {
142        return CRYPT_INVALID_ARG;
143     }
144
145     /* increase the length of the message */
146     md->sha1.length += md->sha1.curlen * 8;
147
148     /* append the '1' bit */
149     md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
150
151     /* if the length is currently above 56 bytes we append zeros
152      * then compress.  Then we can fall back to padding zeros and length
153      * encoding like normal.
154      */
155     if (md->sha1.curlen > 56) {
156         while (md->sha1.curlen < 64) {
157             md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
158         }
159         sha1_compress(md, md->sha1.buf);
160         md->sha1.curlen = 0;
161     }
162
163     /* pad upto 56 bytes of zeroes */
164     while (md->sha1.curlen < 56) {
165         md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
166     }
167
168     /* store length */
169     STORE64H(md->sha1.length, md->sha1.buf+56);
170     sha1_compress(md, md->sha1.buf);
171
172     /* copy output */
173     for (i = 0; i < 5; i++) {
174         STORE32H(md->sha1.state[i], out+(4*i));
175     }
176 #ifdef LTC_CLEAN_STACK
177     zeromem(md, sizeof(hash_state));
178 #endif
179     return CRYPT_OK;
180 }
181
182 int  sha1_test(void) {
183  #if 0
184     return CRYPT_NOP;
185  #else    
186   static const struct {
187       char *msg;
188       unsigned char hash[20];
189   } tests[] = {
190     { "abc",
191       { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
192         0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
193         0x9c, 0xd0, 0xd8, 0x9d }
194     },
195     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
196       { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
197         0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
198         0xE5, 0x46, 0x70, 0xF1 }
199     }
200   };
201
202   int i;
203   unsigned char tmp[20];
204   hash_state md;
205
206   for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0]));  i++) {
207       sha1_init(&md);
208       sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
209       sha1_done(&md, tmp);
210       if (XMEMCMP(tmp, tests[i].hash, 20) != 0) {
211          return CRYPT_FAIL_TESTVECTOR;
212       }
213   }
214   return CRYPT_OK;
215   #endif
216 }