9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

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 }