180ee5cbfSDavid du Colombier #include "os.h"
280ee5cbfSDavid du Colombier #include <libsec.h>
380ee5cbfSDavid du Colombier
480ee5cbfSDavid du Colombier static void encode(uchar*, u32int*, ulong);
580ee5cbfSDavid du Colombier
680ee5cbfSDavid du Colombier extern void _sha1block(uchar*, ulong, u32int*);
780ee5cbfSDavid du Colombier
880ee5cbfSDavid du Colombier /*
980ee5cbfSDavid du Colombier * we require len to be a multiple of 64 for all but
1080ee5cbfSDavid du Colombier * the last call. There must be room in the input buffer
1180ee5cbfSDavid du Colombier * to pad.
1280ee5cbfSDavid du Colombier */
1380ee5cbfSDavid du Colombier SHA1state*
sha1(uchar * p,ulong len,uchar * digest,SHA1state * s)1480ee5cbfSDavid du Colombier sha1(uchar *p, ulong len, uchar *digest, SHA1state *s)
1580ee5cbfSDavid du Colombier {
1680ee5cbfSDavid du Colombier uchar buf[128];
1780ee5cbfSDavid du Colombier u32int x[16];
1880ee5cbfSDavid du Colombier int i;
1980ee5cbfSDavid du Colombier uchar *e;
2080ee5cbfSDavid du Colombier
2180ee5cbfSDavid du Colombier if(s == nil){
2280ee5cbfSDavid du Colombier s = malloc(sizeof(*s));
2380ee5cbfSDavid du Colombier if(s == nil)
2480ee5cbfSDavid du Colombier return nil;
2580ee5cbfSDavid du Colombier memset(s, 0, sizeof(*s));
2680ee5cbfSDavid du Colombier s->malloced = 1;
2780ee5cbfSDavid du Colombier }
2880ee5cbfSDavid du Colombier
2980ee5cbfSDavid du Colombier if(s->seeded == 0){
3080ee5cbfSDavid du Colombier /* seed the state, these constants would look nicer big-endian */
3180ee5cbfSDavid du Colombier s->state[0] = 0x67452301;
3280ee5cbfSDavid du Colombier s->state[1] = 0xefcdab89;
3380ee5cbfSDavid du Colombier s->state[2] = 0x98badcfe;
3480ee5cbfSDavid du Colombier s->state[3] = 0x10325476;
3580ee5cbfSDavid du Colombier s->state[4] = 0xc3d2e1f0;
3680ee5cbfSDavid du Colombier s->seeded = 1;
3780ee5cbfSDavid du Colombier }
3880ee5cbfSDavid du Colombier
3980ee5cbfSDavid du Colombier /* fill out the partial 64 byte block from previous calls */
4080ee5cbfSDavid du Colombier if(s->blen){
4180ee5cbfSDavid du Colombier i = 64 - s->blen;
4280ee5cbfSDavid du Colombier if(len < i)
4380ee5cbfSDavid du Colombier i = len;
4480ee5cbfSDavid du Colombier memmove(s->buf + s->blen, p, i);
4580ee5cbfSDavid du Colombier len -= i;
4680ee5cbfSDavid du Colombier s->blen += i;
4780ee5cbfSDavid du Colombier p += i;
4880ee5cbfSDavid du Colombier if(s->blen == 64){
4980ee5cbfSDavid du Colombier _sha1block(s->buf, s->blen, s->state);
5080ee5cbfSDavid du Colombier s->len += s->blen;
5180ee5cbfSDavid du Colombier s->blen = 0;
5280ee5cbfSDavid du Colombier }
5380ee5cbfSDavid du Colombier }
5480ee5cbfSDavid du Colombier
5580ee5cbfSDavid du Colombier /* do 64 byte blocks */
5680ee5cbfSDavid du Colombier i = len & ~0x3f;
5780ee5cbfSDavid du Colombier if(i){
5880ee5cbfSDavid du Colombier _sha1block(p, i, s->state);
5980ee5cbfSDavid du Colombier s->len += i;
6080ee5cbfSDavid du Colombier len -= i;
6180ee5cbfSDavid du Colombier p += i;
6280ee5cbfSDavid du Colombier }
6380ee5cbfSDavid du Colombier
6480ee5cbfSDavid du Colombier /* save the left overs if not last call */
6580ee5cbfSDavid du Colombier if(digest == 0){
6680ee5cbfSDavid du Colombier if(len){
6780ee5cbfSDavid du Colombier memmove(s->buf, p, len);
6880ee5cbfSDavid du Colombier s->blen += len;
6980ee5cbfSDavid du Colombier }
7080ee5cbfSDavid du Colombier return s;
7180ee5cbfSDavid du Colombier }
7280ee5cbfSDavid du Colombier
7380ee5cbfSDavid du Colombier /*
7480ee5cbfSDavid du Colombier * this is the last time through, pad what's left with 0x80,
7580ee5cbfSDavid du Colombier * 0's, and the input count to create a multiple of 64 bytes
7680ee5cbfSDavid du Colombier */
7780ee5cbfSDavid du Colombier if(s->blen){
7880ee5cbfSDavid du Colombier p = s->buf;
7980ee5cbfSDavid du Colombier len = s->blen;
8080ee5cbfSDavid du Colombier } else {
8180ee5cbfSDavid du Colombier memmove(buf, p, len);
8280ee5cbfSDavid du Colombier p = buf;
8380ee5cbfSDavid du Colombier }
8480ee5cbfSDavid du Colombier s->len += len;
8580ee5cbfSDavid du Colombier e = p + len;
8680ee5cbfSDavid du Colombier if(len < 56)
8780ee5cbfSDavid du Colombier i = 56 - len;
8880ee5cbfSDavid du Colombier else
8980ee5cbfSDavid du Colombier i = 120 - len;
9080ee5cbfSDavid du Colombier memset(e, 0, i);
9180ee5cbfSDavid du Colombier *e = 0x80;
9280ee5cbfSDavid du Colombier len += i;
9380ee5cbfSDavid du Colombier
9480ee5cbfSDavid du Colombier /* append the count */
9580ee5cbfSDavid du Colombier x[0] = s->len>>29;
9680ee5cbfSDavid du Colombier x[1] = s->len<<3;
9780ee5cbfSDavid du Colombier encode(p+len, x, 8);
9880ee5cbfSDavid du Colombier
9980ee5cbfSDavid du Colombier /* digest the last part */
10080ee5cbfSDavid du Colombier _sha1block(p, len+8, s->state);
10180ee5cbfSDavid du Colombier s->len += len+8;
10280ee5cbfSDavid du Colombier
10380ee5cbfSDavid du Colombier /* return result and free state */
10480ee5cbfSDavid du Colombier encode(digest, s->state, SHA1dlen);
10580ee5cbfSDavid du Colombier if(s->malloced == 1)
10680ee5cbfSDavid du Colombier free(s);
10780ee5cbfSDavid du Colombier return nil;
10880ee5cbfSDavid du Colombier }
10980ee5cbfSDavid du Colombier
11080ee5cbfSDavid du Colombier /*
11180ee5cbfSDavid du Colombier * encodes input (ulong) into output (uchar). Assumes len is
11280ee5cbfSDavid du Colombier * a multiple of 4.
11380ee5cbfSDavid du Colombier */
11480ee5cbfSDavid du Colombier static void
encode(uchar * output,u32int * input,ulong len)11580ee5cbfSDavid du Colombier encode(uchar *output, u32int *input, ulong len)
11680ee5cbfSDavid du Colombier {
11780ee5cbfSDavid du Colombier u32int x;
11880ee5cbfSDavid du Colombier uchar *e;
11980ee5cbfSDavid du Colombier
12080ee5cbfSDavid du Colombier for(e = output + len; output < e;) {
12180ee5cbfSDavid du Colombier x = *input++;
12280ee5cbfSDavid du Colombier *output++ = x >> 24;
12380ee5cbfSDavid du Colombier *output++ = x >> 16;
12480ee5cbfSDavid du Colombier *output++ = x >> 8;
12580ee5cbfSDavid du Colombier *output++ = x;
12680ee5cbfSDavid du Colombier }
12780ee5cbfSDavid du Colombier }
128*ff55b41dSDavid du Colombier
129*ff55b41dSDavid du Colombier DigestState*
hmac_sha1(uchar * p,ulong len,uchar * key,ulong klen,uchar * digest,DigestState * s)130*ff55b41dSDavid du Colombier hmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
131*ff55b41dSDavid du Colombier DigestState *s)
132*ff55b41dSDavid du Colombier {
133*ff55b41dSDavid du Colombier return hmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen);
134*ff55b41dSDavid du Colombier }
135