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