/src/resiprocate/rutil/vmd5.cxx
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * This code implements the MD5 message-digest algorithm. |
3 | | * The algorithm is due to Ron Rivest. This code was |
4 | | * written by Colin Plumb in 1993, no copyright is claimed. |
5 | | * This code is in the public domain; do with it what you wish. |
6 | | * |
7 | | * Equivalent code is available from RSA Data Security, Inc. |
8 | | * This code has been tested against that, and is equivalent, |
9 | | * except that you don't need to include two pages of legalese |
10 | | * with every copy. |
11 | | * |
12 | | * To compute the message digest of a chunk of bytes, declare an |
13 | | * MD5Context structure, pass it to MD5Init, call MD5Update as |
14 | | * needed on buffers full of bytes, and then call MD5Final, which |
15 | | * will fill a supplied 16-byte array with the digest. |
16 | | * |
17 | | * Changed so as no longer to depend on Colin Plumb's `usual.h' header |
18 | | * definitions; now uses stuff from dpkg's config.h. |
19 | | * - Ian Jackson <ijackson@nyx.cs.du.edu>. |
20 | | * Still in the public domain. |
21 | | */ |
22 | | |
23 | | #include <string.h> /* for memcpy() */ |
24 | | #include <sys/types.h> /* for stupid systems */ |
25 | | |
26 | | #ifndef WIN32 |
27 | | #include <netinet/in.h> /* for ntohl() */ |
28 | | #endif |
29 | | |
30 | | #include "rutil/vmd5.hxx" |
31 | | |
32 | | /* Add _BIG_ENDIAN for Solaris */ |
33 | | /* Add _BIG_ENDIAN__ for MAC OSX */ |
34 | | #if defined(WORDS_BIGENDIAN) || defined(_BIG_ENDIAN) || defined( __BIG_ENDIAN__ ) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || defined(RESIP_BIG_ENDIAN) |
35 | | void |
36 | | resip::byteSwap(u_int32_t *buf, unsigned words) |
37 | | { |
38 | | md5byte *p = (md5byte *)buf; |
39 | | |
40 | | do |
41 | | { |
42 | | *buf++ = (u_int32_t)((unsigned)p[3] << 8 | p[2]) << 16 | |
43 | | ((unsigned)p[1] << 8 | p[0]); |
44 | | p += 4; |
45 | | } |
46 | | while (--words); |
47 | | } |
48 | | #else |
49 | | #define byteSwap(buf,words) |
50 | | #endif |
51 | | |
52 | | |
53 | | /* |
54 | | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious |
55 | | * initialization constants. |
56 | | */ |
57 | | void |
58 | | resip::MD5Init(struct MD5Context *ctx) |
59 | 0 | { |
60 | 0 | ctx->buf[0] = 0x67452301; |
61 | 0 | ctx->buf[1] = 0xefcdab89; |
62 | 0 | ctx->buf[2] = 0x98badcfe; |
63 | 0 | ctx->buf[3] = 0x10325476; |
64 | |
|
65 | 0 | ctx->bytes[0] = 0; |
66 | 0 | ctx->bytes[1] = 0; |
67 | 0 | } |
68 | | |
69 | | /* |
70 | | * Update context to reflect the concatenation of another buffer full |
71 | | * of bytes. |
72 | | */ |
73 | | void |
74 | | resip::MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) |
75 | 0 | { |
76 | 0 | u_int32_t t; |
77 | | |
78 | | /* Update byte count */ |
79 | |
|
80 | 0 | t = ctx->bytes[0]; |
81 | 0 | if ((ctx->bytes[0] = t + len) < t) |
82 | 0 | ctx->bytes[1]++; /* Carry from low to high */ |
83 | |
|
84 | 0 | t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ |
85 | 0 | if (t > len) |
86 | 0 | { |
87 | 0 | memcpy((md5byte *)ctx->in + 64 - t, buf, len); |
88 | 0 | return ; |
89 | 0 | } |
90 | | /* First chunk is an odd size */ |
91 | 0 | memcpy((md5byte *)ctx->in + 64 - t, buf, t); |
92 | 0 | byteSwap(ctx->in, 16); |
93 | 0 | MD5Transform(ctx->buf, ctx->in); |
94 | 0 | buf += t; |
95 | 0 | len -= t; |
96 | | |
97 | | /* Process data in 64-byte chunks */ |
98 | 0 | while (len >= 64) |
99 | 0 | { |
100 | 0 | memcpy(ctx->in, buf, 64); |
101 | 0 | byteSwap(ctx->in, 16); |
102 | 0 | MD5Transform(ctx->buf, ctx->in); |
103 | 0 | buf += 64; |
104 | 0 | len -= 64; |
105 | 0 | } |
106 | | |
107 | | /* Handle any remaining bytes of data. */ |
108 | 0 | memcpy(ctx->in, buf, len); |
109 | 0 | } |
110 | | |
111 | | /* |
112 | | * Final wrapup - pad to 64-byte boundary with the bit pattern |
113 | | * 1 0* (64-bit count of bits processed, MSB-first) |
114 | | */ |
115 | | void |
116 | | resip::MD5Final(md5byte digest[16], struct MD5Context *ctx) |
117 | 0 | { |
118 | 0 | int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ |
119 | 0 | md5byte *p = (md5byte *)ctx->in + count; |
120 | | |
121 | | /* Set the first char of padding to 0x80. There is always room. */ |
122 | 0 | *p++ = 0x80; |
123 | | |
124 | | /* Bytes of padding needed to make 56 bytes (-8..55) */ |
125 | 0 | count = 56 - 1 - count; |
126 | |
|
127 | 0 | if (count < 0) |
128 | 0 | { /* Padding forces an extra block */ |
129 | 0 | memset(p, 0, count + 8); |
130 | 0 | byteSwap(ctx->in, 16); |
131 | 0 | MD5Transform(ctx->buf, ctx->in); |
132 | 0 | p = (md5byte *)ctx->in; |
133 | 0 | count = 56; |
134 | 0 | } |
135 | 0 | memset(p, 0, count); |
136 | 0 | byteSwap(ctx->in, 14); |
137 | | |
138 | | /* Append length in bits and transform */ |
139 | 0 | ctx->in[14] = ctx->bytes[0] << 3; |
140 | 0 | ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; |
141 | 0 | MD5Transform(ctx->buf, ctx->in); |
142 | |
|
143 | 0 | byteSwap(ctx->buf, 4); |
144 | 0 | memcpy(digest, ctx->buf, 16); |
145 | 0 | memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ |
146 | 0 | } |
147 | | |
148 | | #ifndef ASM_MD5 |
149 | | |
150 | | /* The four core functions - F1 is optimized somewhat */ |
151 | | |
152 | | /* #define F1(x, y, z) (x & y | ~x & z) */ |
153 | 0 | #define F1(x, y, z) (z ^ (x & (y ^ z))) |
154 | 0 | #define F2(x, y, z) F1(z, x, y) |
155 | 0 | #define F3(x, y, z) (x ^ y ^ z) |
156 | 0 | #define F4(x, y, z) (y ^ (x | ~z)) |
157 | | |
158 | | /* This is the central step in the MD5 algorithm. */ |
159 | 0 | #define MD5STEP(f,w,x,y,z,in,s) \ |
160 | 0 | (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x) |
161 | | |
162 | | /* |
163 | | * The core of the MD5 algorithm, this alters an existing MD5 hash to |
164 | | * reflect the addition of 16 longwords of new data. MD5Update blocks |
165 | | * the data and converts bytes into longwords for this routine. |
166 | | */ |
167 | | void |
168 | | resip::MD5Transform(u_int32_t buf[4], u_int32_t const in[16]) |
169 | 0 | { |
170 | 0 | u_int32_t a, b, c, d; |
171 | |
|
172 | 0 | a = buf[0]; |
173 | 0 | b = buf[1]; |
174 | 0 | c = buf[2]; |
175 | 0 | d = buf[3]; |
176 | |
|
177 | 0 | MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); |
178 | 0 | MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); |
179 | 0 | MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); |
180 | 0 | MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); |
181 | 0 | MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); |
182 | 0 | MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); |
183 | 0 | MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); |
184 | 0 | MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); |
185 | 0 | MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); |
186 | 0 | MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); |
187 | 0 | MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); |
188 | 0 | MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); |
189 | 0 | MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); |
190 | 0 | MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); |
191 | 0 | MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); |
192 | 0 | MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); |
193 | |
|
194 | 0 | MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); |
195 | 0 | MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); |
196 | 0 | MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); |
197 | 0 | MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); |
198 | 0 | MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); |
199 | 0 | MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); |
200 | 0 | MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); |
201 | 0 | MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); |
202 | 0 | MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); |
203 | 0 | MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); |
204 | 0 | MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); |
205 | 0 | MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); |
206 | 0 | MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); |
207 | 0 | MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); |
208 | 0 | MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); |
209 | 0 | MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); |
210 | |
|
211 | 0 | MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); |
212 | 0 | MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); |
213 | 0 | MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); |
214 | 0 | MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); |
215 | 0 | MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); |
216 | 0 | MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); |
217 | 0 | MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); |
218 | 0 | MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); |
219 | 0 | MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); |
220 | 0 | MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); |
221 | 0 | MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); |
222 | 0 | MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); |
223 | 0 | MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); |
224 | 0 | MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); |
225 | 0 | MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); |
226 | 0 | MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); |
227 | |
|
228 | 0 | MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); |
229 | 0 | MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); |
230 | 0 | MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); |
231 | 0 | MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); |
232 | 0 | MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); |
233 | 0 | MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); |
234 | 0 | MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); |
235 | 0 | MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); |
236 | 0 | MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); |
237 | 0 | MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); |
238 | 0 | MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); |
239 | 0 | MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); |
240 | 0 | MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); |
241 | 0 | MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); |
242 | 0 | MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); |
243 | 0 | MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); |
244 | |
|
245 | 0 | buf[0] += a; |
246 | 0 | buf[1] += b; |
247 | 0 | buf[2] += c; |
248 | 0 | buf[3] += d; |
249 | 0 | } |
250 | | |
251 | | #endif |
252 | | |
253 | | /* ==================================================================== |
254 | | * The Vovida Software License, Version 1.0 |
255 | | * |
256 | | * Copyright (c) 2000-2005 Vovida Networks, Inc. All rights reserved. |
257 | | * |
258 | | * Redistribution and use in source and binary forms, with or without |
259 | | * modification, are permitted provided that the following conditions |
260 | | * are met: |
261 | | * |
262 | | * 1. Redistributions of source code must retain the above copyright |
263 | | * notice, this list of conditions and the following disclaimer. |
264 | | * |
265 | | * 2. Redistributions in binary form must reproduce the above copyright |
266 | | * notice, this list of conditions and the following disclaimer in |
267 | | * the documentation and/or other materials provided with the |
268 | | * distribution. |
269 | | * |
270 | | * 3. The names "VOCAL", "Vovida Open Communication Application Library", |
271 | | * and "Vovida Open Communication Application Library (VOCAL)" must |
272 | | * not be used to endorse or promote products derived from this |
273 | | * software without prior written permission. For written |
274 | | * permission, please contact vocal@vovida.org. |
275 | | * |
276 | | * 4. Products derived from this software may not be called "VOCAL", nor |
277 | | * may "VOCAL" appear in their name, without prior written |
278 | | * permission of Vovida Networks, Inc. |
279 | | * |
280 | | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
281 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
282 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
283 | | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA |
284 | | * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES |
285 | | * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, |
286 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
287 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
288 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
289 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
290 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
291 | | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
292 | | * DAMAGE. |
293 | | * |
294 | | * ==================================================================== |
295 | | * |
296 | | * This software consists of voluntary contributions made by Vovida |
297 | | * Networks, Inc. and many individuals on behalf of Vovida Networks, |
298 | | * Inc. For more information on Vovida Networks, Inc., please see |
299 | | * <http://www.vovida.org/>. |
300 | | * |
301 | | */ |