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