xref: /plan9/sys/src/libsec/port/md5.c (revision ff55b41d4e9d2c13b36de2101465a357b4133185)
180ee5cbfSDavid du Colombier #include "os.h"
280ee5cbfSDavid du Colombier #include <libsec.h>
380ee5cbfSDavid du Colombier 
480ee5cbfSDavid du Colombier /*
580ee5cbfSDavid du Colombier  *  rfc1321 requires that I include this.  The code is new.  The constants
680ee5cbfSDavid du Colombier  *  all come from the rfc (hence the copyright).  We trade a table for the
780ee5cbfSDavid du Colombier  *  macros in rfc.  The total size is a lot less. -- presotto
880ee5cbfSDavid du Colombier  *
980ee5cbfSDavid du Colombier  *	Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
1080ee5cbfSDavid du Colombier  *	rights reserved.
1180ee5cbfSDavid du Colombier  *
1280ee5cbfSDavid du Colombier  *	License to copy and use this software is granted provided that it
1380ee5cbfSDavid du Colombier  *	is identified as the "RSA Data Security, Inc. MD5 Message-Digest
1480ee5cbfSDavid du Colombier  *	Algorithm" in all material mentioning or referencing this software
1580ee5cbfSDavid du Colombier  *	or this function.
1680ee5cbfSDavid du Colombier  *
1780ee5cbfSDavid du Colombier  *	License is also granted to make and use derivative works provided
1880ee5cbfSDavid du Colombier  *	that such works are identified as "derived from the RSA Data
1980ee5cbfSDavid du Colombier  *	Security, Inc. MD5 Message-Digest Algorithm" in all material
2080ee5cbfSDavid du Colombier  *	mentioning or referencing the derived work.
2180ee5cbfSDavid du Colombier  *
2280ee5cbfSDavid du Colombier  *	RSA Data Security, Inc. makes no representations concerning either
2380ee5cbfSDavid du Colombier  *	the merchantability of this software or the suitability of this
2480ee5cbfSDavid du Colombier  *	software forany particular purpose. It is provided "as is"
2580ee5cbfSDavid du Colombier  *	without express or implied warranty of any kind.
2680ee5cbfSDavid du Colombier  *	These notices must be retained in any copies of any part of this
2780ee5cbfSDavid du Colombier  *	documentation and/or software.
2880ee5cbfSDavid du Colombier  */
2980ee5cbfSDavid du Colombier 
3080ee5cbfSDavid du Colombier static void encode(uchar*, u32int*, ulong);
3180ee5cbfSDavid du Colombier 
3280ee5cbfSDavid du Colombier extern void _md5block(uchar*, ulong, u32int*);
3380ee5cbfSDavid du Colombier 
3480ee5cbfSDavid du Colombier MD5state*
md5(uchar * p,ulong len,uchar * digest,MD5state * s)3580ee5cbfSDavid du Colombier md5(uchar *p, ulong len, uchar *digest, MD5state *s)
3680ee5cbfSDavid du Colombier {
3780ee5cbfSDavid du Colombier 	u32int x[16];
3880ee5cbfSDavid du Colombier 	uchar buf[128];
3980ee5cbfSDavid du Colombier 	int i;
4080ee5cbfSDavid du Colombier 	uchar *e;
4180ee5cbfSDavid du Colombier 
4280ee5cbfSDavid du Colombier 	if(s == nil){
4380ee5cbfSDavid du Colombier 		s = malloc(sizeof(*s));
4480ee5cbfSDavid du Colombier 		if(s == nil)
4580ee5cbfSDavid du Colombier 			return nil;
4680ee5cbfSDavid du Colombier 		memset(s, 0, sizeof(*s));
4780ee5cbfSDavid du Colombier 		s->malloced = 1;
4880ee5cbfSDavid du Colombier 	}
4980ee5cbfSDavid du Colombier 
5080ee5cbfSDavid du Colombier 	if(s->seeded == 0){
5180ee5cbfSDavid du Colombier 		/* seed the state, these constants would look nicer big-endian */
5280ee5cbfSDavid du Colombier 		s->state[0] = 0x67452301;
5380ee5cbfSDavid du Colombier 		s->state[1] = 0xefcdab89;
5480ee5cbfSDavid du Colombier 		s->state[2] = 0x98badcfe;
5580ee5cbfSDavid du Colombier 		s->state[3] = 0x10325476;
5680ee5cbfSDavid du Colombier 		s->seeded = 1;
5780ee5cbfSDavid du Colombier 	}
5880ee5cbfSDavid du Colombier 
5980ee5cbfSDavid du Colombier 	/* fill out the partial 64 byte block from previous calls */
6080ee5cbfSDavid du Colombier 	if(s->blen){
6180ee5cbfSDavid du Colombier 		i = 64 - s->blen;
6280ee5cbfSDavid du Colombier 		if(len < i)
6380ee5cbfSDavid du Colombier 			i = len;
6480ee5cbfSDavid du Colombier 		memmove(s->buf + s->blen, p, i);
6580ee5cbfSDavid du Colombier 		len -= i;
6680ee5cbfSDavid du Colombier 		s->blen += i;
6780ee5cbfSDavid du Colombier 		p += i;
6880ee5cbfSDavid du Colombier 		if(s->blen == 64){
6980ee5cbfSDavid du Colombier 			_md5block(s->buf, s->blen, s->state);
7080ee5cbfSDavid du Colombier 			s->len += s->blen;
7180ee5cbfSDavid du Colombier 			s->blen = 0;
7280ee5cbfSDavid du Colombier 		}
7380ee5cbfSDavid du Colombier 	}
7480ee5cbfSDavid du Colombier 
7580ee5cbfSDavid du Colombier 	/* do 64 byte blocks */
7680ee5cbfSDavid du Colombier 	i = len & ~0x3f;
7780ee5cbfSDavid du Colombier 	if(i){
7880ee5cbfSDavid du Colombier 		_md5block(p, i, s->state);
7980ee5cbfSDavid du Colombier 		s->len += i;
8080ee5cbfSDavid du Colombier 		len -= i;
8180ee5cbfSDavid du Colombier 		p += i;
8280ee5cbfSDavid du Colombier 	}
8380ee5cbfSDavid du Colombier 
8480ee5cbfSDavid du Colombier 	/* save the left overs if not last call */
8580ee5cbfSDavid du Colombier 	if(digest == 0){
8680ee5cbfSDavid du Colombier 		if(len){
8780ee5cbfSDavid du Colombier 			memmove(s->buf, p, len);
8880ee5cbfSDavid du Colombier 			s->blen += len;
8980ee5cbfSDavid du Colombier 		}
9080ee5cbfSDavid du Colombier 		return s;
9180ee5cbfSDavid du Colombier 	}
9280ee5cbfSDavid du Colombier 
9380ee5cbfSDavid du Colombier 	/*
9480ee5cbfSDavid du Colombier 	 *  this is the last time through, pad what's left with 0x80,
9580ee5cbfSDavid du Colombier 	 *  0's, and the input count to create a multiple of 64 bytes
9680ee5cbfSDavid du Colombier 	 */
9780ee5cbfSDavid du Colombier 	if(s->blen){
9880ee5cbfSDavid du Colombier 		p = s->buf;
9980ee5cbfSDavid du Colombier 		len = s->blen;
10080ee5cbfSDavid du Colombier 	} else {
10180ee5cbfSDavid du Colombier 		memmove(buf, p, len);
10280ee5cbfSDavid du Colombier 		p = buf;
10380ee5cbfSDavid du Colombier 	}
10480ee5cbfSDavid du Colombier 	s->len += len;
10580ee5cbfSDavid du Colombier 	e = p + len;
10680ee5cbfSDavid du Colombier 	if(len < 56)
10780ee5cbfSDavid du Colombier 		i = 56 - len;
10880ee5cbfSDavid du Colombier 	else
10980ee5cbfSDavid du Colombier 		i = 120 - len;
11080ee5cbfSDavid du Colombier 	memset(e, 0, i);
11180ee5cbfSDavid du Colombier 	*e = 0x80;
11280ee5cbfSDavid du Colombier 	len += i;
11380ee5cbfSDavid du Colombier 
11480ee5cbfSDavid du Colombier 	/* append the count */
11580ee5cbfSDavid du Colombier 	x[0] = s->len<<3;
11680ee5cbfSDavid du Colombier 	x[1] = s->len>>29;
11780ee5cbfSDavid du Colombier 	encode(p+len, x, 8);
11880ee5cbfSDavid du Colombier 
11980ee5cbfSDavid du Colombier 	/* digest the last part */
12080ee5cbfSDavid du Colombier 	_md5block(p, len+8, s->state);
12180ee5cbfSDavid du Colombier 	s->len += len;
12280ee5cbfSDavid du Colombier 
12380ee5cbfSDavid du Colombier 	/* return result and free state */
12480ee5cbfSDavid du Colombier 	encode(digest, s->state, MD5dlen);
12580ee5cbfSDavid du Colombier 	if(s->malloced == 1)
12680ee5cbfSDavid du Colombier 		free(s);
12780ee5cbfSDavid du Colombier 	return nil;
12880ee5cbfSDavid du Colombier }
12980ee5cbfSDavid du Colombier 
13080ee5cbfSDavid du Colombier /*
13180ee5cbfSDavid du Colombier  *	encodes input (u32int) into output (uchar). Assumes len is
13280ee5cbfSDavid du Colombier  *	a multiple of 4.
13380ee5cbfSDavid du Colombier  */
13480ee5cbfSDavid du Colombier static void
encode(uchar * output,u32int * input,ulong len)13580ee5cbfSDavid du Colombier encode(uchar *output, u32int *input, ulong len)
13680ee5cbfSDavid du Colombier {
13780ee5cbfSDavid du Colombier 	u32int x;
13880ee5cbfSDavid du Colombier 	uchar *e;
13980ee5cbfSDavid du Colombier 
14080ee5cbfSDavid du Colombier 	for(e = output + len; output < e;) {
14180ee5cbfSDavid du Colombier 		x = *input++;
14280ee5cbfSDavid du Colombier 		*output++ = x;
14380ee5cbfSDavid du Colombier 		*output++ = x >> 8;
14480ee5cbfSDavid du Colombier 		*output++ = x >> 16;
14580ee5cbfSDavid du Colombier 		*output++ = x >> 24;
14680ee5cbfSDavid du Colombier 	}
14780ee5cbfSDavid du Colombier }
148*ff55b41dSDavid du Colombier 
149*ff55b41dSDavid du Colombier DigestState*
hmac_md5(uchar * p,ulong len,uchar * key,ulong klen,uchar * digest,DigestState * s)150*ff55b41dSDavid du Colombier hmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
151*ff55b41dSDavid du Colombier 	DigestState *s)
152*ff55b41dSDavid du Colombier {
153*ff55b41dSDavid du Colombier 	return hmac_x(p, len, key, klen, digest, s, md5, MD5dlen);
154*ff55b41dSDavid du Colombier }
155