Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <libsec.h>
5 static void encode(uchar*, u32int*, ulong);
7 extern void _sha1block(uchar*, ulong, u32int*);
9 /*
10 * we require len to be a multiple of 64 for all but
11 * the last call. There must be room in the input buffer
12 * to pad.
13 */
14 ulong lastlen;
16 SHA1state*
17 sha1(uchar *p, ulong len, uchar *digest, SHA1state *s)
18 {
19 uchar buf[128];
20 u32int x[16];
21 int i;
22 uchar *e;
24 lastlen = len;
25 if(s == nil){
26 s = malloc(sizeof(*s));
27 if(s == nil)
28 return nil;
29 memset(s, 0, sizeof(*s));
30 s->malloced = 1;
31 assert(!s->seeded);
32 assert(!s->blen);
33 }
35 if(s->seeded == 0){
36 /* seed the state, these constants would look nicer big-endian */
37 s->state[0] = 0x67452301;
38 s->state[1] = 0xefcdab89;
39 s->state[2] = 0x98badcfe;
40 s->state[3] = 0x10325476;
41 s->state[4] = 0xc3d2e1f0;
42 s->seeded = 1;
43 }
45 assert(len < 100000);
47 /* fill out the partial 64 byte block from previous calls */
48 if(s->blen){
49 assert(s);
50 i = 64 - s->blen;
51 if(len < i)
52 i = len;
53 memmove(s->buf + s->blen, p, i);
54 len -= i;
55 s->blen += i;
56 p += i;
57 if(s->blen == 64){
58 _sha1block(s->buf, s->blen, s->state);
59 s->len += s->blen;
60 s->blen = 0;
61 }
62 }
64 assert(len < 1000000);
65 /* do 64 byte blocks */
66 i = len & ~0x3f;
67 if(i){
68 assert(i < 1000000);
69 _sha1block(p, i, s->state);
70 s->len += i;
71 len -= i;
72 p += i;
73 }
75 /* save the left overs if not last call */
76 if(digest == 0){
77 if(len){
78 memmove(s->buf, p, len);
79 s->blen += len;
80 }
81 return s;
82 }
84 /*
85 * this is the last time through, pad what's left with 0x80,
86 * 0's, and the input count to create a multiple of 64 bytes
87 */
88 if(s->blen){
89 p = s->buf;
90 len = s->blen;
91 } else {
92 memmove(buf, p, len);
93 p = buf;
94 }
95 s->len += len;
96 e = p + len;
97 if(len < 56)
98 i = 56 - len;
99 else
100 i = 120 - len;
101 memset(e, 0, i);
102 *e = 0x80;
103 len += i;
105 /* append the count */
106 x[0] = s->len>>29;
107 x[1] = s->len<<3;
108 encode(p+len, x, 8);
110 /* digest the last part */
111 _sha1block(p, len+8, s->state);
112 s->len += len+8;
114 /* return result and free state */
115 encode(digest, s->state, SHA1dlen);
116 if(s->malloced == 1)
117 free(s);
118 return nil;
121 /*
122 * encodes input (ulong) into output (uchar). Assumes len is
123 * a multiple of 4.
124 */
125 static void
126 encode(uchar *output, u32int *input, ulong len)
128 u32int x;
129 uchar *e;
131 for(e = output + len; output < e;) {
132 x = *input++;
133 *output++ = x >> 24;
134 *output++ = x >> 16;
135 *output++ = x >> 8;
136 *output++ = x;