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
19Log: DNSDigest.c,v $
20Revision 1.26  2008/10/10 23:21:51  mcguire
21fixed typo in original MD5 source reference
22
23Revision 1.25  2007/12/17 23:48:29  cheshire
24DNSDigest_SignMessage doesn't need to return a result -- it already updates the 'end' parameter
25
26Revision 1.24  2007/11/30 23:03:51  cheshire
27Fixes for EFI: Use "mDNSPlatformMemCopy" instead of assuming existence of "memcpy"
28
29Revision 1.23  2007/09/21 21:12:36  cheshire
30DNSDigest_SignMessage does not need separate "mDNSu16 *numAdditionals" parameter
31
32Revision 1.22  2007/04/22 06:02:02  cheshire
33<rdar://problem/4615977> Query should immediately return failure when no server
34
35Revision 1.21  2007/03/22 18:31:48  cheshire
36Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
37
38Revision 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
42Revision 1.19  2006/12/21 00:06:07  cheshire
43Don't need to do mDNSPlatformMemZero() -- mDNS_SetupResourceRecord() does it for us
44
45Revision 1.18  2006/12/19 22:41:21  cheshire
46Fix compiler warnings
47
48Revision 1.17  2006/08/14 23:24:22  cheshire
49Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
50
51Revision 1.16  2006/07/05 23:05:15  cheshire
52<rdar://problem/4472013> Add Private DNS server functionality to dnsextd
53Add DNSDigest_VerifyMessage() function
54
55Revision 1.15  2006/06/20 04:12:30  cheshire
56<rdar://problem/4490961> DNS Update broken
57
58Revision 1.14  2006/02/25 23:12:07  cheshire
59<rdar://problem/4427969> Fix to avoid code generation warning/error on FreeBSD 7
60
61Revision 1.13  2004/12/16 20:12:59  cheshire
62<rdar://problem/3324626> Cache memory management improvements
63
64Revision 1.12  2004/12/03 07:20:50  ksekar
65<rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
66
67Revision 1.11  2004/12/02 01:10:27  cheshire
68Fix to compile cleanly on 64-bit x86
69
70Revision 1.10  2004/11/01 20:36:04  ksekar
71<rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
72
73Revision 1.9  2004/10/26 09:00:12  cheshire
74Save a few bytes by creating HMAC_MD5_AlgName as a C string instead of a 256-byte object
75
76Revision 1.8  2004/09/17 01:08:48  cheshire
77Renamed 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
82Revision 1.7  2004/08/15 18:36:38  cheshire
83Don't use strcpy() and strlen() on "struct domainname" objects;
84use AssignDomainName() and DomainNameLength() instead
85(A "struct domainname" is a collection of packed pascal strings, not a C string.)
86
87Revision 1.6  2004/06/02 00:17:46  ksekar
88Referenced original OpenSSL license headers in source file description.
89
90Revision 1.5  2004/05/20 18:37:37  cheshire
91Fix compiler warnings
92
93Revision 1.4  2004/04/22 20:28:20  cheshire
94Use existing facility of PutResourceRecordTTL() to update count field for us
95
96Revision 1.3  2004/04/22 03:05:28  cheshire
97kDNSClass_ANY should be kDNSQClass_ANY
98
99Revision 1.2  2004/04/15 00:51:28  bradley
100Minor tweaks for Windows and C++ builds. Added casts for signed/unsigned integers and 64-bit pointers.
101Prefix some functions with mDNS to avoid conflicts. Disable benign warnings on Microsoft compilers.
102
103Revision 1.1  2004/04/14 23:09:28  ksekar
104Support for TSIG signed dynamic updates.
105
106
107
108*/
109
110
111#ifdef __cplusplus
112extern "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
132mDNSlocal mDNSu16 NToH16(mDNSu8 * bytes)
133	{
134	return (mDNSu16)((mDNSu16)bytes[0] << 8 | (mDNSu16)bytes[1]);
135	}
136
137mDNSlocal 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
281typedef 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
296int MD5_Init(MD5_CTX *c);
297int MD5_Update(MD5_CTX *c, const void *data, unsigned long len);
298int MD5_Final(unsigned char *md, MD5_CTX *c);
299void 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
316void md5_block_host_order (MD5_CTX *c, const void *p,int num);
317void 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"((unsigned int)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
739int 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
856void 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
876int 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
1013int 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
1026void 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
1119void 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
1224static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1225static const char Pad64 = '=';
1226
1227
1228#define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
1229
1230mDNSlocal 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
1246mDNSlocal 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
1376mDNSlocal 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
1407mDNSexport 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
1416mDNSexport 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
1516mDNSexport 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
1656exit:
1657
1658	return ok;
1659	}
1660
1661
1662#ifdef __cplusplus
1663}
1664#endif
1665