From db6608bd819d10cc2ddb57d18054d62d4ca15596 Mon Sep 17 00:00:00 2001 From: rsc Date: Sun, 23 Nov 2003 18:21:42 +0000 Subject: add libsec --- src/libsec/port/sha1.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/libsec/port/sha1.c (limited to 'src/libsec/port/sha1.c') diff --git a/src/libsec/port/sha1.c b/src/libsec/port/sha1.c new file mode 100644 index 00000000..dabe75f0 --- /dev/null +++ b/src/libsec/port/sha1.c @@ -0,0 +1,138 @@ +#include +#include +#include + +static void encode(uchar*, u32int*, ulong); + +extern void _sha1block(uchar*, ulong, u32int*); + +/* + * we require len to be a multiple of 64 for all but + * the last call. There must be room in the input buffer + * to pad. + */ +ulong lastlen; + +SHA1state* +sha1(uchar *p, ulong len, uchar *digest, SHA1state *s) +{ + uchar buf[128]; + u32int x[16]; + int i; + uchar *e; + +lastlen = len; + if(s == nil){ + s = malloc(sizeof(*s)); + if(s == nil) + return nil; + memset(s, 0, sizeof(*s)); + s->malloced = 1; + assert(!s->seeded); + assert(!s->blen); + } + + if(s->seeded == 0){ + /* seed the state, these constants would look nicer big-endian */ + s->state[0] = 0x67452301; + s->state[1] = 0xefcdab89; + s->state[2] = 0x98badcfe; + s->state[3] = 0x10325476; + s->state[4] = 0xc3d2e1f0; + s->seeded = 1; + } + +assert(len < 100000); + + /* fill out the partial 64 byte block from previous calls */ + if(s->blen){ +assert(s); + i = 64 - s->blen; + if(len < i) + i = len; + memmove(s->buf + s->blen, p, i); + len -= i; + s->blen += i; + p += i; + if(s->blen == 64){ + _sha1block(s->buf, s->blen, s->state); + s->len += s->blen; + s->blen = 0; + } + } + +assert(len < 1000000); + /* do 64 byte blocks */ + i = len & ~0x3f; + if(i){ +assert(i < 1000000); + _sha1block(p, i, s->state); + s->len += i; + len -= i; + p += i; + } + + /* save the left overs if not last call */ + if(digest == 0){ + if(len){ + memmove(s->buf, p, len); + s->blen += len; + } + return s; + } + + /* + * this is the last time through, pad what's left with 0x80, + * 0's, and the input count to create a multiple of 64 bytes + */ + if(s->blen){ + p = s->buf; + len = s->blen; + } else { + memmove(buf, p, len); + p = buf; + } + s->len += len; + e = p + len; + if(len < 56) + i = 56 - len; + else + i = 120 - len; + memset(e, 0, i); + *e = 0x80; + len += i; + + /* append the count */ + x[0] = s->len>>29; + x[1] = s->len<<3; + encode(p+len, x, 8); + + /* digest the last part */ + _sha1block(p, len+8, s->state); + s->len += len+8; + + /* return result and free state */ + encode(digest, s->state, SHA1dlen); + if(s->malloced == 1) + free(s); + return nil; +} + +/* + * encodes input (ulong) into output (uchar). Assumes len is + * a multiple of 4. + */ +static void +encode(uchar *output, u32int *input, ulong len) +{ + u32int x; + uchar *e; + + for(e = output + len; output < e;) { + x = *input++; + *output++ = x >> 24; + *output++ = x >> 16; + *output++ = x >> 8; + *output++ = x; + } +} -- cgit v1.2.3