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-endian */ 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 }