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 but11 * the last call. There must be room in the input buffer12 * 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 bytes87 */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 else100 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;119 }121 /*122 * encodes input (ulong) into output (uchar). Assumes len is123 * a multiple of 4.124 */125 static void126 encode(uchar *output, u32int *input, ulong len)127 {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;137 }138 }