xref: /netbsd-src/external/apache2/mDNSResponder/dist/mDNSCore/DNSDigest.c (revision bbde328be4e75ea9ad02e9715ea13ca54b797ada)
1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16 
17     Change History (most recent first):
18 
19 Log: DNSDigest.c,v $
20 Revision 1.26  2008/10/10 23:21:51  mcguire
21 fixed typo in original MD5 source reference
22 
23 Revision 1.25  2007/12/17 23:48:29  cheshire
24 DNSDigest_SignMessage doesn't need to return a result -- it already updates the 'end' parameter
25 
26 Revision 1.24  2007/11/30 23:03:51  cheshire
27 Fixes for EFI: Use "mDNSPlatformMemCopy" instead of assuming existence of "memcpy"
28 
29 Revision 1.23  2007/09/21 21:12:36  cheshire
30 DNSDigest_SignMessage does not need separate "mDNSu16 *numAdditionals" parameter
31 
32 Revision 1.22  2007/04/22 06:02:02  cheshire
33 <rdar://problem/4615977> Query should immediately return failure when no server
34 
35 Revision 1.21  2007/03/22 18:31:48  cheshire
36 Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
37 
38 Revision 1.20  2006/12/22 20:59:49  cheshire
39 <rdar://problem/4742742> Read *all* DNS keys from keychain,
40  not just key for the system-wide default registration domain
41 
42 Revision 1.19  2006/12/21 00:06:07  cheshire
43 Don't need to do mDNSPlatformMemZero() -- mDNS_SetupResourceRecord() does it for us
44 
45 Revision 1.18  2006/12/19 22:41:21  cheshire
46 Fix compiler warnings
47 
48 Revision 1.17  2006/08/14 23:24:22  cheshire
49 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
50 
51 Revision 1.16  2006/07/05 23:05:15  cheshire
52 <rdar://problem/4472013> Add Private DNS server functionality to dnsextd
53 Add DNSDigest_VerifyMessage() function
54 
55 Revision 1.15  2006/06/20 04:12:30  cheshire
56 <rdar://problem/4490961> DNS Update broken
57 
58 Revision 1.14  2006/02/25 23:12:07  cheshire
59 <rdar://problem/4427969> Fix to avoid code generation warning/error on FreeBSD 7
60 
61 Revision 1.13  2004/12/16 20:12:59  cheshire
62 <rdar://problem/3324626> Cache memory management improvements
63 
64 Revision 1.12  2004/12/03 07:20:50  ksekar
65 <rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
66 
67 Revision 1.11  2004/12/02 01:10:27  cheshire
68 Fix to compile cleanly on 64-bit x86
69 
70 Revision 1.10  2004/11/01 20:36:04  ksekar
71 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
72 
73 Revision 1.9  2004/10/26 09:00:12  cheshire
74 Save a few bytes by creating HMAC_MD5_AlgName as a C string instead of a 256-byte object
75 
76 Revision 1.8  2004/09/17 01:08:48  cheshire
77 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
78   The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
79   declared in that file are ONLY appropriate to single-address-space embedded applications.
80   For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
81 
82 Revision 1.7  2004/08/15 18:36:38  cheshire
83 Don't use strcpy() and strlen() on "struct domainname" objects;
84 use AssignDomainName() and DomainNameLength() instead
85 (A "struct domainname" is a collection of packed pascal strings, not a C string.)
86 
87 Revision 1.6  2004/06/02 00:17:46  ksekar
88 Referenced original OpenSSL license headers in source file description.
89 
90 Revision 1.5  2004/05/20 18:37:37  cheshire
91 Fix compiler warnings
92 
93 Revision 1.4  2004/04/22 20:28:20  cheshire
94 Use existing facility of PutResourceRecordTTL() to update count field for us
95 
96 Revision 1.3  2004/04/22 03:05:28  cheshire
97 kDNSClass_ANY should be kDNSQClass_ANY
98 
99 Revision 1.2  2004/04/15 00:51:28  bradley
100 Minor tweaks for Windows and C++ builds. Added casts for signed/unsigned integers and 64-bit pointers.
101 Prefix some functions with mDNS to avoid conflicts. Disable benign warnings on Microsoft compilers.
102 
103 Revision 1.1  2004/04/14 23:09:28  ksekar
104 Support for TSIG signed dynamic updates.
105 
106 
107 
108 */
109 
110 
111 #ifdef __cplusplus
112 extern "C" {
113 #endif
114 
115 #include "mDNSEmbeddedAPI.h"
116 #include "DNSCommon.h"
117 
118 // Disable certain benign warnings with Microsoft compilers
119 #if(defined(_MSC_VER))
120 	// Disable "conditional expression is constant" warning for debug macros.
121 	// Otherwise, this generates warnings for the perfectly natural construct "while(1)"
122 	// If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
123 	#pragma warning(disable:4127)
124 #endif
125 
126 
127  // ***************************************************************************
128 #if COMPILER_LIKES_PRAGMA_MARK
129 #pragma mark - Byte Swapping Functions
130 #endif
131 
132 mDNSlocal mDNSu16 NToH16(mDNSu8 * bytes)
133 	{
134 	return (mDNSu16)((mDNSu16)bytes[0] << 8 | (mDNSu16)bytes[1]);
135 	}
136 
137 mDNSlocal mDNSu32 NToH32(mDNSu8 * bytes)
138 	{
139 	return (mDNSu32)((mDNSu32) bytes[0] << 24 | (mDNSu32) bytes[1] << 16 | (mDNSu32) bytes[2] << 8 | (mDNSu32)bytes[3]);
140 	}
141 
142  // ***************************************************************************
143 #if COMPILER_LIKES_PRAGMA_MARK
144 #pragma mark - MD5 Hash Functions
145 #endif
146 
147 
148 /* The source for the has is derived CommonCrypto files CommonDigest.h, md32_common.h, md5_locl.h, md5_locl.h, and openssl/md5.h.
149  * The following changes have been made to the original sources:
150  *    replaced CC_LONG w/ mDNSu32
151  *    replaced CC_MD5* with MD5*
152  *    replaced CC_LONG w/ mDNSu32, removed conditional #defines from md5.h
153  *    removed extern decls for MD5_Init/Update/Final from CommonDigest.h
154  *    removed APPLE_COMMON_DIGEST specific #defines from md5_locl.h
155  *
156  * Note: machine archetecure specific conditionals from the original sources are turned off, but are left in the code
157  * to aid in platform-specific optimizations and debugging.
158  * Sources originally distributed under the following license headers:
159  * CommonDigest.h - APSL
160  *
161  * md32_Common.h
162  * ====================================================================
163  * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
164  *
165  * Redistribution and use in source and binary forms, with or without
166  * modification, are permitted provided that the following conditions
167  * are met:
168  *
169  * 1. Redistributions of source code must retain the above copyright
170  *    notice, this list of conditions and the following disclaimer.
171  *
172  * 2. Redistributions in binary form must reproduce the above copyright
173  *    notice, this list of conditions and the following disclaimer in
174  *    the documentation and/or other materials provided with the
175  *    distribution.
176  *
177  * 3. All advertising materials mentioning features or use of this
178  *    software must display the following acknowledgment:
179  *    "This product includes software developed by the OpenSSL Project
180  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
181  *
182  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
183  *    endorse or promote products derived from this software without
184  *    prior written permission. For written permission, please contact
185  *    licensing@OpenSSL.org.
186  *
187  * 5. Products derived from this software may not be called "OpenSSL"
188  *    nor may "OpenSSL" appear in their names without prior written
189  *    permission of the OpenSSL Project.
190  *
191  * 6. Redistributions of any form whatsoever must retain the following
192  *    acknowledgment:
193  *    "This product includes software developed by the OpenSSL Project
194  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
195  *
196  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
197  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
198  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
199  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
200  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
201  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
202  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
203  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
204  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
205  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
206  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
207  * OF THE POSSIBILITY OF SUCH DAMAGE.
208  *
209  *
210  * md5_dgst.c, md5_locl.h
211  * ====================================================================
212  *
213  * This product includes cryptographic software written by Eric Young
214  * (eay@cryptsoft.com).  This product includes software written by Tim
215  * Hudson (tjh@cryptsoft.com).
216  *
217  * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
218  * All rights reserved.
219  *
220  * This package is an SSL implementation written
221  * by Eric Young (eay@cryptsoft.com).
222  * The implementation was written so as to conform with Netscapes SSL.
223  *
224  * This library is free for commercial and non-commercial use as long as
225  * the following conditions are aheared to.  The following conditions
226  * apply to all code found in this distribution, be it the RC4, RSA,
227  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
228  * included with this distribution is covered by the same copyright terms
229  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
230  *
231  * Copyright remains Eric Young's, and as such any Copyright notices in
232  * the code are not to be removed.
233  * If this package is used in a product, Eric Young should be given attribution
234  * as the author of the parts of the library used.
235  * This can be in the form of a textual message at program startup or
236  * in documentation (online or textual) provided with the package.
237  *
238  * Redistribution and use in source and binary forms, with or without
239  * modification, are permitted provided that the following conditions
240  * are met:
241  * 1. Redistributions of source code must retain the copyright
242  *    notice, this list of conditions and the following disclaimer.
243  * 2. Redistributions in binary form must reproduce the above copyright
244  *    notice, this list of conditions and the following disclaimer in the
245  *    documentation and/or other materials provided with the distribution.
246  * 3. All advertising materials mentioning features or use of this software
247  *    must display the following acknowledgement:
248  *    "This product includes cryptographic software written by
249  *     Eric Young (eay@cryptsoft.com)"
250  *    The word 'cryptographic' can be left out if the rouines from the library
251  *    being used are not cryptographic related :-).
252  * 4. If you include any Windows specific code (or a derivative thereof) from
253  *    the apps directory (application code) you must include an acknowledgement:
254  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
255  *
256  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
257  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
258  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
259  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
260  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
262  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
263  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
264  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
265  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
266  * SUCH DAMAGE.
267  *
268  * The licence and distribution terms for any publically available version or
269  * derivative of this code cannot be changed.  i.e. this code cannot simply be
270  * copied and put under another distribution licence
271  * [including the GNU Public Licence.]
272  *
273  */
274 
275 //from CommonDigest.h
276 
277 #define MD5_DIGEST_LENGTH	16			/* digest length in bytes */
278 #define MD5_BLOCK_BYTES		64			/* block size in bytes */
279 #define MD5_BLOCK_LONG       (MD5_BLOCK_BYTES / sizeof(mDNSu32))
280 
281 typedef struct MD5state_st
282 {
283 	mDNSu32 A,B,C,D;
284 	mDNSu32 Nl,Nh;
285 	mDNSu32 data[MD5_BLOCK_LONG];
286 	int num;
287 } MD5_CTX;
288 
289 
290 // from openssl/md5.h
291 
292 #define MD5_CBLOCK	64
293 #define MD5_LBLOCK	(MD5_CBLOCK/4)
294 #define MD5_DIGEST_LENGTH 16
295 
296 int MD5_Init(MD5_CTX *c);
297 int MD5_Update(MD5_CTX *c, const void *data, unsigned long len);
298 int MD5_Final(unsigned char *md, MD5_CTX *c);
299 void MD5_Transform(MD5_CTX *c, const unsigned char *b);
300 
301 // From md5_locl.h
302 
303 #ifndef MD5_LONG_LOG2
304 #define MD5_LONG_LOG2 2 /* default to 32 bits */
305 #endif
306 
307 #ifdef MD5_ASM
308 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
309 #  define md5_block_host_order md5_block_asm_host_order
310 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
311    void md5_block_asm_data_order_aligned (MD5_CTX *c, const mDNSu32 *p,int num);
312 #  define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned
313 # endif
314 #endif
315 
316 void md5_block_host_order (MD5_CTX *c, const void *p,int num);
317 void md5_block_data_order (MD5_CTX *c, const void *p,int num);
318 
319 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
320 /*
321  * *_block_host_order is expected to handle aligned data while
322  * *_block_data_order - unaligned. As algorithm and host (x86)
323  * are in this case of the same "endianness" these two are
324  * otherwise indistinguishable. But normally you don't want to
325  * call the same function because unaligned access in places
326  * where alignment is expected is usually a "Bad Thing". Indeed,
327  * on RISCs you get punished with BUS ERROR signal or *severe*
328  * performance degradation. Intel CPUs are in turn perfectly
329  * capable of loading unaligned data without such drastic side
330  * effect. Yes, they say it's slower than aligned load, but no
331  * exception is generated and therefore performance degradation
332  * is *incomparable* with RISCs. What we should weight here is
333  * costs of unaligned access against costs of aligning data.
334  * According to my measurements allowing unaligned access results
335  * in ~9% performance improvement on Pentium II operating at
336  * 266MHz. I won't be surprised if the difference will be higher
337  * on faster systems:-)
338  *
339  *				<appro@fy.chalmers.se>
340  */
341 #define md5_block_data_order md5_block_host_order
342 #endif
343 
344 #define DATA_ORDER_IS_LITTLE_ENDIAN
345 
346 #define HASH_LONG		mDNSu32
347 #define HASH_LONG_LOG2	MD5_LONG_LOG2
348 #define HASH_CTX		MD5_CTX
349 #define HASH_CBLOCK		MD5_CBLOCK
350 #define HASH_LBLOCK		MD5_LBLOCK
351 
352 #define HASH_UPDATE		MD5_Update
353 #define HASH_TRANSFORM	MD5_Transform
354 #define HASH_FINAL		MD5_Final
355 
356 #define	HASH_MAKE_STRING(c,s)	do {	\
357 	unsigned long ll;		\
358 	ll=(c)->A; HOST_l2c(ll,(s));	\
359 	ll=(c)->B; HOST_l2c(ll,(s));	\
360 	ll=(c)->C; HOST_l2c(ll,(s));	\
361 	ll=(c)->D; HOST_l2c(ll,(s));	\
362 	} while (0)
363 #define HASH_BLOCK_HOST_ORDER	md5_block_host_order
364 #if !defined(L_ENDIAN) || defined(md5_block_data_order)
365 #define	HASH_BLOCK_DATA_ORDER	md5_block_data_order
366 /*
367  * Little-endians (Intel and Alpha) feel better without this.
368  * It looks like memcpy does better job than generic
369  * md5_block_data_order on copying-n-aligning input data.
370  * But frankly speaking I didn't expect such result on Alpha.
371  * On the other hand I've got this with egcs-1.0.2 and if
372  * program is compiled with another (better?) compiler it
373  * might turn out other way around.
374  *
375  *				<appro@fy.chalmers.se>
376  */
377 #endif
378 
379 
380 // from md32_common.h
381 
382 /*
383  * This is a generic 32 bit "collector" for message digest algorithms.
384  * Whenever needed it collects input character stream into chunks of
385  * 32 bit values and invokes a block function that performs actual hash
386  * calculations.
387  *
388  * Porting guide.
389  *
390  * Obligatory macros:
391  *
392  * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
393  *	this macro defines byte order of input stream.
394  * HASH_CBLOCK
395  *	size of a unit chunk HASH_BLOCK operates on.
396  * HASH_LONG
397  *	has to be at lest 32 bit wide, if it's wider, then
398  *	HASH_LONG_LOG2 *has to* be defined along
399  * HASH_CTX
400  *	context structure that at least contains following
401  *	members:
402  *		typedef struct {
403  *			...
404  *			HASH_LONG	Nl,Nh;
405  *			HASH_LONG	data[HASH_LBLOCK];
406  *			int		num;
407  *			...
408  *			} HASH_CTX;
409  * HASH_UPDATE
410  *	name of "Update" function, implemented here.
411  * HASH_TRANSFORM
412  *	name of "Transform" function, implemented here.
413  * HASH_FINAL
414  *	name of "Final" function, implemented here.
415  * HASH_BLOCK_HOST_ORDER
416  *	name of "block" function treating *aligned* input message
417  *	in host byte order, implemented externally.
418  * HASH_BLOCK_DATA_ORDER
419  *	name of "block" function treating *unaligned* input message
420  *	in original (data) byte order, implemented externally (it
421  *	actually is optional if data and host are of the same
422  *	"endianess").
423  * HASH_MAKE_STRING
424  *	macro convering context variables to an ASCII hash string.
425  *
426  * Optional macros:
427  *
428  * B_ENDIAN or L_ENDIAN
429  *	defines host byte-order.
430  * HASH_LONG_LOG2
431  *	defaults to 2 if not states otherwise.
432  * HASH_LBLOCK
433  *	assumed to be HASH_CBLOCK/4 if not stated otherwise.
434  * HASH_BLOCK_DATA_ORDER_ALIGNED
435  *	alternative "block" function capable of treating
436  *	aligned input message in original (data) order,
437  *	implemented externally.
438  *
439  * MD5 example:
440  *
441  *	#define DATA_ORDER_IS_LITTLE_ENDIAN
442  *
443  *	#define HASH_LONG		mDNSu32
444  *	#define HASH_LONG_LOG2	mDNSu32_LOG2
445  *	#define HASH_CTX		MD5_CTX
446  *	#define HASH_CBLOCK		MD5_CBLOCK
447  *	#define HASH_LBLOCK		MD5_LBLOCK
448  *	#define HASH_UPDATE		MD5_Update
449  *	#define HASH_TRANSFORM		MD5_Transform
450  *	#define HASH_FINAL		MD5_Final
451  *	#define HASH_BLOCK_HOST_ORDER	md5_block_host_order
452  *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order
453  *
454  *					<appro@fy.chalmers.se>
455  */
456 
457 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
458 #error "DATA_ORDER must be defined!"
459 #endif
460 
461 #ifndef HASH_CBLOCK
462 #error "HASH_CBLOCK must be defined!"
463 #endif
464 #ifndef HASH_LONG
465 #error "HASH_LONG must be defined!"
466 #endif
467 #ifndef HASH_CTX
468 #error "HASH_CTX must be defined!"
469 #endif
470 
471 #ifndef HASH_UPDATE
472 #error "HASH_UPDATE must be defined!"
473 #endif
474 #ifndef HASH_TRANSFORM
475 #error "HASH_TRANSFORM must be defined!"
476 #endif
477 #ifndef HASH_FINAL
478 #error "HASH_FINAL must be defined!"
479 #endif
480 
481 #ifndef HASH_BLOCK_HOST_ORDER
482 #error "HASH_BLOCK_HOST_ORDER must be defined!"
483 #endif
484 
485 #if 0
486 /*
487  * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
488  * isn't defined.
489  */
490 #ifndef HASH_BLOCK_DATA_ORDER
491 #error "HASH_BLOCK_DATA_ORDER must be defined!"
492 #endif
493 #endif
494 
495 #ifndef HASH_LBLOCK
496 #define HASH_LBLOCK	(HASH_CBLOCK/4)
497 #endif
498 
499 #ifndef HASH_LONG_LOG2
500 #define HASH_LONG_LOG2	2
501 #endif
502 
503 /*
504  * Engage compiler specific rotate intrinsic function if available.
505  */
506 #undef ROTATE
507 #ifndef PEDANTIC
508 # if 0 /* defined(_MSC_VER) */
509 #  define ROTATE(a,n)	_lrotl(a,n)
510 # elif defined(__MWERKS__)
511 #  if defined(__POWERPC__)
512 #   define ROTATE(a,n)	(unsigned MD32_REG_T)__rlwinm((int)a,n,0,31)
513 #  elif defined(__MC68K__)
514     /* Motorola specific tweak. <appro@fy.chalmers.se> */
515 #   define ROTATE(a,n)	(n<24 ? __rol(a,n) : __ror(a,32-n))
516 #  else
517 #   define ROTATE(a,n)	__rol(a,n)
518 #  endif
519 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
520   /*
521    * Some GNU C inline assembler templates. Note that these are
522    * rotates by *constant* number of bits! But that's exactly
523    * what we need here...
524    *
525    * 					<appro@fy.chalmers.se>
526    */
527 #  if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
528 #   define ROTATE(a,n)	({ register unsigned int ret;	\
529 				asm (			\
530 				"roll %1,%0"		\
531 				: "=r"(ret)		\
532 				: "I"(n), "0"(a)	\
533 				: "cc");		\
534 			   ret;				\
535 			})
536 #  elif defined(__powerpc) || defined(__ppc)
537 #   define ROTATE(a,n)	({ register unsigned int ret;	\
538 				asm (			\
539 				"rlwinm %0,%1,%2,0,31"	\
540 				: "=r"(ret)		\
541 				: "r"(a), "I"(n));	\
542 			   ret;				\
543 			})
544 #  endif
545 # endif
546 
547 /*
548  * Engage compiler specific "fetch in reverse byte order"
549  * intrinsic function if available.
550  */
551 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
552   /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
553 #  if (defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)) && !defined(I386_ONLY)
554 #   define BE_FETCH32(a)	({ register unsigned int l=(a);\
555 				asm (			\
556 				"bswapl %0"		\
557 				: "=r"(l) : "0"(l));	\
558 			  l;				\
559 			})
560 #  elif defined(__powerpc)
561 #   define LE_FETCH32(a)	({ register unsigned int l;	\
562 				asm (			\
563 				"lwbrx %0,0,%1"		\
564 				: "=r"(l)		\
565 				: "r"(a));		\
566 			   l;				\
567 			})
568 
569 #  elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
570 #  define LE_FETCH32(a)	({ register unsigned int l;		\
571 				asm (				\
572 				"lda [%1]#ASI_PRIMARY_LITTLE,%0"\
573 				: "=r"(l)			\
574 				: "r"(a));			\
575 			   l;					\
576 			})
577 #  endif
578 # endif
579 #endif /* PEDANTIC */
580 
581 #if HASH_LONG_LOG2==2	/* Engage only if sizeof(HASH_LONG)== 4 */
582 /* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
583 #ifdef ROTATE
584 /* 5 instructions with rotate instruction, else 9 */
585 #define REVERSE_FETCH32(a,l)	(					\
586 		l=*(const HASH_LONG *)(a),				\
587 		((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24)))	\
588 				)
589 #else
590 /* 6 instructions with rotate instruction, else 8 */
591 #define REVERSE_FETCH32(a,l)	(				\
592 		l=*(const HASH_LONG *)(a),			\
593 		l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)),	\
594 		ROTATE(l,16)					\
595 				)
596 /*
597  * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
598  * It's rewritten as above for two reasons:
599  *	- RISCs aren't good at long constants and have to explicitely
600  *	  compose 'em with several (well, usually 2) instructions in a
601  *	  register before performing the actual operation and (as you
602  *	  already realized:-) having same constant should inspire the
603  *	  compiler to permanently allocate the only register for it;
604  *	- most modern CPUs have two ALUs, but usually only one has
605  *	  circuitry for shifts:-( this minor tweak inspires compiler
606  *	  to schedule shift instructions in a better way...
607  *
608  *				<appro@fy.chalmers.se>
609  */
610 #endif
611 #endif
612 
613 #ifndef ROTATE
614 #define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
615 #endif
616 
617 /*
618  * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
619  * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
620  * and host are of the same "endianess". It's possible to mask
621  * this with blank #define HASH_BLOCK_DATA_ORDER though...
622  *
623  *				<appro@fy.chalmers.se>
624  */
625 #if defined(B_ENDIAN)
626 #  if defined(DATA_ORDER_IS_BIG_ENDIAN)
627 #    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
628 #      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
629 #    endif
630 #  elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
631 #    ifndef HOST_FETCH32
632 #      ifdef LE_FETCH32
633 #        define HOST_FETCH32(p,l)	LE_FETCH32(p)
634 #      elif defined(REVERSE_FETCH32)
635 #        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l)
636 #      endif
637 #    endif
638 #  endif
639 #elif defined(L_ENDIAN)
640 #  if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
641 #    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
642 #      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
643 #    endif
644 #  elif defined(DATA_ORDER_IS_BIG_ENDIAN)
645 #    ifndef HOST_FETCH32
646 #      ifdef BE_FETCH32
647 #        define HOST_FETCH32(p,l)	BE_FETCH32(p)
648 #      elif defined(REVERSE_FETCH32)
649 #        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l)
650 #      endif
651 #    endif
652 #  endif
653 #endif
654 
655 #if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
656 #ifndef HASH_BLOCK_DATA_ORDER
657 #error "HASH_BLOCK_DATA_ORDER must be defined!"
658 #endif
659 #endif
660 
661 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
662 
663 #define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))<<24),		\
664 			 l|=(((unsigned long)(*((c)++)))<<16),		\
665 			 l|=(((unsigned long)(*((c)++)))<< 8),		\
666 			 l|=(((unsigned long)(*((c)++)))    ),		\
667 			 l)
668 #define HOST_p_c2l(c,l,n)	{					\
669 			switch (n) {					\
670 			case 0: l =((unsigned long)(*((c)++)))<<24;	\
671 			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
672 			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
673 			case 3: l|=((unsigned long)(*((c)++)));		\
674 				} }
675 #define HOST_p_c2l_p(c,l,sc,len) {					\
676 			switch (sc) {					\
677 			case 0: l =((unsigned long)(*((c)++)))<<24;	\
678 				if (--len == 0) break;			\
679 			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
680 				if (--len == 0) break;			\
681 			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
682 				} }
683 /* NOTE the pointer is not incremented at the end of this */
684 #define HOST_c2l_p(c,l,n)	{					\
685 			l=0; (c)+=n;					\
686 			switch (n) {					\
687 			case 3: l =((unsigned long)(*(--(c))))<< 8;	\
688 			case 2: l|=((unsigned long)(*(--(c))))<<16;	\
689 			case 1: l|=((unsigned long)(*(--(c))))<<24;	\
690 				} }
691 #define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff),	\
692 			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
693 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
694 			 *((c)++)=(unsigned char)(((l)    )&0xff),	\
695 			 l)
696 
697 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
698 
699 #define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))    ),		\
700 			 l|=(((unsigned long)(*((c)++)))<< 8),		\
701 			 l|=(((unsigned long)(*((c)++)))<<16),		\
702 			 l|=(((unsigned long)(*((c)++)))<<24),		\
703 			 l)
704 #define HOST_p_c2l(c,l,n)	{					\
705 			switch (n) {					\
706 			case 0: l =((unsigned long)(*((c)++)));		\
707 			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
708 			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
709 			case 3: l|=((unsigned long)(*((c)++)))<<24;	\
710 				} }
711 #define HOST_p_c2l_p(c,l,sc,len) {					\
712 			switch (sc) {					\
713 			case 0: l =((unsigned long)(*((c)++)));		\
714 				if (--len == 0) break;			\
715 			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
716 				if (--len == 0) break;			\
717 			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
718 				} }
719 /* NOTE the pointer is not incremented at the end of this */
720 #define HOST_c2l_p(c,l,n)	{					\
721 			l=0; (c)+=n;					\
722 			switch (n) {					\
723 			case 3: l =((unsigned long)(*(--(c))))<<16;	\
724 			case 2: l|=((unsigned long)(*(--(c))))<< 8;	\
725 			case 1: l|=((unsigned long)(*(--(c))));		\
726 				} }
727 #define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff),	\
728 			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
729 			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
730 			 *((c)++)=(unsigned char)(((l)>>24)&0xff),	\
731 			 l)
732 
733 #endif
734 
735 /*
736  * Time for some action:-)
737  */
738 
739 int HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len)
740 	{
741 	const unsigned char *data=(const unsigned char *)data_;
742 	register HASH_LONG * p;
743 	register unsigned long l;
744 	int sw,sc,ew,ec;
745 
746 	if (len==0) return 1;
747 
748 	l=(c->Nl+(len<<3))&0xffffffffL;
749 	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
750 	 * Wei Dai <weidai@eskimo.com> for pointing it out. */
751 	if (l < c->Nl) /* overflow */
752 		c->Nh++;
753 	c->Nh+=(len>>29);
754 	c->Nl=l;
755 
756 	if (c->num != 0)
757 		{
758 		p=c->data;
759 		sw=c->num>>2;
760 		sc=c->num&0x03;
761 
762 		if ((c->num+len) >= HASH_CBLOCK)
763 			{
764 			l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
765 			for (; sw<HASH_LBLOCK; sw++)
766 				{
767 				HOST_c2l(data,l); p[sw]=l;
768 				}
769 			HASH_BLOCK_HOST_ORDER (c,p,1);
770 			len-=(HASH_CBLOCK-c->num);
771 			c->num=0;
772 			/* drop through and do the rest */
773 			}
774 		else
775 			{
776 			c->num+=len;
777 			if ((sc+len) < 4) /* ugly, add char's to a word */
778 				{
779 				l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
780 				}
781 			else
782 				{
783 				ew=(c->num>>2);
784 				ec=(c->num&0x03);
785 				if (sc)
786 					l=p[sw];
787 				HOST_p_c2l(data,l,sc);
788 				p[sw++]=l;
789 				for (; sw < ew; sw++)
790 					{
791 					HOST_c2l(data,l); p[sw]=l;
792 					}
793 				if (ec)
794 					{
795 					HOST_c2l_p(data,l,ec); p[sw]=l;
796 					}
797 				}
798 			return 1;
799 			}
800 		}
801 
802 	sw=(int)(len/HASH_CBLOCK);
803 	if (sw > 0)
804 		{
805 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
806 		/*
807 		 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
808 		 * only if sizeof(HASH_LONG)==4.
809 		 */
810 		if ((((unsigned long)data)%4) == 0)
811 			{
812 			/* data is properly aligned so that we can cast it: */
813 			HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw);
814 			sw*=HASH_CBLOCK;
815 			data+=sw;
816 			len-=sw;
817 			}
818 		else
819 #if !defined(HASH_BLOCK_DATA_ORDER)
820 			while (sw--)
821 				{
822 				mDNSPlatformMemCopy(p=c->data,data,HASH_CBLOCK);
823 				HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
824 				data+=HASH_CBLOCK;
825 				len-=HASH_CBLOCK;
826 				}
827 #endif
828 #endif
829 #if defined(HASH_BLOCK_DATA_ORDER)
830 			{
831 			HASH_BLOCK_DATA_ORDER(c,data,sw);
832 			sw*=HASH_CBLOCK;
833 			data+=sw;
834 			len-=sw;
835 			}
836 #endif
837 		}
838 
839 	if (len!=0)
840 		{
841 		p = c->data;
842 		c->num = (int)len;
843 		ew=(int)(len>>2);	/* words to copy */
844 		ec=(int)(len&0x03);
845 		for (; ew; ew--,p++)
846 			{
847 			HOST_c2l(data,l); *p=l;
848 			}
849 		HOST_c2l_p(data,l,ec);
850 		*p=l;
851 		}
852 	return 1;
853 	}
854 
855 
856 void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
857 	{
858 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
859 	if ((((unsigned long)data)%4) == 0)
860 		/* data is properly aligned so that we can cast it: */
861 		HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1);
862 	else
863 #if !defined(HASH_BLOCK_DATA_ORDER)
864 		{
865 		mDNSPlatformMemCopy(c->data,data,HASH_CBLOCK);
866 		HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
867 		}
868 #endif
869 #endif
870 #if defined(HASH_BLOCK_DATA_ORDER)
871 	HASH_BLOCK_DATA_ORDER (c,data,1);
872 #endif
873 	}
874 
875 
876 int HASH_FINAL (unsigned char *md, HASH_CTX *c)
877 	{
878 	register HASH_LONG *p;
879 	register unsigned long l;
880 	register int i,j;
881 	static const unsigned char end[4]={0x80,0x00,0x00,0x00};
882 	const unsigned char *cp=end;
883 
884 	/* c->num should definitly have room for at least one more byte. */
885 	p=c->data;
886 	i=c->num>>2;
887 	j=c->num&0x03;
888 
889 #if 0
890 	/* purify often complains about the following line as an
891 	 * Uninitialized Memory Read.  While this can be true, the
892 	 * following p_c2l macro will reset l when that case is true.
893 	 * This is because j&0x03 contains the number of 'valid' bytes
894 	 * already in p[i].  If and only if j&0x03 == 0, the UMR will
895 	 * occur but this is also the only time p_c2l will do
896 	 * l= *(cp++) instead of l|= *(cp++)
897 	 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
898 	 * 'potential bug' */
899 #ifdef PURIFY
900 	if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */
901 #endif
902 	l=p[i];
903 #else
904 	l = (j==0) ? 0 : p[i];
905 #endif
906 	HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */
907 
908 	if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */
909 		{
910 		if (i<HASH_LBLOCK) p[i]=0;
911 		HASH_BLOCK_HOST_ORDER (c,p,1);
912 		i=0;
913 		}
914 	for (; i<(HASH_LBLOCK-2); i++)
915 		p[i]=0;
916 
917 #if   defined(DATA_ORDER_IS_BIG_ENDIAN)
918 	p[HASH_LBLOCK-2]=c->Nh;
919 	p[HASH_LBLOCK-1]=c->Nl;
920 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
921 	p[HASH_LBLOCK-2]=c->Nl;
922 	p[HASH_LBLOCK-1]=c->Nh;
923 #endif
924 	HASH_BLOCK_HOST_ORDER (c,p,1);
925 
926 #ifndef HASH_MAKE_STRING
927 #error "HASH_MAKE_STRING must be defined!"
928 #else
929 	HASH_MAKE_STRING(c,md);
930 #endif
931 
932 	c->num=0;
933 	/* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
934 	 * but I'm not worried :-)
935 	OPENSSL_cleanse((void *)c,sizeof(HASH_CTX));
936 	 */
937 	return 1;
938 	}
939 
940 #ifndef MD32_REG_T
941 #define MD32_REG_T long
942 /*
943  * This comment was originaly written for MD5, which is why it
944  * discusses A-D. But it basically applies to all 32-bit digests,
945  * which is why it was moved to common header file.
946  *
947  * In case you wonder why A-D are declared as long and not
948  * as mDNSu32. Doing so results in slight performance
949  * boost on LP64 architectures. The catch is we don't
950  * really care if 32 MSBs of a 64-bit register get polluted
951  * with eventual overflows as we *save* only 32 LSBs in
952  * *either* case. Now declaring 'em long excuses the compiler
953  * from keeping 32 MSBs zeroed resulting in 13% performance
954  * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
955  * Well, to be honest it should say that this *prevents*
956  * performance degradation.
957  *				<appro@fy.chalmers.se>
958  * Apparently there're LP64 compilers that generate better
959  * code if A-D are declared int. Most notably GCC-x86_64
960  * generates better code.
961  *				<appro@fy.chalmers.se>
962  */
963 #endif
964 
965 
966 // from md5_locl.h (continued)
967 
968 /*
969 #define	F(x,y,z)	(((x) & (y))  |  ((~(x)) & (z)))
970 #define	G(x,y,z)	(((x) & (z))  |  ((y) & (~(z))))
971 */
972 
973 /* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
974  * simplified to the code below.  Wei attributes these optimizations
975  * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
976  */
977 #define	F(b,c,d)	((((c) ^ (d)) & (b)) ^ (d))
978 #define	G(b,c,d)	((((b) ^ (c)) & (d)) ^ (c))
979 #define	H(b,c,d)	((b) ^ (c) ^ (d))
980 #define	I(b,c,d)	(((~(d)) | (b)) ^ (c))
981 
982 #define R0(a,b,c,d,k,s,t) { \
983 	a+=((k)+(t)+F((b),(c),(d))); \
984 	a=ROTATE(a,s); \
985 	a+=b; };\
986 
987 #define R1(a,b,c,d,k,s,t) { \
988 	a+=((k)+(t)+G((b),(c),(d))); \
989 	a=ROTATE(a,s); \
990 	a+=b; };
991 
992 #define R2(a,b,c,d,k,s,t) { \
993 	a+=((k)+(t)+H((b),(c),(d))); \
994 	a=ROTATE(a,s); \
995 	a+=b; };
996 
997 #define R3(a,b,c,d,k,s,t) { \
998 	a+=((k)+(t)+I((b),(c),(d))); \
999 	a=ROTATE(a,s); \
1000 	a+=b; };
1001 
1002 // from md5_dgst.c
1003 
1004 
1005 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
1006  */
1007 
1008 #define INIT_DATA_A (unsigned long)0x67452301L
1009 #define INIT_DATA_B (unsigned long)0xefcdab89L
1010 #define INIT_DATA_C (unsigned long)0x98badcfeL
1011 #define INIT_DATA_D (unsigned long)0x10325476L
1012 
1013 int MD5_Init(MD5_CTX *c)
1014 	{
1015 	c->A=INIT_DATA_A;
1016 	c->B=INIT_DATA_B;
1017 	c->C=INIT_DATA_C;
1018 	c->D=INIT_DATA_D;
1019 	c->Nl=0;
1020 	c->Nh=0;
1021 	c->num=0;
1022 	return 1;
1023 	}
1024 
1025 #ifndef md5_block_host_order
1026 void md5_block_host_order (MD5_CTX *c, const void *data, int num)
1027 	{
1028 	const mDNSu32 *X=(const mDNSu32 *)data;
1029 	register unsigned MD32_REG_T A,B,C,D;
1030 
1031 	A=c->A;
1032 	B=c->B;
1033 	C=c->C;
1034 	D=c->D;
1035 
1036 	for (;num--;X+=HASH_LBLOCK)
1037 		{
1038 	/* Round 0 */
1039 	R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
1040 	R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
1041 	R0(C,D,A,B,X[ 2],17,0x242070dbL);
1042 	R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
1043 	R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
1044 	R0(D,A,B,C,X[ 5],12,0x4787c62aL);
1045 	R0(C,D,A,B,X[ 6],17,0xa8304613L);
1046 	R0(B,C,D,A,X[ 7],22,0xfd469501L);
1047 	R0(A,B,C,D,X[ 8], 7,0x698098d8L);
1048 	R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
1049 	R0(C,D,A,B,X[10],17,0xffff5bb1L);
1050 	R0(B,C,D,A,X[11],22,0x895cd7beL);
1051 	R0(A,B,C,D,X[12], 7,0x6b901122L);
1052 	R0(D,A,B,C,X[13],12,0xfd987193L);
1053 	R0(C,D,A,B,X[14],17,0xa679438eL);
1054 	R0(B,C,D,A,X[15],22,0x49b40821L);
1055 	/* Round 1 */
1056 	R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
1057 	R1(D,A,B,C,X[ 6], 9,0xc040b340L);
1058 	R1(C,D,A,B,X[11],14,0x265e5a51L);
1059 	R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
1060 	R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
1061 	R1(D,A,B,C,X[10], 9,0x02441453L);
1062 	R1(C,D,A,B,X[15],14,0xd8a1e681L);
1063 	R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
1064 	R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
1065 	R1(D,A,B,C,X[14], 9,0xc33707d6L);
1066 	R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
1067 	R1(B,C,D,A,X[ 8],20,0x455a14edL);
1068 	R1(A,B,C,D,X[13], 5,0xa9e3e905L);
1069 	R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
1070 	R1(C,D,A,B,X[ 7],14,0x676f02d9L);
1071 	R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
1072 	/* Round 2 */
1073 	R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
1074 	R2(D,A,B,C,X[ 8],11,0x8771f681L);
1075 	R2(C,D,A,B,X[11],16,0x6d9d6122L);
1076 	R2(B,C,D,A,X[14],23,0xfde5380cL);
1077 	R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
1078 	R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
1079 	R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
1080 	R2(B,C,D,A,X[10],23,0xbebfbc70L);
1081 	R2(A,B,C,D,X[13], 4,0x289b7ec6L);
1082 	R2(D,A,B,C,X[ 0],11,0xeaa127faL);
1083 	R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
1084 	R2(B,C,D,A,X[ 6],23,0x04881d05L);
1085 	R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
1086 	R2(D,A,B,C,X[12],11,0xe6db99e5L);
1087 	R2(C,D,A,B,X[15],16,0x1fa27cf8L);
1088 	R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
1089 	/* Round 3 */
1090 	R3(A,B,C,D,X[ 0], 6,0xf4292244L);
1091 	R3(D,A,B,C,X[ 7],10,0x432aff97L);
1092 	R3(C,D,A,B,X[14],15,0xab9423a7L);
1093 	R3(B,C,D,A,X[ 5],21,0xfc93a039L);
1094 	R3(A,B,C,D,X[12], 6,0x655b59c3L);
1095 	R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
1096 	R3(C,D,A,B,X[10],15,0xffeff47dL);
1097 	R3(B,C,D,A,X[ 1],21,0x85845dd1L);
1098 	R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
1099 	R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
1100 	R3(C,D,A,B,X[ 6],15,0xa3014314L);
1101 	R3(B,C,D,A,X[13],21,0x4e0811a1L);
1102 	R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
1103 	R3(D,A,B,C,X[11],10,0xbd3af235L);
1104 	R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
1105 	R3(B,C,D,A,X[ 9],21,0xeb86d391L);
1106 
1107 	A = c->A += A;
1108 	B = c->B += B;
1109 	C = c->C += C;
1110 	D = c->D += D;
1111 		}
1112 	}
1113 #endif
1114 
1115 #ifndef md5_block_data_order
1116 #ifdef X
1117 #undef X
1118 #endif
1119 void md5_block_data_order (MD5_CTX *c, const void *data_, int num)
1120 	{
1121 	const unsigned char *data=data_;
1122 	register unsigned MD32_REG_T A,B,C,D,l;
1123 #ifndef MD32_XARRAY
1124 	/* See comment in crypto/sha/sha_locl.h for details. */
1125 	unsigned MD32_REG_T	XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
1126 				XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
1127 # define X(i)	XX##i
1128 #else
1129 	mDNSu32 XX[MD5_LBLOCK];
1130 # define X(i)	XX[i]
1131 #endif
1132 
1133 	A=c->A;
1134 	B=c->B;
1135 	C=c->C;
1136 	D=c->D;
1137 
1138 	for (;num--;)
1139 		{
1140 	HOST_c2l(data,l); X( 0)=l;		HOST_c2l(data,l); X( 1)=l;
1141 	/* Round 0 */
1142 	R0(A,B,C,D,X( 0), 7,0xd76aa478L);	HOST_c2l(data,l); X( 2)=l;
1143 	R0(D,A,B,C,X( 1),12,0xe8c7b756L);	HOST_c2l(data,l); X( 3)=l;
1144 	R0(C,D,A,B,X( 2),17,0x242070dbL);	HOST_c2l(data,l); X( 4)=l;
1145 	R0(B,C,D,A,X( 3),22,0xc1bdceeeL);	HOST_c2l(data,l); X( 5)=l;
1146 	R0(A,B,C,D,X( 4), 7,0xf57c0fafL);	HOST_c2l(data,l); X( 6)=l;
1147 	R0(D,A,B,C,X( 5),12,0x4787c62aL);	HOST_c2l(data,l); X( 7)=l;
1148 	R0(C,D,A,B,X( 6),17,0xa8304613L);	HOST_c2l(data,l); X( 8)=l;
1149 	R0(B,C,D,A,X( 7),22,0xfd469501L);	HOST_c2l(data,l); X( 9)=l;
1150 	R0(A,B,C,D,X( 8), 7,0x698098d8L);	HOST_c2l(data,l); X(10)=l;
1151 	R0(D,A,B,C,X( 9),12,0x8b44f7afL);	HOST_c2l(data,l); X(11)=l;
1152 	R0(C,D,A,B,X(10),17,0xffff5bb1L);	HOST_c2l(data,l); X(12)=l;
1153 	R0(B,C,D,A,X(11),22,0x895cd7beL);	HOST_c2l(data,l); X(13)=l;
1154 	R0(A,B,C,D,X(12), 7,0x6b901122L);	HOST_c2l(data,l); X(14)=l;
1155 	R0(D,A,B,C,X(13),12,0xfd987193L);	HOST_c2l(data,l); X(15)=l;
1156 	R0(C,D,A,B,X(14),17,0xa679438eL);
1157 	R0(B,C,D,A,X(15),22,0x49b40821L);
1158 	/* Round 1 */
1159 	R1(A,B,C,D,X( 1), 5,0xf61e2562L);
1160 	R1(D,A,B,C,X( 6), 9,0xc040b340L);
1161 	R1(C,D,A,B,X(11),14,0x265e5a51L);
1162 	R1(B,C,D,A,X( 0),20,0xe9b6c7aaL);
1163 	R1(A,B,C,D,X( 5), 5,0xd62f105dL);
1164 	R1(D,A,B,C,X(10), 9,0x02441453L);
1165 	R1(C,D,A,B,X(15),14,0xd8a1e681L);
1166 	R1(B,C,D,A,X( 4),20,0xe7d3fbc8L);
1167 	R1(A,B,C,D,X( 9), 5,0x21e1cde6L);
1168 	R1(D,A,B,C,X(14), 9,0xc33707d6L);
1169 	R1(C,D,A,B,X( 3),14,0xf4d50d87L);
1170 	R1(B,C,D,A,X( 8),20,0x455a14edL);
1171 	R1(A,B,C,D,X(13), 5,0xa9e3e905L);
1172 	R1(D,A,B,C,X( 2), 9,0xfcefa3f8L);
1173 	R1(C,D,A,B,X( 7),14,0x676f02d9L);
1174 	R1(B,C,D,A,X(12),20,0x8d2a4c8aL);
1175 	/* Round 2 */
1176 	R2(A,B,C,D,X( 5), 4,0xfffa3942L);
1177 	R2(D,A,B,C,X( 8),11,0x8771f681L);
1178 	R2(C,D,A,B,X(11),16,0x6d9d6122L);
1179 	R2(B,C,D,A,X(14),23,0xfde5380cL);
1180 	R2(A,B,C,D,X( 1), 4,0xa4beea44L);
1181 	R2(D,A,B,C,X( 4),11,0x4bdecfa9L);
1182 	R2(C,D,A,B,X( 7),16,0xf6bb4b60L);
1183 	R2(B,C,D,A,X(10),23,0xbebfbc70L);
1184 	R2(A,B,C,D,X(13), 4,0x289b7ec6L);
1185 	R2(D,A,B,C,X( 0),11,0xeaa127faL);
1186 	R2(C,D,A,B,X( 3),16,0xd4ef3085L);
1187 	R2(B,C,D,A,X( 6),23,0x04881d05L);
1188 	R2(A,B,C,D,X( 9), 4,0xd9d4d039L);
1189 	R2(D,A,B,C,X(12),11,0xe6db99e5L);
1190 	R2(C,D,A,B,X(15),16,0x1fa27cf8L);
1191 	R2(B,C,D,A,X( 2),23,0xc4ac5665L);
1192 	/* Round 3 */
1193 	R3(A,B,C,D,X( 0), 6,0xf4292244L);
1194 	R3(D,A,B,C,X( 7),10,0x432aff97L);
1195 	R3(C,D,A,B,X(14),15,0xab9423a7L);
1196 	R3(B,C,D,A,X( 5),21,0xfc93a039L);
1197 	R3(A,B,C,D,X(12), 6,0x655b59c3L);
1198 	R3(D,A,B,C,X( 3),10,0x8f0ccc92L);
1199 	R3(C,D,A,B,X(10),15,0xffeff47dL);
1200 	R3(B,C,D,A,X( 1),21,0x85845dd1L);
1201 	R3(A,B,C,D,X( 8), 6,0x6fa87e4fL);
1202 	R3(D,A,B,C,X(15),10,0xfe2ce6e0L);
1203 	R3(C,D,A,B,X( 6),15,0xa3014314L);
1204 	R3(B,C,D,A,X(13),21,0x4e0811a1L);
1205 	R3(A,B,C,D,X( 4), 6,0xf7537e82L);
1206 	R3(D,A,B,C,X(11),10,0xbd3af235L);
1207 	R3(C,D,A,B,X( 2),15,0x2ad7d2bbL);
1208 	R3(B,C,D,A,X( 9),21,0xeb86d391L);
1209 
1210 	A = c->A += A;
1211 	B = c->B += B;
1212 	C = c->C += C;
1213 	D = c->D += D;
1214 		}
1215 	}
1216 #endif
1217 
1218 
1219  // ***************************************************************************
1220 #if COMPILER_LIKES_PRAGMA_MARK
1221 #pragma mark - base64 -> binary conversion
1222 #endif
1223 
1224 static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1225 static const char Pad64 = '=';
1226 
1227 
1228 #define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
1229 
1230 mDNSlocal const char *mDNSstrchr(const char *s, int c)
1231 	{
1232 	while (1)
1233 		{
1234 		if (c == *s) return s;
1235 		if (!*s) return mDNSNULL;
1236 		s++;
1237 		}
1238 	}
1239 
1240 // skips all whitespace anywhere.
1241 // converts characters, four at a time, starting at (or after)
1242 // src from base - 64 numbers into three 8 bit bytes in the target area.
1243 // it returns the number of data bytes stored at the target, or -1 on error.
1244 // adapted from BIND sources
1245 
1246 mDNSlocal mDNSs32 DNSDigest_Base64ToBin(const char *src, mDNSu8 *target, mDNSu32 targsize)
1247 	{
1248 	int tarindex, state, ch;
1249 	const char *pos;
1250 
1251 	state = 0;
1252 	tarindex = 0;
1253 
1254 	while ((ch = *src++) != '\0') {
1255 		if (mDNSisspace(ch))	/* Skip whitespace anywhere. */
1256 			continue;
1257 
1258 		if (ch == Pad64)
1259 			break;
1260 
1261 		pos = mDNSstrchr(Base64, ch);
1262 		if (pos == 0) 		/* A non-base64 character. */
1263 			return (-1);
1264 
1265 		switch (state) {
1266 		case 0:
1267 			if (target) {
1268 				if ((mDNSu32)tarindex >= targsize)
1269 					return (-1);
1270 				target[tarindex] = (mDNSu8)((pos - Base64) << 2);
1271 			}
1272 			state = 1;
1273 			break;
1274 		case 1:
1275 			if (target) {
1276 				if ((mDNSu32)tarindex + 1 >= targsize)
1277 					return (-1);
1278 				target[tarindex]   |=  (pos - Base64) >> 4;
1279 				target[tarindex+1]  = (mDNSu8)(((pos - Base64) & 0x0f) << 4);
1280 			}
1281 			tarindex++;
1282 			state = 2;
1283 			break;
1284 		case 2:
1285 			if (target) {
1286 				if ((mDNSu32)tarindex + 1 >= targsize)
1287 					return (-1);
1288 				target[tarindex]   |=  (pos - Base64) >> 2;
1289 				target[tarindex+1]  = (mDNSu8)(((pos - Base64) & 0x03) << 6);
1290 			}
1291 			tarindex++;
1292 			state = 3;
1293 			break;
1294 		case 3:
1295 			if (target) {
1296 				if ((mDNSu32)tarindex >= targsize)
1297 					return (-1);
1298 				target[tarindex] |= (pos - Base64);
1299 			}
1300 			tarindex++;
1301 			state = 0;
1302 			break;
1303 		default:
1304 			return -1;
1305 		}
1306 	}
1307 
1308 	/*
1309 	 * We are done decoding Base-64 chars.  Let's see if we ended
1310 	 * on a byte boundary, and/or with erroneous trailing characters.
1311 	 */
1312 
1313 	if (ch == Pad64) {		/* We got a pad char. */
1314 		ch = *src++;		/* Skip it, get next. */
1315 		switch (state) {
1316 		case 0:		/* Invalid = in first position */
1317 		case 1:		/* Invalid = in second position */
1318 			return (-1);
1319 
1320 		case 2:		/* Valid, means one byte of info */
1321 			/* Skip any number of spaces. */
1322 			for ((void)mDNSNULL; ch != '\0'; ch = *src++)
1323 				if (!mDNSisspace(ch))
1324 					break;
1325 			/* Make sure there is another trailing = sign. */
1326 			if (ch != Pad64)
1327 				return (-1);
1328 			ch = *src++;		/* Skip the = */
1329 			/* Fall through to "single trailing =" case. */
1330 			/* FALLTHROUGH */
1331 
1332 		case 3:		/* Valid, means two bytes of info */
1333 			/*
1334 			 * We know this char is an =.  Is there anything but
1335 			 * whitespace after it?
1336 			 */
1337 			for ((void)mDNSNULL; ch != '\0'; ch = *src++)
1338 				if (!mDNSisspace(ch))
1339 					return (-1);
1340 
1341 			/*
1342 			 * Now make sure for cases 2 and 3 that the "extra"
1343 			 * bits that slopped past the last full byte were
1344 			 * zeros.  If we don't check them, they become a
1345 			 * subliminal channel.
1346 			 */
1347 			if (target && target[tarindex] != 0)
1348 				return (-1);
1349 		}
1350 	} else {
1351 		/*
1352 		 * We ended by seeing the end of the string.  Make sure we
1353 		 * have no partial bytes lying around.
1354 		 */
1355 		if (state != 0)
1356 			return (-1);
1357 		}
1358 
1359 	return (tarindex);
1360 	}
1361 
1362 
1363  // ***************************************************************************
1364 #if COMPILER_LIKES_PRAGMA_MARK
1365 #pragma mark - API exported to mDNS Core
1366 #endif
1367 
1368 // Constants
1369 #define HMAC_IPAD   0x36
1370 #define HMAC_OPAD   0x5c
1371 #define MD5_LEN     16
1372 
1373 #define HMAC_MD5_AlgName (*(const domainname*) "\010" "hmac-md5" "\007" "sig-alg" "\003" "reg" "\003" "int")
1374 
1375 // Adapted from Appendix, RFC 2104
1376 mDNSlocal void DNSDigest_ConstructHMACKey(DomainAuthInfo *info, const mDNSu8 *key, mDNSu32 len)
1377 	{
1378 	MD5_CTX k;
1379 	mDNSu8 buf[MD5_LEN];
1380 	int i;
1381 
1382 	// If key is longer than HMAC_LEN reset it to MD5(key)
1383 	if (len > HMAC_LEN)
1384 		{
1385 		MD5_Init(&k);
1386 		MD5_Update(&k, key, len);
1387 		MD5_Final(buf, &k);
1388 		key = buf;
1389 		len = MD5_LEN;
1390 		}
1391 
1392 	// store key in pads
1393 	mDNSPlatformMemZero(info->keydata_ipad, HMAC_LEN);
1394 	mDNSPlatformMemZero(info->keydata_opad, HMAC_LEN);
1395 	mDNSPlatformMemCopy(info->keydata_ipad, key, len);
1396 	mDNSPlatformMemCopy(info->keydata_opad, key, len);
1397 
1398 	// XOR key with ipad and opad values
1399 	for (i = 0; i < HMAC_LEN; i++)
1400 		{
1401 		info->keydata_ipad[i] ^= HMAC_IPAD;
1402 		info->keydata_opad[i] ^= HMAC_OPAD;
1403 		}
1404 
1405 	}
1406 
1407 mDNSexport mDNSs32 DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo *info, const char *b64key)
1408 	{
1409 	mDNSu8 keybuf[1024];
1410 	mDNSs32 keylen = DNSDigest_Base64ToBin(b64key, keybuf, sizeof(keybuf));
1411 	if (keylen < 0) return(keylen);
1412 	DNSDigest_ConstructHMACKey(info, keybuf, (mDNSu32)keylen);
1413 	return(keylen);
1414 	}
1415 
1416 mDNSexport void DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode)
1417 	{
1418 	AuthRecord tsig;
1419 	mDNSu8  *rdata, *const countPtr = (mDNSu8 *)&msg->h.numAdditionals;	// Get existing numAdditionals value
1420 	mDNSu32 utc32;
1421 	mDNSu8 utc48[6];
1422 	mDNSu8 digest[MD5_LEN];
1423 	mDNSu8 *ptr = *end;
1424 	mDNSu32 len;
1425 	mDNSOpaque16 buf;
1426 	MD5_CTX c;
1427 	mDNSu16 numAdditionals = (mDNSu16)((mDNSu16)countPtr[0] << 8 | countPtr[1]);
1428 
1429 	// Init MD5 context, digest inner key pad and message
1430     MD5_Init(&c);
1431     MD5_Update(&c, info->keydata_ipad, HMAC_LEN);
1432 	MD5_Update(&c, (mDNSu8 *)msg, (unsigned long)(*end - (mDNSu8 *)msg));
1433 
1434 	// Construct TSIG RR, digesting variables as apporpriate
1435 	mDNS_SetupResourceRecord(&tsig, mDNSNULL, 0, kDNSType_TSIG, 0, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
1436 
1437 	// key name
1438 	AssignDomainName(&tsig.namestorage, &info->keyname);
1439 	MD5_Update(&c, info->keyname.c, DomainNameLength(&info->keyname));
1440 
1441 	// class
1442 	tsig.resrec.rrclass = kDNSQClass_ANY;
1443 	buf = mDNSOpaque16fromIntVal(kDNSQClass_ANY);
1444 	MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
1445 
1446 	// ttl
1447 	tsig.resrec.rroriginalttl = 0;
1448 	MD5_Update(&c, (mDNSu8 *)&tsig.resrec.rroriginalttl, sizeof(tsig.resrec.rroriginalttl));
1449 
1450 	// alg name
1451 	AssignDomainName(&tsig.resrec.rdata->u.name, &HMAC_MD5_AlgName);
1452 	len = DomainNameLength(&HMAC_MD5_AlgName);
1453 	rdata = tsig.resrec.rdata->u.data + len;
1454 	MD5_Update(&c, HMAC_MD5_AlgName.c, len);
1455 
1456 	// time
1457 	// get UTC (universal time), convert to 48-bit unsigned in network byte order
1458 	utc32 = (mDNSu32)mDNSPlatformUTC();
1459 	if (utc32 == (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); *end = mDNSNULL; }
1460 	utc48[0] = 0;
1461 	utc48[1] = 0;
1462 	utc48[2] = (mDNSu8)((utc32 >> 24) & 0xff);
1463 	utc48[3] = (mDNSu8)((utc32 >> 16) & 0xff);
1464 	utc48[4] = (mDNSu8)((utc32 >>  8) & 0xff);
1465 	utc48[5] = (mDNSu8)( utc32        & 0xff);
1466 
1467 	mDNSPlatformMemCopy(rdata, utc48, 6);
1468 	rdata += 6;
1469 	MD5_Update(&c, utc48, 6);
1470 
1471 	// 300 sec is fudge recommended in RFC 2485
1472 	rdata[0] = (mDNSu8)((300 >> 8)  & 0xff);
1473 	rdata[1] = (mDNSu8)( 300        & 0xff);
1474 	MD5_Update(&c, rdata, sizeof(mDNSOpaque16));
1475 	rdata += sizeof(mDNSOpaque16);
1476 
1477 	// digest error (tcode) and other data len (zero) - we'll add them to the rdata later
1478 	buf.b[0] = (mDNSu8)((tcode >> 8) & 0xff);
1479 	buf.b[1] = (mDNSu8)( tcode       & 0xff);
1480 	MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));  // error
1481 	buf.NotAnInteger = 0;
1482 	MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));  // other data len
1483 
1484 	// finish the message & tsig var hash
1485     MD5_Final(digest, &c);
1486 
1487 	// perform outer MD5 (outer key pad, inner digest)
1488 	MD5_Init(&c);
1489 	MD5_Update(&c, info->keydata_opad, HMAC_LEN);
1490 	MD5_Update(&c, digest, MD5_LEN);
1491 	MD5_Final(digest, &c);
1492 
1493 	// set remaining rdata fields
1494 	rdata[0] = (mDNSu8)((MD5_LEN >> 8)  & 0xff);
1495 	rdata[1] = (mDNSu8)( MD5_LEN        & 0xff);
1496 	rdata += sizeof(mDNSOpaque16);
1497 	mDNSPlatformMemCopy(rdata, digest, MD5_LEN);                          // MAC
1498 	rdata += MD5_LEN;
1499 	rdata[0] = msg->h.id.b[0];                                            // original ID
1500 	rdata[1] = msg->h.id.b[1];
1501 	rdata[2] = (mDNSu8)((tcode >> 8) & 0xff);
1502 	rdata[3] = (mDNSu8)( tcode       & 0xff);
1503 	rdata[4] = 0;                                                         // other data len
1504 	rdata[5] = 0;
1505 	rdata += 6;
1506 
1507 	tsig.resrec.rdlength = (mDNSu16)(rdata - tsig.resrec.rdata->u.data);
1508 	*end = PutResourceRecordTTLJumbo(msg, ptr, &numAdditionals, &tsig.resrec, 0);
1509 	if (!*end) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); *end = mDNSNULL; return; }
1510 
1511 	// Write back updated numAdditionals value
1512 	countPtr[0] = (mDNSu8)(numAdditionals >> 8);
1513 	countPtr[1] = (mDNSu8)(numAdditionals &  0xFF);
1514 	}
1515 
1516 mDNSexport mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCacheRecord * lcr, DomainAuthInfo *info, mDNSu16 * rcode, mDNSu16 * tcode)
1517 	{
1518 	mDNSu8			*	ptr = (mDNSu8*) &lcr->r.resrec.rdata->u.data;
1519 	mDNSs32				now;
1520 	mDNSs32				then;
1521 	mDNSu8				thisDigest[MD5_LEN];
1522 	mDNSu8				thatDigest[MD5_LEN];
1523 	mDNSu32				macsize;
1524 	mDNSOpaque16 		buf;
1525 	mDNSu8				utc48[6];
1526 	mDNSs32				delta;
1527 	mDNSu16				fudge;
1528 	domainname		*	algo;
1529 	MD5_CTX				c;
1530 	mDNSBool			ok = mDNSfalse;
1531 
1532 	// We only support HMAC-MD5 for now
1533 
1534 	algo = (domainname*) ptr;
1535 
1536 	if (!SameDomainName(algo, &HMAC_MD5_AlgName))
1537 		{
1538 		LogMsg("ERROR: DNSDigest_VerifyMessage - TSIG algorithm not supported: %##s", algo->c);
1539 		*rcode = kDNSFlag1_RC_NotAuth;
1540 		*tcode = TSIG_ErrBadKey;
1541 		ok = mDNSfalse;
1542 		goto exit;
1543 		}
1544 
1545 	ptr += DomainNameLength(algo);
1546 
1547 	// Check the times
1548 
1549 	now = mDNSPlatformUTC();
1550 	if (now == -1)
1551 		{
1552 		LogMsg("ERROR: DNSDigest_VerifyMessage - mDNSPlatformUTC returned bad time -1");
1553 		*rcode = kDNSFlag1_RC_NotAuth;
1554 		*tcode = TSIG_ErrBadTime;
1555 		ok = mDNSfalse;
1556 		goto exit;
1557 		}
1558 
1559 	// Get the 48 bit time field, skipping over the first word
1560 
1561 	utc48[0] = *ptr++;
1562 	utc48[1] = *ptr++;
1563 	utc48[2] = *ptr++;
1564 	utc48[3] = *ptr++;
1565 	utc48[4] = *ptr++;
1566 	utc48[5] = *ptr++;
1567 
1568 	then  = (mDNSs32)NToH32(utc48 + sizeof(mDNSu16));
1569 
1570 	fudge = NToH16(ptr);
1571 
1572 	ptr += sizeof(mDNSu16);
1573 
1574 	delta = (now > then) ? now - then : then - now;
1575 
1576 	if (delta > fudge)
1577 		{
1578 		LogMsg("ERROR: DNSDigest_VerifyMessage - time skew > %d", fudge);
1579 		*rcode = kDNSFlag1_RC_NotAuth;
1580 		*tcode = TSIG_ErrBadTime;
1581 		ok = mDNSfalse;
1582 		goto exit;
1583 		}
1584 
1585 	// MAC size
1586 
1587 	macsize = (mDNSu32) NToH16(ptr);
1588 
1589 	ptr += sizeof(mDNSu16);
1590 
1591 	// MAC
1592 
1593 	mDNSPlatformMemCopy(thatDigest, ptr, MD5_LEN);
1594 
1595 	// Init MD5 context, digest inner key pad and message
1596 
1597 	MD5_Init(&c);
1598 	MD5_Update(&c, info->keydata_ipad, HMAC_LEN);
1599 	MD5_Update(&c, (mDNSu8*) msg, (unsigned long)(end - (mDNSu8*) msg));
1600 
1601 	// Key name
1602 
1603 	MD5_Update(&c, lcr->r.resrec.name->c, DomainNameLength(lcr->r.resrec.name));
1604 
1605 	// Class name
1606 
1607 	buf = mDNSOpaque16fromIntVal(lcr->r.resrec.rrclass);
1608 	MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
1609 
1610 	// TTL
1611 
1612 	MD5_Update(&c, (mDNSu8*) &lcr->r.resrec.rroriginalttl, sizeof(lcr->r.resrec.rroriginalttl));
1613 
1614 	// Algorithm
1615 
1616 	MD5_Update(&c, algo->c, DomainNameLength(algo));
1617 
1618 	// Time
1619 
1620 	MD5_Update(&c, utc48, 6);
1621 
1622 	// Fudge
1623 
1624 	buf = mDNSOpaque16fromIntVal(fudge);
1625 	MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
1626 
1627 	// Digest error and other data len (both zero) - we'll add them to the rdata later
1628 
1629 	buf.NotAnInteger = 0;
1630 	MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));  // error
1631 	MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));  // other data len
1632 
1633 	// Finish the message & tsig var hash
1634 
1635     MD5_Final(thisDigest, &c);
1636 
1637 	// perform outer MD5 (outer key pad, inner digest)
1638 
1639 	MD5_Init(&c);
1640 	MD5_Update(&c, info->keydata_opad, HMAC_LEN);
1641 	MD5_Update(&c, thisDigest, MD5_LEN);
1642 	MD5_Final(thisDigest, &c);
1643 
1644 	if (!mDNSPlatformMemSame(thisDigest, thatDigest, MD5_LEN))
1645 		{
1646 		LogMsg("ERROR: DNSDigest_VerifyMessage - bad signature");
1647 		*rcode = kDNSFlag1_RC_NotAuth;
1648 		*tcode = TSIG_ErrBadSig;
1649 		ok = mDNSfalse;
1650 		goto exit;
1651 		}
1652 
1653 	// set remaining rdata fields
1654 	ok = mDNStrue;
1655 
1656 exit:
1657 
1658 	return ok;
1659 	}
1660 
1661 
1662 #ifdef __cplusplus
1663 }
1664 #endif
1665