1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 Change History (most recent first):
20 Revision 1.25 2007/12/17 23:48:29 cheshire
21 DNSDigest_SignMessage doesn't need to return a result -- it already updates the 'end' parameter
23 Revision 1.24 2007/11/30 23:03:51 cheshire
24 Fixes for EFI: Use "mDNSPlatformMemCopy" instead of assuming existence of "memcpy"
26 Revision 1.23 2007/09/21 21:12:36 cheshire
27 DNSDigest_SignMessage does not need separate "mDNSu16 *numAdditionals" parameter
29 Revision 1.22 2007/04/22 06:02:02 cheshire
30 <rdar://problem/4615977> Query should immediately return failure when no server
32 Revision 1.21 2007/03/22 18:31:48 cheshire
33 Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
35 Revision 1.20 2006/12/22 20:59:49 cheshire
36 <rdar://problem/4742742> Read *all* DNS keys from keychain,
37 not just key for the system-wide default registration domain
39 Revision 1.19 2006/12/21 00:06:07 cheshire
40 Don't need to do mDNSPlatformMemZero() -- mDNS_SetupResourceRecord() does it for us
42 Revision 1.18 2006/12/19 22:41:21 cheshire
45 Revision 1.17 2006/08/14 23:24:22 cheshire
46 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
48 Revision 1.16 2006/07/05 23:05:15 cheshire
49 <rdar://problem/4472013> Add Private DNS server functionality to dnsextd
50 Add DNSDigest_VerifyMessage() function
52 Revision 1.15 2006/06/20 04:12:30 cheshire
53 <rdar://problem/4490961> DNS Update broken
55 Revision 1.14 2006/02/25 23:12:07 cheshire
56 <rdar://problem/4427969> Fix to avoid code generation warning/error on FreeBSD 7
58 Revision 1.13 2004/12/16 20:12:59 cheshire
59 <rdar://problem/3324626> Cache memory management improvements
61 Revision 1.12 2004/12/03 07:20:50 ksekar
62 <rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
64 Revision 1.11 2004/12/02 01:10:27 cheshire
65 Fix to compile cleanly on 64-bit x86
67 Revision 1.10 2004/11/01 20:36:04 ksekar
68 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
70 Revision 1.9 2004/10/26 09:00:12 cheshire
71 Save a few bytes by creating HMAC_MD5_AlgName as a C string instead of a 256-byte object
73 Revision 1.8 2004/09/17 01:08:48 cheshire
74 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
75 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
76 declared in that file are ONLY appropriate to single-address-space embedded applications.
77 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
79 Revision 1.7 2004/08/15 18:36:38 cheshire
80 Don't use strcpy() and strlen() on "struct domainname" objects;
81 use AssignDomainName() and DomainNameLength() instead
82 (A "struct domainname" is a collection of packed pascal strings, not a C string.)
84 Revision 1.6 2004/06/02 00:17:46 ksekar
85 Referenced original OpenSSL license headers in source file description.
87 Revision 1.5 2004/05/20 18:37:37 cheshire
90 Revision 1.4 2004/04/22 20:28:20 cheshire
91 Use existing facility of PutResourceRecordTTL() to update count field for us
93 Revision 1.3 2004/04/22 03:05:28 cheshire
94 kDNSClass_ANY should be kDNSQClass_ANY
96 Revision 1.2 2004/04/15 00:51:28 bradley
97 Minor tweaks for Windows and C++ builds. Added casts for signed/unsigned integers and 64-bit pointers.
98 Prefix some functions with mDNS to avoid conflicts. Disable benign warnings on Microsoft compilers.
100 Revision 1.1 2004/04/14 23:09:28 ksekar
101 Support for TSIG signed dynamic updates.
112 #include "mDNSEmbeddedAPI.h"
113 #include "DNSCommon.h"
115 // Disable certain benign warnings with Microsoft compilers
116 #if(defined(_MSC_VER))
117 // Disable "conditional expression is constant" warning for debug macros.
118 // Otherwise, this generates warnings for the perfectly natural construct "while(1)"
119 // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
120 #pragma warning(disable:4127)
124 // ***************************************************************************
125 #if COMPILER_LIKES_PRAGMA_MARK
126 #pragma mark - Byte Swapping Functions
129 mDNSlocal mDNSu16
NToH16(mDNSu8
* bytes
)
131 return (mDNSu16
)((mDNSu16
)bytes
[0] << 8 | (mDNSu16
)bytes
[1]);
134 mDNSlocal mDNSu32
NToH32(mDNSu8
* bytes
)
136 return (mDNSu32
)((mDNSu32
) bytes
[0] << 24 | (mDNSu32
) bytes
[1] << 16 | (mDNSu32
) bytes
[2] << 8 | (mDNSu32
)bytes
[3]);
139 // ***************************************************************************
140 #if COMPILER_LIKES_PRAGMA_MARK
141 #pragma mark - MD5 Hash Functions
145 /* The source for the has is derived CommonCrypto files CommonDigest.h, md32_common.h, md5_locl.h, md5_locl.h, and openssl/md5.h.
146 * The following changes have been made to the original sources:
147 * replaced CC_LONG w/ mDNSu32
148 * replaced CC_MD5* with MD5*
149 * replaced CC_LONG w/ mDNSu32, removed conditional #defines from md5.h
150 * removed extern decls for MD5_Init/Update/Final from CommonDigest.h
151 * removed APPLE_COMMON_DIGEST specific #defines from md5_locl.h
153 * Note: machine archetecure specific conditionals from the original sources are turned off, but are left in the code
154 * to aid in platform-specific optimizations and debugging.
155 * Sources originally distributed under the following license headers:
156 * CommonDigest.c - APSL
159 * ====================================================================
160 * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
162 * Redistribution and use in source and binary forms, with or without
163 * modification, are permitted provided that the following conditions
166 * 1. Redistributions of source code must retain the above copyright
167 * notice, this list of conditions and the following disclaimer.
169 * 2. Redistributions in binary form must reproduce the above copyright
170 * notice, this list of conditions and the following disclaimer in
171 * the documentation and/or other materials provided with the
174 * 3. All advertising materials mentioning features or use of this
175 * software must display the following acknowledgment:
176 * "This product includes software developed by the OpenSSL Project
177 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
179 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
180 * endorse or promote products derived from this software without
181 * prior written permission. For written permission, please contact
182 * licensing@OpenSSL.org.
184 * 5. Products derived from this software may not be called "OpenSSL"
185 * nor may "OpenSSL" appear in their names without prior written
186 * permission of the OpenSSL Project.
188 * 6. Redistributions of any form whatsoever must retain the following
190 * "This product includes software developed by the OpenSSL Project
191 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
193 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
194 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
195 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
196 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
197 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
198 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
199 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
200 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
201 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
202 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
203 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
204 * OF THE POSSIBILITY OF SUCH DAMAGE.
207 * md5_dgst.c, md5_locl.h
208 * ====================================================================
210 * This product includes cryptographic software written by Eric Young
211 * (eay@cryptsoft.com). This product includes software written by Tim
212 * Hudson (tjh@cryptsoft.com).
214 * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
215 * All rights reserved.
217 * This package is an SSL implementation written
218 * by Eric Young (eay@cryptsoft.com).
219 * The implementation was written so as to conform with Netscapes SSL.
221 * This library is free for commercial and non-commercial use as long as
222 * the following conditions are aheared to. The following conditions
223 * apply to all code found in this distribution, be it the RC4, RSA,
224 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
225 * included with this distribution is covered by the same copyright terms
226 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
228 * Copyright remains Eric Young's, and as such any Copyright notices in
229 * the code are not to be removed.
230 * If this package is used in a product, Eric Young should be given attribution
231 * as the author of the parts of the library used.
232 * This can be in the form of a textual message at program startup or
233 * in documentation (online or textual) provided with the package.
235 * Redistribution and use in source and binary forms, with or without
236 * modification, are permitted provided that the following conditions
238 * 1. Redistributions of source code must retain the copyright
239 * notice, this list of conditions and the following disclaimer.
240 * 2. Redistributions in binary form must reproduce the above copyright
241 * notice, this list of conditions and the following disclaimer in the
242 * documentation and/or other materials provided with the distribution.
243 * 3. All advertising materials mentioning features or use of this software
244 * must display the following acknowledgement:
245 * "This product includes cryptographic software written by
246 * Eric Young (eay@cryptsoft.com)"
247 * The word 'cryptographic' can be left out if the rouines from the library
248 * being used are not cryptographic related :-).
249 * 4. If you include any Windows specific code (or a derivative thereof) from
250 * the apps directory (application code) you must include an acknowledgement:
251 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
253 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
254 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
255 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
256 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
257 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
258 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
260 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
262 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
265 * The licence and distribution terms for any publically available version or
266 * derivative of this code cannot be changed. i.e. this code cannot simply be
267 * copied and put under another distribution licence
268 * [including the GNU Public Licence.]
272 //from CommonDigest.h
274 #define MD5_DIGEST_LENGTH 16 /* digest length in bytes */
275 #define MD5_BLOCK_BYTES 64 /* block size in bytes */
276 #define MD5_BLOCK_LONG (MD5_BLOCK_BYTES / sizeof(mDNSu32))
278 typedef struct MD5state_st
282 mDNSu32 data
[MD5_BLOCK_LONG
];
287 // from openssl/md5.h
289 #define MD5_CBLOCK 64
290 #define MD5_LBLOCK (MD5_CBLOCK/4)
291 #define MD5_DIGEST_LENGTH 16
293 int MD5_Init(MD5_CTX
*c
);
294 int MD5_Update(MD5_CTX
*c
, const void *data
, unsigned long len
);
295 int MD5_Final(unsigned char *md
, MD5_CTX
*c
);
296 void MD5_Transform(MD5_CTX
*c
, const unsigned char *b
);
300 #ifndef MD5_LONG_LOG2
301 #define MD5_LONG_LOG2 2 /* default to 32 bits */
305 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
306 # define md5_block_host_order md5_block_asm_host_order
307 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
308 void md5_block_asm_data_order_aligned (MD5_CTX
*c
, const mDNSu32
*p
,int num
);
309 # define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned
313 void md5_block_host_order (MD5_CTX
*c
, const void *p
,int num
);
314 void md5_block_data_order (MD5_CTX
*c
, const void *p
,int num
);
316 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
318 * *_block_host_order is expected to handle aligned data while
319 * *_block_data_order - unaligned. As algorithm and host (x86)
320 * are in this case of the same "endianness" these two are
321 * otherwise indistinguishable. But normally you don't want to
322 * call the same function because unaligned access in places
323 * where alignment is expected is usually a "Bad Thing". Indeed,
324 * on RISCs you get punished with BUS ERROR signal or *severe*
325 * performance degradation. Intel CPUs are in turn perfectly
326 * capable of loading unaligned data without such drastic side
327 * effect. Yes, they say it's slower than aligned load, but no
328 * exception is generated and therefore performance degradation
329 * is *incomparable* with RISCs. What we should weight here is
330 * costs of unaligned access against costs of aligning data.
331 * According to my measurements allowing unaligned access results
332 * in ~9% performance improvement on Pentium II operating at
333 * 266MHz. I won't be surprised if the difference will be higher
334 * on faster systems:-)
336 * <appro@fy.chalmers.se>
338 #define md5_block_data_order md5_block_host_order
341 #define DATA_ORDER_IS_LITTLE_ENDIAN
343 #define HASH_LONG mDNSu32
344 #define HASH_LONG_LOG2 MD5_LONG_LOG2
345 #define HASH_CTX MD5_CTX
346 #define HASH_CBLOCK MD5_CBLOCK
347 #define HASH_LBLOCK MD5_LBLOCK
349 #define HASH_UPDATE MD5_Update
350 #define HASH_TRANSFORM MD5_Transform
351 #define HASH_FINAL MD5_Final
353 #define HASH_MAKE_STRING(c,s) do { \
355 ll=(c)->A; HOST_l2c(ll,(s)); \
356 ll=(c)->B; HOST_l2c(ll,(s)); \
357 ll=(c)->C; HOST_l2c(ll,(s)); \
358 ll=(c)->D; HOST_l2c(ll,(s)); \
360 #define HASH_BLOCK_HOST_ORDER md5_block_host_order
361 #if !defined(L_ENDIAN) || defined(md5_block_data_order)
362 #define HASH_BLOCK_DATA_ORDER md5_block_data_order
364 * Little-endians (Intel and Alpha) feel better without this.
365 * It looks like memcpy does better job than generic
366 * md5_block_data_order on copying-n-aligning input data.
367 * But frankly speaking I didn't expect such result on Alpha.
368 * On the other hand I've got this with egcs-1.0.2 and if
369 * program is compiled with another (better?) compiler it
370 * might turn out other way around.
372 * <appro@fy.chalmers.se>
377 // from md32_common.h
380 * This is a generic 32 bit "collector" for message digest algorithms.
381 * Whenever needed it collects input character stream into chunks of
382 * 32 bit values and invokes a block function that performs actual hash
389 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
390 * this macro defines byte order of input stream.
392 * size of a unit chunk HASH_BLOCK operates on.
394 * has to be at lest 32 bit wide, if it's wider, then
395 * HASH_LONG_LOG2 *has to* be defined along
397 * context structure that at least contains following
402 * HASH_LONG data[HASH_LBLOCK];
407 * name of "Update" function, implemented here.
409 * name of "Transform" function, implemented here.
411 * name of "Final" function, implemented here.
412 * HASH_BLOCK_HOST_ORDER
413 * name of "block" function treating *aligned* input message
414 * in host byte order, implemented externally.
415 * HASH_BLOCK_DATA_ORDER
416 * name of "block" function treating *unaligned* input message
417 * in original (data) byte order, implemented externally (it
418 * actually is optional if data and host are of the same
421 * macro convering context variables to an ASCII hash string.
425 * B_ENDIAN or L_ENDIAN
426 * defines host byte-order.
428 * defaults to 2 if not states otherwise.
430 * assumed to be HASH_CBLOCK/4 if not stated otherwise.
431 * HASH_BLOCK_DATA_ORDER_ALIGNED
432 * alternative "block" function capable of treating
433 * aligned input message in original (data) order,
434 * implemented externally.
438 * #define DATA_ORDER_IS_LITTLE_ENDIAN
440 * #define HASH_LONG mDNSu32
441 * #define HASH_LONG_LOG2 mDNSu32_LOG2
442 * #define HASH_CTX MD5_CTX
443 * #define HASH_CBLOCK MD5_CBLOCK
444 * #define HASH_LBLOCK MD5_LBLOCK
445 * #define HASH_UPDATE MD5_Update
446 * #define HASH_TRANSFORM MD5_Transform
447 * #define HASH_FINAL MD5_Final
448 * #define HASH_BLOCK_HOST_ORDER md5_block_host_order
449 * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
451 * <appro@fy.chalmers.se>
454 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
455 #error "DATA_ORDER must be defined!"
459 #error "HASH_CBLOCK must be defined!"
462 #error "HASH_LONG must be defined!"
465 #error "HASH_CTX must be defined!"
469 #error "HASH_UPDATE must be defined!"
471 #ifndef HASH_TRANSFORM
472 #error "HASH_TRANSFORM must be defined!"
475 #error "HASH_FINAL must be defined!"
478 #ifndef HASH_BLOCK_HOST_ORDER
479 #error "HASH_BLOCK_HOST_ORDER must be defined!"
484 * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
487 #ifndef HASH_BLOCK_DATA_ORDER
488 #error "HASH_BLOCK_DATA_ORDER must be defined!"
493 #define HASH_LBLOCK (HASH_CBLOCK/4)
496 #ifndef HASH_LONG_LOG2
497 #define HASH_LONG_LOG2 2
501 * Engage compiler specific rotate intrinsic function if available.
505 # if 0 /* defined(_MSC_VER) */
506 # define ROTATE(a,n) _lrotl(a,n)
507 # elif defined(__MWERKS__)
508 # if defined(__POWERPC__)
509 # define ROTATE(a,n) (unsigned MD32_REG_T)__rlwinm((int)a,n,0,31)
510 # elif defined(__MC68K__)
511 /* Motorola specific tweak. <appro@fy.chalmers.se> */
512 # define ROTATE(a,n) (n<24 ? __rol(a,n) : __ror(a,32-n))
514 # define ROTATE(a,n) __rol(a,n)
516 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
518 * Some GNU C inline assembler templates. Note that these are
519 * rotates by *constant* number of bits! But that's exactly
520 * what we need here...
522 * <appro@fy.chalmers.se>
524 # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
525 # define ROTATE(a,n) ({ register unsigned int ret; \
533 # elif defined(__powerpc) || defined(__ppc)
534 # define ROTATE(a,n) ({ register unsigned int ret; \
536 "rlwinm %0,%1,%2,0,31" \
545 * Engage compiler specific "fetch in reverse byte order"
546 * intrinsic function if available.
548 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
549 /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
550 # if (defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)) && !defined(I386_ONLY)
551 # define BE_FETCH32(a) ({ register unsigned int l=(a);\
554 : "=r"(l) : "0"(l)); \
557 # elif defined(__powerpc)
558 # define LE_FETCH32(a) ({ register unsigned int l; \
566 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
567 # define LE_FETCH32(a) ({ register unsigned int l; \
569 "lda [%1]#ASI_PRIMARY_LITTLE,%0"\
576 #endif /* PEDANTIC */
578 #if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */
579 /* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
581 /* 5 instructions with rotate instruction, else 9 */
582 #define REVERSE_FETCH32(a,l) ( \
583 l=*(const HASH_LONG *)(a), \
584 ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \
587 /* 6 instructions with rotate instruction, else 8 */
588 #define REVERSE_FETCH32(a,l) ( \
589 l=*(const HASH_LONG *)(a), \
590 l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \
594 * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
595 * It's rewritten as above for two reasons:
596 * - RISCs aren't good at long constants and have to explicitely
597 * compose 'em with several (well, usually 2) instructions in a
598 * register before performing the actual operation and (as you
599 * already realized:-) having same constant should inspire the
600 * compiler to permanently allocate the only register for it;
601 * - most modern CPUs have two ALUs, but usually only one has
602 * circuitry for shifts:-( this minor tweak inspires compiler
603 * to schedule shift instructions in a better way...
605 * <appro@fy.chalmers.se>
611 #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
615 * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
616 * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
617 * and host are of the same "endianess". It's possible to mask
618 * this with blank #define HASH_BLOCK_DATA_ORDER though...
620 * <appro@fy.chalmers.se>
622 #if defined(B_ENDIAN)
623 # if defined(DATA_ORDER_IS_BIG_ENDIAN)
624 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
625 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
627 # elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
628 # ifndef HOST_FETCH32
630 # define HOST_FETCH32(p,l) LE_FETCH32(p)
631 # elif defined(REVERSE_FETCH32)
632 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
636 #elif defined(L_ENDIAN)
637 # if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
638 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
639 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
641 # elif defined(DATA_ORDER_IS_BIG_ENDIAN)
642 # ifndef HOST_FETCH32
644 # define HOST_FETCH32(p,l) BE_FETCH32(p)
645 # elif defined(REVERSE_FETCH32)
646 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
652 #if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
653 #ifndef HASH_BLOCK_DATA_ORDER
654 #error "HASH_BLOCK_DATA_ORDER must be defined!"
658 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
660 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
661 l|=(((unsigned long)(*((c)++)))<<16), \
662 l|=(((unsigned long)(*((c)++)))<< 8), \
663 l|=(((unsigned long)(*((c)++))) ), \
665 #define HOST_p_c2l(c,l,n) { \
667 case 0: l =((unsigned long)(*((c)++)))<<24; \
668 case 1: l|=((unsigned long)(*((c)++)))<<16; \
669 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
670 case 3: l|=((unsigned long)(*((c)++))); \
672 #define HOST_p_c2l_p(c,l,sc,len) { \
674 case 0: l =((unsigned long)(*((c)++)))<<24; \
675 if (--len == 0) break; \
676 case 1: l|=((unsigned long)(*((c)++)))<<16; \
677 if (--len == 0) break; \
678 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
680 /* NOTE the pointer is not incremented at the end of this */
681 #define HOST_c2l_p(c,l,n) { \
684 case 3: l =((unsigned long)(*(--(c))))<< 8; \
685 case 2: l|=((unsigned long)(*(--(c))))<<16; \
686 case 1: l|=((unsigned long)(*(--(c))))<<24; \
688 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
689 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
690 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
691 *((c)++)=(unsigned char)(((l) )&0xff), \
694 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
696 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
697 l|=(((unsigned long)(*((c)++)))<< 8), \
698 l|=(((unsigned long)(*((c)++)))<<16), \
699 l|=(((unsigned long)(*((c)++)))<<24), \
701 #define HOST_p_c2l(c,l,n) { \
703 case 0: l =((unsigned long)(*((c)++))); \
704 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
705 case 2: l|=((unsigned long)(*((c)++)))<<16; \
706 case 3: l|=((unsigned long)(*((c)++)))<<24; \
708 #define HOST_p_c2l_p(c,l,sc,len) { \
710 case 0: l =((unsigned long)(*((c)++))); \
711 if (--len == 0) break; \
712 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
713 if (--len == 0) break; \
714 case 2: l|=((unsigned long)(*((c)++)))<<16; \
716 /* NOTE the pointer is not incremented at the end of this */
717 #define HOST_c2l_p(c,l,n) { \
720 case 3: l =((unsigned long)(*(--(c))))<<16; \
721 case 2: l|=((unsigned long)(*(--(c))))<< 8; \
722 case 1: l|=((unsigned long)(*(--(c)))); \
724 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
725 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
726 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
727 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
733 * Time for some action:-)
736 int HASH_UPDATE (HASH_CTX
*c
, const void *data_
, unsigned long len
)
738 const unsigned char *data
=(const unsigned char *)data_
;
739 register HASH_LONG
* p
;
740 register unsigned long l
;
743 if (len
==0) return 1;
745 l
=(c
->Nl
+(len
<<3))&0xffffffffL
;
746 /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
747 * Wei Dai <weidai@eskimo.com> for pointing it out. */
748 if (l
< c
->Nl
) /* overflow */
759 if ((c
->num
+len
) >= HASH_CBLOCK
)
761 l
=p
[sw
]; HOST_p_c2l(data
,l
,sc
); p
[sw
++]=l
;
762 for (; sw
<HASH_LBLOCK
; sw
++)
764 HOST_c2l(data
,l
); p
[sw
]=l
;
766 HASH_BLOCK_HOST_ORDER (c
,p
,1);
767 len
-=(HASH_CBLOCK
-c
->num
);
769 /* drop through and do the rest */
774 if ((sc
+len
) < 4) /* ugly, add char's to a word */
776 l
=p
[sw
]; HOST_p_c2l_p(data
,l
,sc
,len
); p
[sw
]=l
;
784 HOST_p_c2l(data
,l
,sc
);
786 for (; sw
< ew
; sw
++)
788 HOST_c2l(data
,l
); p
[sw
]=l
;
792 HOST_c2l_p(data
,l
,ec
); p
[sw
]=l
;
799 sw
=(int)(len
/HASH_CBLOCK
);
802 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
804 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
805 * only if sizeof(HASH_LONG)==4.
807 if ((((unsigned long)data
)%4
) == 0)
809 /* data is properly aligned so that we can cast it: */
810 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,(HASH_LONG
*)data
,sw
);
816 #if !defined(HASH_BLOCK_DATA_ORDER)
819 mDNSPlatformMemCopy(p
=c
->data
,data
,HASH_CBLOCK
);
820 HASH_BLOCK_DATA_ORDER_ALIGNED(c
,p
,1);
826 #if defined(HASH_BLOCK_DATA_ORDER)
828 HASH_BLOCK_DATA_ORDER(c
,data
,sw
);
840 ew
=(int)(len
>>2); /* words to copy */
844 HOST_c2l(data
,l
); *p
=l
;
846 HOST_c2l_p(data
,l
,ec
);
853 void HASH_TRANSFORM (HASH_CTX
*c
, const unsigned char *data
)
855 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
856 if ((((unsigned long)data
)%4
) == 0)
857 /* data is properly aligned so that we can cast it: */
858 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,(HASH_LONG
*)data
,1);
860 #if !defined(HASH_BLOCK_DATA_ORDER)
862 mDNSPlatformMemCopy(c
->data
,data
,HASH_CBLOCK
);
863 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,c
->data
,1);
867 #if defined(HASH_BLOCK_DATA_ORDER)
868 HASH_BLOCK_DATA_ORDER (c
,data
,1);
873 int HASH_FINAL (unsigned char *md
, HASH_CTX
*c
)
875 register HASH_LONG
*p
;
876 register unsigned long l
;
878 static const unsigned char end
[4]={0x80,0x00,0x00,0x00};
879 const unsigned char *cp
=end
;
881 /* c->num should definitly have room for at least one more byte. */
887 /* purify often complains about the following line as an
888 * Uninitialized Memory Read. While this can be true, the
889 * following p_c2l macro will reset l when that case is true.
890 * This is because j&0x03 contains the number of 'valid' bytes
891 * already in p[i]. If and only if j&0x03 == 0, the UMR will
892 * occur but this is also the only time p_c2l will do
893 * l= *(cp++) instead of l|= *(cp++)
894 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
897 if (j
==0) p
[i
]=0; /* Yeah, but that's not the way to fix it:-) */
901 l
= (j
==0) ? 0 : p
[i
];
903 HOST_p_c2l(cp
,l
,j
); p
[i
++]=l
; /* i is the next 'undefined word' */
905 if (i
>(HASH_LBLOCK
-2)) /* save room for Nl and Nh */
907 if (i
<HASH_LBLOCK
) p
[i
]=0;
908 HASH_BLOCK_HOST_ORDER (c
,p
,1);
911 for (; i
<(HASH_LBLOCK
-2); i
++)
914 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
915 p
[HASH_LBLOCK
-2]=c
->Nh
;
916 p
[HASH_LBLOCK
-1]=c
->Nl
;
917 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
918 p
[HASH_LBLOCK
-2]=c
->Nl
;
919 p
[HASH_LBLOCK
-1]=c
->Nh
;
921 HASH_BLOCK_HOST_ORDER (c
,p
,1);
923 #ifndef HASH_MAKE_STRING
924 #error "HASH_MAKE_STRING must be defined!"
926 HASH_MAKE_STRING(c
,md
);
930 /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
931 * but I'm not worried :-)
932 OPENSSL_cleanse((void *)c,sizeof(HASH_CTX));
938 #define MD32_REG_T long
940 * This comment was originaly written for MD5, which is why it
941 * discusses A-D. But it basically applies to all 32-bit digests,
942 * which is why it was moved to common header file.
944 * In case you wonder why A-D are declared as long and not
945 * as mDNSu32. Doing so results in slight performance
946 * boost on LP64 architectures. The catch is we don't
947 * really care if 32 MSBs of a 64-bit register get polluted
948 * with eventual overflows as we *save* only 32 LSBs in
949 * *either* case. Now declaring 'em long excuses the compiler
950 * from keeping 32 MSBs zeroed resulting in 13% performance
951 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
952 * Well, to be honest it should say that this *prevents*
953 * performance degradation.
954 * <appro@fy.chalmers.se>
955 * Apparently there're LP64 compilers that generate better
956 * code if A-D are declared int. Most notably GCC-x86_64
957 * generates better code.
958 * <appro@fy.chalmers.se>
963 // from md5_locl.h (continued)
966 #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
967 #define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
970 /* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
971 * simplified to the code below. Wei attributes these optimizations
972 * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
974 #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
975 #define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c))
976 #define H(b,c,d) ((b) ^ (c) ^ (d))
977 #define I(b,c,d) (((~(d)) | (b)) ^ (c))
979 #define R0(a,b,c,d,k,s,t) { \
980 a+=((k)+(t)+F((b),(c),(d))); \
984 #define R1(a,b,c,d,k,s,t) { \
985 a+=((k)+(t)+G((b),(c),(d))); \
989 #define R2(a,b,c,d,k,s,t) { \
990 a+=((k)+(t)+H((b),(c),(d))); \
994 #define R3(a,b,c,d,k,s,t) { \
995 a+=((k)+(t)+I((b),(c),(d))); \
1002 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
1005 #define INIT_DATA_A (unsigned long)0x67452301L
1006 #define INIT_DATA_B (unsigned long)0xefcdab89L
1007 #define INIT_DATA_C (unsigned long)0x98badcfeL
1008 #define INIT_DATA_D (unsigned long)0x10325476L
1010 int MD5_Init(MD5_CTX
*c
)
1022 #ifndef md5_block_host_order
1023 void md5_block_host_order (MD5_CTX
*c
, const void *data
, int num
)
1025 const mDNSu32
*X
=(const mDNSu32
*)data
;
1026 register unsigned MD32_REG_T A
,B
,C
,D
;
1033 for (;num
--;X
+=HASH_LBLOCK
)
1036 R0(A
,B
,C
,D
,X
[ 0], 7,0xd76aa478L
);
1037 R0(D
,A
,B
,C
,X
[ 1],12,0xe8c7b756L
);
1038 R0(C
,D
,A
,B
,X
[ 2],17,0x242070dbL
);
1039 R0(B
,C
,D
,A
,X
[ 3],22,0xc1bdceeeL
);
1040 R0(A
,B
,C
,D
,X
[ 4], 7,0xf57c0fafL
);
1041 R0(D
,A
,B
,C
,X
[ 5],12,0x4787c62aL
);
1042 R0(C
,D
,A
,B
,X
[ 6],17,0xa8304613L
);
1043 R0(B
,C
,D
,A
,X
[ 7],22,0xfd469501L
);
1044 R0(A
,B
,C
,D
,X
[ 8], 7,0x698098d8L
);
1045 R0(D
,A
,B
,C
,X
[ 9],12,0x8b44f7afL
);
1046 R0(C
,D
,A
,B
,X
[10],17,0xffff5bb1L
);
1047 R0(B
,C
,D
,A
,X
[11],22,0x895cd7beL
);
1048 R0(A
,B
,C
,D
,X
[12], 7,0x6b901122L
);
1049 R0(D
,A
,B
,C
,X
[13],12,0xfd987193L
);
1050 R0(C
,D
,A
,B
,X
[14],17,0xa679438eL
);
1051 R0(B
,C
,D
,A
,X
[15],22,0x49b40821L
);
1053 R1(A
,B
,C
,D
,X
[ 1], 5,0xf61e2562L
);
1054 R1(D
,A
,B
,C
,X
[ 6], 9,0xc040b340L
);
1055 R1(C
,D
,A
,B
,X
[11],14,0x265e5a51L
);
1056 R1(B
,C
,D
,A
,X
[ 0],20,0xe9b6c7aaL
);
1057 R1(A
,B
,C
,D
,X
[ 5], 5,0xd62f105dL
);
1058 R1(D
,A
,B
,C
,X
[10], 9,0x02441453L
);
1059 R1(C
,D
,A
,B
,X
[15],14,0xd8a1e681L
);
1060 R1(B
,C
,D
,A
,X
[ 4],20,0xe7d3fbc8L
);
1061 R1(A
,B
,C
,D
,X
[ 9], 5,0x21e1cde6L
);
1062 R1(D
,A
,B
,C
,X
[14], 9,0xc33707d6L
);
1063 R1(C
,D
,A
,B
,X
[ 3],14,0xf4d50d87L
);
1064 R1(B
,C
,D
,A
,X
[ 8],20,0x455a14edL
);
1065 R1(A
,B
,C
,D
,X
[13], 5,0xa9e3e905L
);
1066 R1(D
,A
,B
,C
,X
[ 2], 9,0xfcefa3f8L
);
1067 R1(C
,D
,A
,B
,X
[ 7],14,0x676f02d9L
);
1068 R1(B
,C
,D
,A
,X
[12],20,0x8d2a4c8aL
);
1070 R2(A
,B
,C
,D
,X
[ 5], 4,0xfffa3942L
);
1071 R2(D
,A
,B
,C
,X
[ 8],11,0x8771f681L
);
1072 R2(C
,D
,A
,B
,X
[11],16,0x6d9d6122L
);
1073 R2(B
,C
,D
,A
,X
[14],23,0xfde5380cL
);
1074 R2(A
,B
,C
,D
,X
[ 1], 4,0xa4beea44L
);
1075 R2(D
,A
,B
,C
,X
[ 4],11,0x4bdecfa9L
);
1076 R2(C
,D
,A
,B
,X
[ 7],16,0xf6bb4b60L
);
1077 R2(B
,C
,D
,A
,X
[10],23,0xbebfbc70L
);
1078 R2(A
,B
,C
,D
,X
[13], 4,0x289b7ec6L
);
1079 R2(D
,A
,B
,C
,X
[ 0],11,0xeaa127faL
);
1080 R2(C
,D
,A
,B
,X
[ 3],16,0xd4ef3085L
);
1081 R2(B
,C
,D
,A
,X
[ 6],23,0x04881d05L
);
1082 R2(A
,B
,C
,D
,X
[ 9], 4,0xd9d4d039L
);
1083 R2(D
,A
,B
,C
,X
[12],11,0xe6db99e5L
);
1084 R2(C
,D
,A
,B
,X
[15],16,0x1fa27cf8L
);
1085 R2(B
,C
,D
,A
,X
[ 2],23,0xc4ac5665L
);
1087 R3(A
,B
,C
,D
,X
[ 0], 6,0xf4292244L
);
1088 R3(D
,A
,B
,C
,X
[ 7],10,0x432aff97L
);
1089 R3(C
,D
,A
,B
,X
[14],15,0xab9423a7L
);
1090 R3(B
,C
,D
,A
,X
[ 5],21,0xfc93a039L
);
1091 R3(A
,B
,C
,D
,X
[12], 6,0x655b59c3L
);
1092 R3(D
,A
,B
,C
,X
[ 3],10,0x8f0ccc92L
);
1093 R3(C
,D
,A
,B
,X
[10],15,0xffeff47dL
);
1094 R3(B
,C
,D
,A
,X
[ 1],21,0x85845dd1L
);
1095 R3(A
,B
,C
,D
,X
[ 8], 6,0x6fa87e4fL
);
1096 R3(D
,A
,B
,C
,X
[15],10,0xfe2ce6e0L
);
1097 R3(C
,D
,A
,B
,X
[ 6],15,0xa3014314L
);
1098 R3(B
,C
,D
,A
,X
[13],21,0x4e0811a1L
);
1099 R3(A
,B
,C
,D
,X
[ 4], 6,0xf7537e82L
);
1100 R3(D
,A
,B
,C
,X
[11],10,0xbd3af235L
);
1101 R3(C
,D
,A
,B
,X
[ 2],15,0x2ad7d2bbL
);
1102 R3(B
,C
,D
,A
,X
[ 9],21,0xeb86d391L
);
1112 #ifndef md5_block_data_order
1116 void md5_block_data_order (MD5_CTX
*c
, const void *data_
, int num
)
1118 const unsigned char *data
=data_
;
1119 register unsigned MD32_REG_T A
,B
,C
,D
,l
;
1121 /* See comment in crypto/sha/sha_locl.h for details. */
1122 unsigned MD32_REG_T XX0
, XX1
, XX2
, XX3
, XX4
, XX5
, XX6
, XX7
,
1123 XX8
, XX9
,XX10
,XX11
,XX12
,XX13
,XX14
,XX15
;
1126 mDNSu32 XX
[MD5_LBLOCK
];
1137 HOST_c2l(data
,l
); X( 0)=l
; HOST_c2l(data
,l
); X( 1)=l
;
1139 R0(A
,B
,C
,D
,X( 0), 7,0xd76aa478L
); HOST_c2l(data
,l
); X( 2)=l
;
1140 R0(D
,A
,B
,C
,X( 1),12,0xe8c7b756L
); HOST_c2l(data
,l
); X( 3)=l
;
1141 R0(C
,D
,A
,B
,X( 2),17,0x242070dbL
); HOST_c2l(data
,l
); X( 4)=l
;
1142 R0(B
,C
,D
,A
,X( 3),22,0xc1bdceeeL
); HOST_c2l(data
,l
); X( 5)=l
;
1143 R0(A
,B
,C
,D
,X( 4), 7,0xf57c0fafL
); HOST_c2l(data
,l
); X( 6)=l
;
1144 R0(D
,A
,B
,C
,X( 5),12,0x4787c62aL
); HOST_c2l(data
,l
); X( 7)=l
;
1145 R0(C
,D
,A
,B
,X( 6),17,0xa8304613L
); HOST_c2l(data
,l
); X( 8)=l
;
1146 R0(B
,C
,D
,A
,X( 7),22,0xfd469501L
); HOST_c2l(data
,l
); X( 9)=l
;
1147 R0(A
,B
,C
,D
,X( 8), 7,0x698098d8L
); HOST_c2l(data
,l
); X(10)=l
;
1148 R0(D
,A
,B
,C
,X( 9),12,0x8b44f7afL
); HOST_c2l(data
,l
); X(11)=l
;
1149 R0(C
,D
,A
,B
,X(10),17,0xffff5bb1L
); HOST_c2l(data
,l
); X(12)=l
;
1150 R0(B
,C
,D
,A
,X(11),22,0x895cd7beL
); HOST_c2l(data
,l
); X(13)=l
;
1151 R0(A
,B
,C
,D
,X(12), 7,0x6b901122L
); HOST_c2l(data
,l
); X(14)=l
;
1152 R0(D
,A
,B
,C
,X(13),12,0xfd987193L
); HOST_c2l(data
,l
); X(15)=l
;
1153 R0(C
,D
,A
,B
,X(14),17,0xa679438eL
);
1154 R0(B
,C
,D
,A
,X(15),22,0x49b40821L
);
1156 R1(A
,B
,C
,D
,X( 1), 5,0xf61e2562L
);
1157 R1(D
,A
,B
,C
,X( 6), 9,0xc040b340L
);
1158 R1(C
,D
,A
,B
,X(11),14,0x265e5a51L
);
1159 R1(B
,C
,D
,A
,X( 0),20,0xe9b6c7aaL
);
1160 R1(A
,B
,C
,D
,X( 5), 5,0xd62f105dL
);
1161 R1(D
,A
,B
,C
,X(10), 9,0x02441453L
);
1162 R1(C
,D
,A
,B
,X(15),14,0xd8a1e681L
);
1163 R1(B
,C
,D
,A
,X( 4),20,0xe7d3fbc8L
);
1164 R1(A
,B
,C
,D
,X( 9), 5,0x21e1cde6L
);
1165 R1(D
,A
,B
,C
,X(14), 9,0xc33707d6L
);
1166 R1(C
,D
,A
,B
,X( 3),14,0xf4d50d87L
);
1167 R1(B
,C
,D
,A
,X( 8),20,0x455a14edL
);
1168 R1(A
,B
,C
,D
,X(13), 5,0xa9e3e905L
);
1169 R1(D
,A
,B
,C
,X( 2), 9,0xfcefa3f8L
);
1170 R1(C
,D
,A
,B
,X( 7),14,0x676f02d9L
);
1171 R1(B
,C
,D
,A
,X(12),20,0x8d2a4c8aL
);
1173 R2(A
,B
,C
,D
,X( 5), 4,0xfffa3942L
);
1174 R2(D
,A
,B
,C
,X( 8),11,0x8771f681L
);
1175 R2(C
,D
,A
,B
,X(11),16,0x6d9d6122L
);
1176 R2(B
,C
,D
,A
,X(14),23,0xfde5380cL
);
1177 R2(A
,B
,C
,D
,X( 1), 4,0xa4beea44L
);
1178 R2(D
,A
,B
,C
,X( 4),11,0x4bdecfa9L
);
1179 R2(C
,D
,A
,B
,X( 7),16,0xf6bb4b60L
);
1180 R2(B
,C
,D
,A
,X(10),23,0xbebfbc70L
);
1181 R2(A
,B
,C
,D
,X(13), 4,0x289b7ec6L
);
1182 R2(D
,A
,B
,C
,X( 0),11,0xeaa127faL
);
1183 R2(C
,D
,A
,B
,X( 3),16,0xd4ef3085L
);
1184 R2(B
,C
,D
,A
,X( 6),23,0x04881d05L
);
1185 R2(A
,B
,C
,D
,X( 9), 4,0xd9d4d039L
);
1186 R2(D
,A
,B
,C
,X(12),11,0xe6db99e5L
);
1187 R2(C
,D
,A
,B
,X(15),16,0x1fa27cf8L
);
1188 R2(B
,C
,D
,A
,X( 2),23,0xc4ac5665L
);
1190 R3(A
,B
,C
,D
,X( 0), 6,0xf4292244L
);
1191 R3(D
,A
,B
,C
,X( 7),10,0x432aff97L
);
1192 R3(C
,D
,A
,B
,X(14),15,0xab9423a7L
);
1193 R3(B
,C
,D
,A
,X( 5),21,0xfc93a039L
);
1194 R3(A
,B
,C
,D
,X(12), 6,0x655b59c3L
);
1195 R3(D
,A
,B
,C
,X( 3),10,0x8f0ccc92L
);
1196 R3(C
,D
,A
,B
,X(10),15,0xffeff47dL
);
1197 R3(B
,C
,D
,A
,X( 1),21,0x85845dd1L
);
1198 R3(A
,B
,C
,D
,X( 8), 6,0x6fa87e4fL
);
1199 R3(D
,A
,B
,C
,X(15),10,0xfe2ce6e0L
);
1200 R3(C
,D
,A
,B
,X( 6),15,0xa3014314L
);
1201 R3(B
,C
,D
,A
,X(13),21,0x4e0811a1L
);
1202 R3(A
,B
,C
,D
,X( 4), 6,0xf7537e82L
);
1203 R3(D
,A
,B
,C
,X(11),10,0xbd3af235L
);
1204 R3(C
,D
,A
,B
,X( 2),15,0x2ad7d2bbL
);
1205 R3(B
,C
,D
,A
,X( 9),21,0xeb86d391L
);
1216 // ***************************************************************************
1217 #if COMPILER_LIKES_PRAGMA_MARK
1218 #pragma mark - base64 -> binary conversion
1221 static const char Base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1222 static const char Pad64
= '=';
1225 #define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
1227 mDNSlocal
const char *mDNSstrchr(const char *s
, int c
)
1231 if (c
== *s
) return s
;
1232 if (!*s
) return mDNSNULL
;
1237 // skips all whitespace anywhere.
1238 // converts characters, four at a time, starting at (or after)
1239 // src from base - 64 numbers into three 8 bit bytes in the target area.
1240 // it returns the number of data bytes stored at the target, or -1 on error.
1241 // adapted from BIND sources
1243 mDNSlocal mDNSs32
DNSDigest_Base64ToBin(const char *src
, mDNSu8
*target
, mDNSu32 targsize
)
1245 int tarindex
, state
, ch
;
1251 while ((ch
= *src
++) != '\0') {
1252 if (mDNSisspace(ch
)) /* Skip whitespace anywhere. */
1258 pos
= mDNSstrchr(Base64
, ch
);
1259 if (pos
== 0) /* A non-base64 character. */
1265 if ((mDNSu32
)tarindex
>= targsize
)
1267 target
[tarindex
] = (mDNSu8
)((pos
- Base64
) << 2);
1273 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1275 target
[tarindex
] |= (pos
- Base64
) >> 4;
1276 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x0f) << 4);
1283 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1285 target
[tarindex
] |= (pos
- Base64
) >> 2;
1286 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x03) << 6);
1293 if ((mDNSu32
)tarindex
>= targsize
)
1295 target
[tarindex
] |= (pos
- Base64
);
1306 * We are done decoding Base-64 chars. Let's see if we ended
1307 * on a byte boundary, and/or with erroneous trailing characters.
1310 if (ch
== Pad64
) { /* We got a pad char. */
1311 ch
= *src
++; /* Skip it, get next. */
1313 case 0: /* Invalid = in first position */
1314 case 1: /* Invalid = in second position */
1317 case 2: /* Valid, means one byte of info */
1318 /* Skip any number of spaces. */
1319 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1320 if (!mDNSisspace(ch
))
1322 /* Make sure there is another trailing = sign. */
1325 ch
= *src
++; /* Skip the = */
1326 /* Fall through to "single trailing =" case. */
1329 case 3: /* Valid, means two bytes of info */
1331 * We know this char is an =. Is there anything but
1332 * whitespace after it?
1334 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1335 if (!mDNSisspace(ch
))
1339 * Now make sure for cases 2 and 3 that the "extra"
1340 * bits that slopped past the last full byte were
1341 * zeros. If we don't check them, they become a
1342 * subliminal channel.
1344 if (target
&& target
[tarindex
] != 0)
1349 * We ended by seeing the end of the string. Make sure we
1350 * have no partial bytes lying around.
1360 // ***************************************************************************
1361 #if COMPILER_LIKES_PRAGMA_MARK
1362 #pragma mark - API exported to mDNS Core
1366 #define HMAC_IPAD 0x36
1367 #define HMAC_OPAD 0x5c
1370 #define HMAC_MD5_AlgName (*(const domainname*) "\010" "hmac-md5" "\007" "sig-alg" "\003" "reg" "\003" "int")
1372 // Adapted from Appendix, RFC 2104
1373 mDNSlocal
void DNSDigest_ConstructHMACKey(DomainAuthInfo
*info
, const mDNSu8
*key
, mDNSu32 len
)
1376 mDNSu8 buf
[MD5_LEN
];
1379 // If key is longer than HMAC_LEN reset it to MD5(key)
1383 MD5_Update(&k
, key
, len
);
1389 // store key in pads
1390 mDNSPlatformMemZero(info
->keydata_ipad
, HMAC_LEN
);
1391 mDNSPlatformMemZero(info
->keydata_opad
, HMAC_LEN
);
1392 mDNSPlatformMemCopy(info
->keydata_ipad
, key
, len
);
1393 mDNSPlatformMemCopy(info
->keydata_opad
, key
, len
);
1395 // XOR key with ipad and opad values
1396 for (i
= 0; i
< HMAC_LEN
; i
++)
1398 info
->keydata_ipad
[i
] ^= HMAC_IPAD
;
1399 info
->keydata_opad
[i
] ^= HMAC_OPAD
;
1404 mDNSexport mDNSs32
DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo
*info
, const char *b64key
)
1406 mDNSu8 keybuf
[1024];
1407 mDNSs32 keylen
= DNSDigest_Base64ToBin(b64key
, keybuf
, sizeof(keybuf
));
1408 if (keylen
< 0) return(keylen
);
1409 DNSDigest_ConstructHMACKey(info
, keybuf
, (mDNSu32
)keylen
);
1413 mDNSexport
void DNSDigest_SignMessage(DNSMessage
*msg
, mDNSu8
**end
, DomainAuthInfo
*info
, mDNSu16 tcode
)
1416 mDNSu8
*rdata
, *const countPtr
= (mDNSu8
*)&msg
->h
.numAdditionals
; // Get existing numAdditionals value
1419 mDNSu8 digest
[MD5_LEN
];
1424 mDNSu16 numAdditionals
= (mDNSu16
)((mDNSu16
)countPtr
[0] << 8 | countPtr
[1]);
1426 // Init MD5 context, digest inner key pad and message
1428 MD5_Update(&c
, info
->keydata_ipad
, HMAC_LEN
);
1429 MD5_Update(&c
, (mDNSu8
*)msg
, (unsigned long)(*end
- (mDNSu8
*)msg
));
1431 // Construct TSIG RR, digesting variables as apporpriate
1432 mDNS_SetupResourceRecord(&tsig
, mDNSNULL
, 0, kDNSType_TSIG
, 0, kDNSRecordTypeKnownUnique
, mDNSNULL
, mDNSNULL
);
1435 AssignDomainName(&tsig
.namestorage
, &info
->keyname
);
1436 MD5_Update(&c
, info
->keyname
.c
, DomainNameLength(&info
->keyname
));
1439 tsig
.resrec
.rrclass
= kDNSQClass_ANY
;
1440 buf
= mDNSOpaque16fromIntVal(kDNSQClass_ANY
);
1441 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1444 tsig
.resrec
.rroriginalttl
= 0;
1445 MD5_Update(&c
, (mDNSu8
*)&tsig
.resrec
.rroriginalttl
, sizeof(tsig
.resrec
.rroriginalttl
));
1448 AssignDomainName(&tsig
.resrec
.rdata
->u
.name
, &HMAC_MD5_AlgName
);
1449 len
= DomainNameLength(&HMAC_MD5_AlgName
);
1450 rdata
= tsig
.resrec
.rdata
->u
.data
+ len
;
1451 MD5_Update(&c
, HMAC_MD5_AlgName
.c
, len
);
1454 // get UTC (universal time), convert to 48-bit unsigned in network byte order
1455 utc32
= (mDNSu32
)mDNSPlatformUTC();
1456 if (utc32
== (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); *end
= mDNSNULL
; }
1459 utc48
[2] = (mDNSu8
)((utc32
>> 24) & 0xff);
1460 utc48
[3] = (mDNSu8
)((utc32
>> 16) & 0xff);
1461 utc48
[4] = (mDNSu8
)((utc32
>> 8) & 0xff);
1462 utc48
[5] = (mDNSu8
)( utc32
& 0xff);
1464 mDNSPlatformMemCopy(rdata
, utc48
, 6);
1466 MD5_Update(&c
, utc48
, 6);
1468 // 300 sec is fudge recommended in RFC 2485
1469 rdata
[0] = (mDNSu8
)((300 >> 8) & 0xff);
1470 rdata
[1] = (mDNSu8
)( 300 & 0xff);
1471 MD5_Update(&c
, rdata
, sizeof(mDNSOpaque16
));
1472 rdata
+= sizeof(mDNSOpaque16
);
1474 // digest error (tcode) and other data len (zero) - we'll add them to the rdata later
1475 buf
.b
[0] = (mDNSu8
)((tcode
>> 8) & 0xff);
1476 buf
.b
[1] = (mDNSu8
)( tcode
& 0xff);
1477 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // error
1478 buf
.NotAnInteger
= 0;
1479 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // other data len
1481 // finish the message & tsig var hash
1482 MD5_Final(digest
, &c
);
1484 // perform outer MD5 (outer key pad, inner digest)
1486 MD5_Update(&c
, info
->keydata_opad
, HMAC_LEN
);
1487 MD5_Update(&c
, digest
, MD5_LEN
);
1488 MD5_Final(digest
, &c
);
1490 // set remaining rdata fields
1491 rdata
[0] = (mDNSu8
)((MD5_LEN
>> 8) & 0xff);
1492 rdata
[1] = (mDNSu8
)( MD5_LEN
& 0xff);
1493 rdata
+= sizeof(mDNSOpaque16
);
1494 mDNSPlatformMemCopy(rdata
, digest
, MD5_LEN
); // MAC
1496 rdata
[0] = msg
->h
.id
.b
[0]; // original ID
1497 rdata
[1] = msg
->h
.id
.b
[1];
1498 rdata
[2] = (mDNSu8
)((tcode
>> 8) & 0xff);
1499 rdata
[3] = (mDNSu8
)( tcode
& 0xff);
1500 rdata
[4] = 0; // other data len
1504 tsig
.resrec
.rdlength
= (mDNSu16
)(rdata
- tsig
.resrec
.rdata
->u
.data
);
1505 *end
= PutResourceRecordTTLJumbo(msg
, ptr
, &numAdditionals
, &tsig
.resrec
, 0);
1506 if (!*end
) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); *end
= mDNSNULL
; return; }
1508 // Write back updated numAdditionals value
1509 countPtr
[0] = (mDNSu8
)(numAdditionals
>> 8);
1510 countPtr
[1] = (mDNSu8
)(numAdditionals
& 0xFF);
1513 mDNSexport mDNSBool
DNSDigest_VerifyMessage(DNSMessage
*msg
, mDNSu8
*end
, LargeCacheRecord
* lcr
, DomainAuthInfo
*info
, mDNSu16
* rcode
, mDNSu16
* tcode
)
1515 mDNSu8
* ptr
= (mDNSu8
*) &lcr
->r
.resrec
.rdata
->u
.data
;
1518 mDNSu8 thisDigest
[MD5_LEN
];
1519 mDNSu8 thatDigest
[MD5_LEN
];
1527 mDNSBool ok
= mDNSfalse
;
1529 // We only support HMAC-MD5 for now
1531 algo
= (domainname
*) ptr
;
1533 if (!SameDomainName(algo
, &HMAC_MD5_AlgName
))
1535 LogMsg("ERROR: DNSDigest_VerifyMessage - TSIG algorithm not supported: %##s", algo
->c
);
1536 *rcode
= kDNSFlag1_RC_NotAuth
;
1537 *tcode
= TSIG_ErrBadKey
;
1542 ptr
+= DomainNameLength(algo
);
1546 now
= mDNSPlatformUTC();
1549 LogMsg("ERROR: DNSDigest_VerifyMessage - mDNSPlatformUTC returned bad time -1");
1550 *rcode
= kDNSFlag1_RC_NotAuth
;
1551 *tcode
= TSIG_ErrBadTime
;
1556 // Get the 48 bit time field, skipping over the first word
1565 then
= (mDNSs32
)NToH32(utc48
+ sizeof(mDNSu16
));
1567 fudge
= NToH16(ptr
);
1569 ptr
+= sizeof(mDNSu16
);
1571 delta
= (now
> then
) ? now
- then
: then
- now
;
1575 LogMsg("ERROR: DNSDigest_VerifyMessage - time skew > %d", fudge
);
1576 *rcode
= kDNSFlag1_RC_NotAuth
;
1577 *tcode
= TSIG_ErrBadTime
;
1584 macsize
= (mDNSu32
) NToH16(ptr
);
1586 ptr
+= sizeof(mDNSu16
);
1590 mDNSPlatformMemCopy(thatDigest
, ptr
, MD5_LEN
);
1592 // Init MD5 context, digest inner key pad and message
1595 MD5_Update(&c
, info
->keydata_ipad
, HMAC_LEN
);
1596 MD5_Update(&c
, (mDNSu8
*) msg
, (unsigned long)(end
- (mDNSu8
*) msg
));
1600 MD5_Update(&c
, lcr
->r
.resrec
.name
->c
, DomainNameLength(lcr
->r
.resrec
.name
));
1604 buf
= mDNSOpaque16fromIntVal(lcr
->r
.resrec
.rrclass
);
1605 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1609 MD5_Update(&c
, (mDNSu8
*) &lcr
->r
.resrec
.rroriginalttl
, sizeof(lcr
->r
.resrec
.rroriginalttl
));
1613 MD5_Update(&c
, algo
->c
, DomainNameLength(algo
));
1617 MD5_Update(&c
, utc48
, 6);
1621 buf
= mDNSOpaque16fromIntVal(fudge
);
1622 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1624 // Digest error and other data len (both zero) - we'll add them to the rdata later
1626 buf
.NotAnInteger
= 0;
1627 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // error
1628 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // other data len
1630 // Finish the message & tsig var hash
1632 MD5_Final(thisDigest
, &c
);
1634 // perform outer MD5 (outer key pad, inner digest)
1637 MD5_Update(&c
, info
->keydata_opad
, HMAC_LEN
);
1638 MD5_Update(&c
, thisDigest
, MD5_LEN
);
1639 MD5_Final(thisDigest
, &c
);
1641 if (!mDNSPlatformMemSame(thisDigest
, thatDigest
, MD5_LEN
))
1643 LogMsg("ERROR: DNSDigest_VerifyMessage - bad signature");
1644 *rcode
= kDNSFlag1_RC_NotAuth
;
1645 *tcode
= TSIG_ErrBadSig
;
1650 // set remaining rdata fields