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