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