blob: 4079bda45ffecab57e1e1045f80c81dde290c4eb [file] [log] [blame]
Brian Waters13d96012017-12-08 16:53:31 -06001/*********************************************************************************/
2/* freeDiameter author note:
3 * The content from this file comes directly from the hostap project.
4 * It is redistributed under the terms of the BSD license, as allowed
5 * by the original copyright reproduced below.
6 * In addition to this notice, only the #include directives have been modified.
7 */
8
9/*********************************************************************************/
10#include"app_sip.h"
11
12/*
13 * MD5 hash implementation and interface functions
14 * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2 as
18 * published by the Free Software Foundation.
19 *
20 * Alternatively, this software may be distributed under the terms of BSD
21 * license.
22 *
23 * See README and COPYING for more details.
24 */
25void CvtHex(
26 IN HASH Bin,
27 OUT HASHHEX Hex
28 )
29{
30 unsigned short i;
31 unsigned char j;
32
33 for (i = 0; i < HASHLEN; i++) {
34 j = (Bin[i] >> 4) & 0xf;
35 if (j <= 9)
36 Hex[i*2] = (j + '0');
37 else
38 Hex[i*2] = (j + 'a' - 10);
39 j = Bin[i] & 0xf;
40 if (j <= 9)
41 Hex[i*2+1] = (j + '0');
42 else
43 Hex[i*2+1] = (j + 'a' - 10);
44 }
45 Hex[HASHHEXLEN] = '\0';
46}
47
48// calculate H(A1) as per spec
49void DigestCalcHA1(char * pszAlg,char * pszUserName,char * pszRealm,char * pszPassword,char * pszNonce,char * pszCNonce,HASHHEX SessionKey)
50{
51 MD5_CTX Md5Ctx;
52 HASH HA1;
53
54 MD5Init(&Md5Ctx);
55 MD5Update(&Md5Ctx, (const unsigned char *)pszUserName, strlen(pszUserName));
56 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
57 MD5Update(&Md5Ctx, (const unsigned char *)pszRealm, strlen(pszRealm));
58 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
59 MD5Update(&Md5Ctx, (const unsigned char *)pszPassword, strlen(pszPassword));
60 MD5Final((unsigned char *)HA1, &Md5Ctx);
61 if (strcmp(pszAlg, "md5-sess") == 0) {
62 MD5Init(&Md5Ctx);
63 MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHLEN);
64 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
65 MD5Update(&Md5Ctx, (const unsigned char *)pszNonce, strlen(pszNonce));
66 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
67 MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
68 MD5Final((unsigned char *)HA1, &Md5Ctx);
69 }
70 CvtHex(HA1, SessionKey);
71}
72
73// calculate request-digest as SIP Digest spec RFC5090
74void DigestCalcResponse(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response)
75{
76 MD5_CTX Md5Ctx;
77 HASH HA2;
78 HASH RespHash;
79 HASHHEX HA2Hex;
80
81 // calculate H(A2)
82 MD5Init(&Md5Ctx);
83 MD5Update(&Md5Ctx, (const unsigned char *)pszMethod, strlen(pszMethod));
84 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
85 MD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, strlen(pszDigestUri));
86 if (strcmp(pszQop, "auth-int") == 0) {
87 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
88 MD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN);
89 }
90 MD5Final((unsigned char *)HA2, &Md5Ctx);
91 CvtHex(HA2, HA2Hex);
92
93 // calculate response
94 MD5Init(&Md5Ctx);
95 MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN);
96 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
97 MD5Update(&Md5Ctx,(const unsigned char *) pszNonce, strlen(pszNonce));
98 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
99 if (*pszQop) {
100 MD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount));
101 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
102 MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
103 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
104 MD5Update(&Md5Ctx, (const unsigned char *)pszQop, strlen(pszQop));
105 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
106 }
107 MD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN);
108 MD5Final((unsigned char *)RespHash, &Md5Ctx);
109 CvtHex(RespHash, Response);
110}
111// calculate Digest_response_Auth as per SIP Digest spec RFC5090
112void DigestCalcResponseAuth(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response)
113{
114 MD5_CTX Md5Ctx;
115 HASH HA2;
116 HASH RespHash;
117 HASHHEX HA2Hex;
118
119 // calculate H(A2)
120 MD5Init(&Md5Ctx);
121 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
122 MD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, strlen(pszDigestUri));
123 if (strcmp(pszQop, "auth-int") == 0) {
124 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
125 MD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN);
126 }
127 MD5Final((unsigned char *)HA2, &Md5Ctx);
128 CvtHex(HA2, HA2Hex);
129
130 // calculate response
131 MD5Init(&Md5Ctx);
132 MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN);
133 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
134 MD5Update(&Md5Ctx, (const unsigned char *)pszNonce, strlen(pszNonce));
135 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
136 if (*pszQop) {
137 MD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount));
138 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
139 MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
140 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
141 MD5Update(&Md5Ctx, (const unsigned char *)pszQop, strlen(pszQop));
142 MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
143 }
144 MD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN);
145 MD5Final((unsigned char *)RespHash, &Md5Ctx);
146 CvtHex(RespHash, Response);
147}
148
149
150
151
152
153static void MD5Transform(u32 buf[4], u32 const in[16]);
154
155
156
157
158/**
159 * md5_vector - MD5 hash for data vector
160 * @num_elem: Number of elements in the data vector
161 * @addr: Pointers to the data areas
162 * @len: Lengths of the data blocks
163 * @mac: Buffer for the hash
164 */
165void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
166{
167 MD5_CTX ctx;
168 size_t i;
169
170 MD5Init(&ctx);
171 for (i = 0; i < num_elem; i++)
172 MD5Update(&ctx, addr[i], len[i]);
173 MD5Final(mac, &ctx);
174}
175
176
177/* ===== start - public domain MD5 implementation ===== */
178/*
179 * This code implements the MD5 message-digest algorithm.
180 * The algorithm is due to Ron Rivest. This code was
181 * written by Colin Plumb in 1993, no copyright is claimed.
182 * This code is in the public domain; do with it what you wish.
183 *
184 * Equivalent code is available from RSA Data Security, Inc.
185 * This code has been tested against that, and is equivalent,
186 * except that you don't need to include two pages of legalese
187 * with every copy.
188 *
189 * To compute the message digest of a chunk of bytes, declare an
190 * MD5Context structure, pass it to MD5Init, call MD5Update as
191 * needed on buffers full of bytes, and then call MD5Final, which
192 * will fill a supplied 16-byte array with the digest.
193 */
194
195#ifndef WORDS_BIGENDIAN
196#define byteReverse(buf, len) /* Nothing */
197#else
198/*
199 * Note: this code is harmless on little-endian machines.
200 */
201static void byteReverse(unsigned char *buf, unsigned longs)
202{
203 u32 t;
204 do {
205 t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
206 ((unsigned) buf[1] << 8 | buf[0]);
207 *(u32 *) buf = t;
208 buf += 4;
209 } while (--longs);
210}
211#endif
212
213/*
214 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
215 * initialization constants.
216 */
217void MD5Init(struct MD5Context *ctx)
218{
219 ctx->buf[0] = 0x67452301;
220 ctx->buf[1] = 0xefcdab89;
221 ctx->buf[2] = 0x98badcfe;
222 ctx->buf[3] = 0x10325476;
223
224 ctx->bits[0] = 0;
225 ctx->bits[1] = 0;
226}
227
228/*
229 * Update context to reflect the concatenation of another buffer full
230 * of bytes.
231 */
232void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
233{
234 u32 t;
235
236 /* Update bitcount */
237
238 t = ctx->bits[0];
239 if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
240 ctx->bits[1]++; /* Carry from low to high */
241 ctx->bits[1] += len >> 29;
242
243 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
244
245 /* Handle any leading odd-sized chunks */
246
247 if (t) {
248 unsigned char *p = (unsigned char *) ctx->in + t;
249
250 t = 64 - t;
251 if (len < t) {
252 os_memcpy(p, buf, len);
253 return;
254 }
255 os_memcpy(p, buf, t);
256 byteReverse(ctx->in, 16);
257 MD5Transform(ctx->buf, (u32 *) ctx->in);
258 buf += t;
259 len -= t;
260 }
261 /* Process data in 64-byte chunks */
262
263 while (len >= 64) {
264 os_memcpy(ctx->in, buf, 64);
265 byteReverse(ctx->in, 16);
266 MD5Transform(ctx->buf, (u32 *) ctx->in);
267 buf += 64;
268 len -= 64;
269 }
270
271 /* Handle any remaining bytes of data. */
272
273 os_memcpy(ctx->in, buf, len);
274}
275
276/*
277 * Final wrapup - pad to 64-byte boundary with the bit pattern
278 * 1 0* (64-bit count of bits processed, MSB-first)
279 */
280void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
281{
282 unsigned count;
283 unsigned char *p;
284
285 /* Compute number of bytes mod 64 */
286 count = (ctx->bits[0] >> 3) & 0x3F;
287
288 /* Set the first char of padding to 0x80. This is safe since there is
289 always at least one byte free */
290 p = ctx->in + count;
291 *p++ = 0x80;
292
293 /* Bytes of padding needed to make 64 bytes */
294 count = 64 - 1 - count;
295
296 /* Pad out to 56 mod 64 */
297 if (count < 8) {
298 /* Two lots of padding: Pad the first block to 64 bytes */
299 os_memset(p, 0, count);
300 byteReverse(ctx->in, 16);
301 MD5Transform(ctx->buf, (u32 *) ctx->in);
302
303 /* Now fill the next block with 56 bytes */
304 os_memset(ctx->in, 0, 56);
305 } else {
306 /* Pad block to 56 bytes */
307 os_memset(p, 0, count - 8);
308 }
309 byteReverse(ctx->in, 14);
310
311 /* Append length in bits and transform */
312 ((u32 *) ctx->in)[14] = ctx->bits[0];
313 ((u32 *) ctx->in)[15] = ctx->bits[1];
314
315 MD5Transform(ctx->buf, (u32 *) ctx->in);
316 byteReverse((unsigned char *) ctx->buf, 4);
317 os_memcpy(digest, ctx->buf, 16);
318 os_memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
319}
320
321/* The four core functions - F1 is optimized somewhat */
322
323/* #define F1(x, y, z) (x & y | ~x & z) */
324#define F1(x, y, z) (z ^ (x & (y ^ z)))
325#define F2(x, y, z) F1(z, x, y)
326#define F3(x, y, z) (x ^ y ^ z)
327#define F4(x, y, z) (y ^ (x | ~z))
328
329/* This is the central step in the MD5 algorithm. */
330#define MD5STEP(f, w, x, y, z, data, s) \
331 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
332
333/*
334 * The core of the MD5 algorithm, this alters an existing MD5 hash to
335 * reflect the addition of 16 longwords of new data. MD5Update blocks
336 * the data and converts bytes into longwords for this routine.
337 */
338static void MD5Transform(u32 buf[4], u32 const in[16])
339{
340 register u32 a, b, c, d;
341
342 a = buf[0];
343 b = buf[1];
344 c = buf[2];
345 d = buf[3];
346
347 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
348 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
349 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
350 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
351 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
352 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
353 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
354 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
355 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
356 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
357 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
358 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
359 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
360 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
361 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
362 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
363
364 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
365 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
366 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
367 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
368 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
369 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
370 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
371 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
372 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
373 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
374 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
375 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
376 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
377 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
378 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
379 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
380
381 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
382 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
383 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
384 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
385 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
386 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
387 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
388 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
389 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
390 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
391 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
392 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
393 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
394 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
395 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
396 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
397
398 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
399 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
400 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
401 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
402 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
403 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
404 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
405 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
406 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
407 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
408 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
409 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
410 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
411 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
412 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
413 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
414
415 buf[0] += a;
416 buf[1] += b;
417 buf[2] += c;
418 buf[3] += d;
419}
420/* ===== end - public domain MD5 implementation ===== */
421