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