]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libsec/port/md5.c
libsec: generalize pbkdf2_hmac_sha1() to pbkdf2_x() passing the hmac as an argument
[plan9front.git] / sys / src / libsec / port / md5.c
1 #include "os.h"
2 #include <libsec.h>
3
4 /*
5  *  rfc1321 requires that I include this.  The code is new.  The constants
6  *  all come from the rfc (hence the copyright).  We trade a table for the
7  *  macros in rfc.  The total size is a lot less. -- presotto
8  *
9  *      Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
10  *      rights reserved.
11  *
12  *      License to copy and use this software is granted provided that it
13  *      is identified as the "RSA Data Security, Inc. MD5 Message-Digest
14  *      Algorithm" in all material mentioning or referencing this software
15  *      or this function.
16  *
17  *      License is also granted to make and use derivative works provided
18  *      that such works are identified as "derived from the RSA Data
19  *      Security, Inc. MD5 Message-Digest Algorithm" in all material
20  *      mentioning or referencing the derived work.
21  *
22  *      RSA Data Security, Inc. makes no representations concerning either
23  *      the merchantability of this software or the suitability of this
24  *      software forany particular purpose. It is provided "as is"
25  *      without express or implied warranty of any kind.
26  *      These notices must be retained in any copies of any part of this
27  *      documentation and/or software.
28  */
29
30 static void encode(uchar*, u32int*, ulong);
31
32 extern void _md5block(uchar*, ulong, u32int*);
33
34 MD5state*
35 md5(uchar *p, ulong len, uchar *digest, MD5state *s)
36 {
37         u32int x[16];
38         uchar buf[128];
39         int i;
40         uchar *e;
41
42         if(s == nil){
43                 s = malloc(sizeof(*s));
44                 if(s == nil)
45                         return nil;
46                 memset(s, 0, sizeof(*s));
47                 s->malloced = 1;
48         }
49
50         if(s->seeded == 0){
51                 /* seed the state, these constants would look nicer big-endian */
52                 s->state[0] = 0x67452301;
53                 s->state[1] = 0xefcdab89;
54                 s->state[2] = 0x98badcfe;
55                 s->state[3] = 0x10325476;
56                 s->seeded = 1;
57         }
58
59         /* fill out the partial 64 byte block from previous calls */
60         if(s->blen){
61                 i = 64 - s->blen;
62                 if(len < i)
63                         i = len;
64                 memmove(s->buf + s->blen, p, i);
65                 len -= i;
66                 s->blen += i;
67                 p += i;
68                 if(s->blen == 64){
69                         _md5block(s->buf, s->blen, s->state);
70                         s->len += s->blen;
71                         s->blen = 0;
72                 }
73         }
74
75         /* do 64 byte blocks */
76         i = len & ~0x3f;
77         if(i){
78                 _md5block(p, i, s->state);
79                 s->len += i;
80                 len -= i;
81                 p += i;
82         }
83
84         /* save the left overs if not last call */
85         if(digest == 0){
86                 if(len){
87                         memmove(s->buf, p, len);
88                         s->blen += len;
89                 }
90                 return s;
91         }
92
93         /*
94          *  this is the last time through, pad what's left with 0x80,
95          *  0's, and the input count to create a multiple of 64 bytes
96          */
97         if(s->blen){
98                 p = s->buf;
99                 len = s->blen;
100         } else {
101                 memmove(buf, p, len);
102                 p = buf;
103         }
104         s->len += len;
105         e = p + len;
106         if(len < 56)
107                 i = 56 - len;
108         else
109                 i = 120 - len;
110         memset(e, 0, i);
111         *e = 0x80;
112         len += i;
113
114         /* append the count */
115         x[0] = s->len<<3;
116         x[1] = s->len>>29;
117         encode(p+len, x, 8);
118
119         /* digest the last part */
120         _md5block(p, len+8, s->state);
121         s->len += len;
122
123         /* return result and free state */
124         encode(digest, s->state, MD5dlen);
125         if(s->malloced == 1)
126                 free(s);
127         return nil;
128 }
129
130 /*
131  *      encodes input (u32int) into output (uchar). Assumes len is
132  *      a multiple of 4.
133  */
134 static void
135 encode(uchar *output, u32int *input, ulong len)
136 {
137         u32int x;
138         uchar *e;
139
140         for(e = output + len; output < e;) {
141                 x = *input++;
142                 *output++ = x;
143                 *output++ = x >> 8;
144                 *output++ = x >> 16;
145                 *output++ = x >> 24;
146         }
147 }
148
149 DigestState*
150 hmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
151         DigestState *s)
152 {
153         return hmac_x(p, len, key, klen, digest, s, md5, MD5dlen);
154 }