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