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.26 2008/10/10 23:21:51 mcguire
21 fixed typo in original MD5 source reference
23 Revision 1.25 2007/12/17 23:48:29 cheshire
24 DNSDigest_SignMessage doesn't need to return a result -- it already updates the 'end' parameter
26 Revision 1.24 2007/11/30 23:03:51 cheshire
27 Fixes for EFI: Use "mDNSPlatformMemCopy" instead of assuming existence of "memcpy"
29 Revision 1.23 2007/09/21 21:12:36 cheshire
30 DNSDigest_SignMessage does not need separate "mDNSu16 *numAdditionals" parameter
32 Revision 1.22 2007/04/22 06:02:02 cheshire
33 <rdar://problem/4615977> Query should immediately return failure when no server
35 Revision 1.21 2007/03/22 18:31:48 cheshire
36 Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
38 Revision 1.20 2006/12/22 20:59:49 cheshire
39 <rdar://problem/4742742> Read *all* DNS keys from keychain,
40 not just key for the system-wide default registration domain
42 Revision 1.19 2006/12/21 00:06:07 cheshire
43 Don't need to do mDNSPlatformMemZero() -- mDNS_SetupResourceRecord() does it for us
45 Revision 1.18 2006/12/19 22:41:21 cheshire
48 Revision 1.17 2006/08/14 23:24:22 cheshire
49 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
51 Revision 1.16 2006/07/05 23:05:15 cheshire
52 <rdar://problem/4472013> Add Private DNS server functionality to dnsextd
53 Add DNSDigest_VerifyMessage() function
55 Revision 1.15 2006/06/20 04:12:30 cheshire
56 <rdar://problem/4490961> DNS Update broken
58 Revision 1.14 2006/02/25 23:12:07 cheshire
59 <rdar://problem/4427969> Fix to avoid code generation warning/error on FreeBSD 7
61 Revision 1.13 2004/12/16 20:12:59 cheshire
62 <rdar://problem/3324626> Cache memory management improvements
64 Revision 1.12 2004/12/03 07:20:50 ksekar
65 <rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
67 Revision 1.11 2004/12/02 01:10:27 cheshire
68 Fix to compile cleanly on 64-bit x86
70 Revision 1.10 2004/11/01 20:36:04 ksekar
71 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
73 Revision 1.9 2004/10/26 09:00:12 cheshire
74 Save a few bytes by creating HMAC_MD5_AlgName as a C string instead of a 256-byte object
76 Revision 1.8 2004/09/17 01:08:48 cheshire
77 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
78 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
79 declared in that file are ONLY appropriate to single-address-space embedded applications.
80 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
82 Revision 1.7 2004/08/15 18:36:38 cheshire
83 Don't use strcpy() and strlen() on "struct domainname" objects;
84 use AssignDomainName() and DomainNameLength() instead
85 (A "struct domainname" is a collection of packed pascal strings, not a C string.)
87 Revision 1.6 2004/06/02 00:17:46 ksekar
88 Referenced original OpenSSL license headers in source file description.
90 Revision 1.5 2004/05/20 18:37:37 cheshire
93 Revision 1.4 2004/04/22 20:28:20 cheshire
94 Use existing facility of PutResourceRecordTTL() to update count field for us
96 Revision 1.3 2004/04/22 03:05:28 cheshire
97 kDNSClass_ANY should be kDNSQClass_ANY
99 Revision 1.2 2004/04/15 00:51:28 bradley
100 Minor tweaks for Windows and C++ builds. Added casts for signed/unsigned integers and 64-bit pointers.
101 Prefix some functions with mDNS to avoid conflicts. Disable benign warnings on Microsoft compilers.
103 Revision 1.1 2004/04/14 23:09:28 ksekar
104 Support for TSIG signed dynamic updates.
115 #include "mDNSEmbeddedAPI.h"
116 #include "DNSCommon.h"
118 // Disable certain benign warnings with Microsoft compilers
119 #if(defined(_MSC_VER))
120 // Disable "conditional expression is constant" warning for debug macros.
121 // Otherwise, this generates warnings for the perfectly natural construct "while(1)"
122 // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
123 #pragma warning(disable:4127)
127 // ***************************************************************************
128 #if COMPILER_LIKES_PRAGMA_MARK
129 #pragma mark - Byte Swapping Functions
132 mDNSlocal mDNSu16
NToH16(mDNSu8
* bytes
)
134 return (mDNSu16
)((mDNSu16
)bytes
[0] << 8 | (mDNSu16
)bytes
[1]);
137 mDNSlocal mDNSu32
NToH32(mDNSu8
* bytes
)
139 return (mDNSu32
)((mDNSu32
) bytes
[0] << 24 | (mDNSu32
) bytes
[1] << 16 | (mDNSu32
) bytes
[2] << 8 | (mDNSu32
)bytes
[3]);
142 // ***************************************************************************
143 #if COMPILER_LIKES_PRAGMA_MARK
144 #pragma mark - MD5 Hash Functions
148 /* The source for the has is derived CommonCrypto files CommonDigest.h, md32_common.h, md5_locl.h, md5_locl.h, and openssl/md5.h.
149 * The following changes have been made to the original sources:
150 * replaced CC_LONG w/ mDNSu32
151 * replaced CC_MD5* with MD5*
152 * replaced CC_LONG w/ mDNSu32, removed conditional #defines from md5.h
153 * removed extern decls for MD5_Init/Update/Final from CommonDigest.h
154 * removed APPLE_COMMON_DIGEST specific #defines from md5_locl.h
156 * Note: machine archetecure specific conditionals from the original sources are turned off, but are left in the code
157 * to aid in platform-specific optimizations and debugging.
158 * Sources originally distributed under the following license headers:
159 * CommonDigest.h - APSL
162 * ====================================================================
163 * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
165 * Redistribution and use in source and binary forms, with or without
166 * modification, are permitted provided that the following conditions
169 * 1. Redistributions of source code must retain the above copyright
170 * notice, this list of conditions and the following disclaimer.
172 * 2. Redistributions in binary form must reproduce the above copyright
173 * notice, this list of conditions and the following disclaimer in
174 * the documentation and/or other materials provided with the
177 * 3. All advertising materials mentioning features or use of this
178 * software must display the following acknowledgment:
179 * "This product includes software developed by the OpenSSL Project
180 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
182 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
183 * endorse or promote products derived from this software without
184 * prior written permission. For written permission, please contact
185 * licensing@OpenSSL.org.
187 * 5. Products derived from this software may not be called "OpenSSL"
188 * nor may "OpenSSL" appear in their names without prior written
189 * permission of the OpenSSL Project.
191 * 6. Redistributions of any form whatsoever must retain the following
193 * "This product includes software developed by the OpenSSL Project
194 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
196 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
197 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
198 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
199 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
200 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
201 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
202 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
203 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
204 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
205 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
206 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
207 * OF THE POSSIBILITY OF SUCH DAMAGE.
210 * md5_dgst.c, md5_locl.h
211 * ====================================================================
213 * This product includes cryptographic software written by Eric Young
214 * (eay@cryptsoft.com). This product includes software written by Tim
215 * Hudson (tjh@cryptsoft.com).
217 * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
218 * All rights reserved.
220 * This package is an SSL implementation written
221 * by Eric Young (eay@cryptsoft.com).
222 * The implementation was written so as to conform with Netscapes SSL.
224 * This library is free for commercial and non-commercial use as long as
225 * the following conditions are aheared to. The following conditions
226 * apply to all code found in this distribution, be it the RC4, RSA,
227 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
228 * included with this distribution is covered by the same copyright terms
229 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
231 * Copyright remains Eric Young's, and as such any Copyright notices in
232 * the code are not to be removed.
233 * If this package is used in a product, Eric Young should be given attribution
234 * as the author of the parts of the library used.
235 * This can be in the form of a textual message at program startup or
236 * in documentation (online or textual) provided with the package.
238 * Redistribution and use in source and binary forms, with or without
239 * modification, are permitted provided that the following conditions
241 * 1. Redistributions of source code must retain the copyright
242 * notice, this list of conditions and the following disclaimer.
243 * 2. Redistributions in binary form must reproduce the above copyright
244 * notice, this list of conditions and the following disclaimer in the
245 * documentation and/or other materials provided with the distribution.
246 * 3. All advertising materials mentioning features or use of this software
247 * must display the following acknowledgement:
248 * "This product includes cryptographic software written by
249 * Eric Young (eay@cryptsoft.com)"
250 * The word 'cryptographic' can be left out if the rouines from the library
251 * being used are not cryptographic related :-).
252 * 4. If you include any Windows specific code (or a derivative thereof) from
253 * the apps directory (application code) you must include an acknowledgement:
254 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
256 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
257 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
258 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
259 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
260 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
262 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
263 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
264 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
265 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
268 * The licence and distribution terms for any publically available version or
269 * derivative of this code cannot be changed. i.e. this code cannot simply be
270 * copied and put under another distribution licence
271 * [including the GNU Public Licence.]
275 //from CommonDigest.h
277 #define MD5_DIGEST_LENGTH 16 /* digest length in bytes */
278 #define MD5_BLOCK_BYTES 64 /* block size in bytes */
279 #define MD5_BLOCK_LONG (MD5_BLOCK_BYTES / sizeof(mDNSu32))
281 typedef struct MD5state_st
285 mDNSu32 data
[MD5_BLOCK_LONG
];
290 // from openssl/md5.h
292 #define MD5_CBLOCK 64
293 #define MD5_LBLOCK (MD5_CBLOCK/4)
294 #define MD5_DIGEST_LENGTH 16
296 int MD5_Init(MD5_CTX
*c
);
297 int MD5_Update(MD5_CTX
*c
, const void *data
, unsigned long len
);
298 int MD5_Final(unsigned char *md
, MD5_CTX
*c
);
299 void MD5_Transform(MD5_CTX
*c
, const unsigned char *b
);
303 #ifndef MD5_LONG_LOG2
304 #define MD5_LONG_LOG2 2 /* default to 32 bits */
308 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
309 # define md5_block_host_order md5_block_asm_host_order
310 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
311 void md5_block_asm_data_order_aligned (MD5_CTX
*c
, const mDNSu32
*p
,int num
);
312 # define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned
316 void md5_block_host_order (MD5_CTX
*c
, const void *p
,int num
);
317 void md5_block_data_order (MD5_CTX
*c
, const void *p
,int num
);
319 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
321 * *_block_host_order is expected to handle aligned data while
322 * *_block_data_order - unaligned. As algorithm and host (x86)
323 * are in this case of the same "endianness" these two are
324 * otherwise indistinguishable. But normally you don't want to
325 * call the same function because unaligned access in places
326 * where alignment is expected is usually a "Bad Thing". Indeed,
327 * on RISCs you get punished with BUS ERROR signal or *severe*
328 * performance degradation. Intel CPUs are in turn perfectly
329 * capable of loading unaligned data without such drastic side
330 * effect. Yes, they say it's slower than aligned load, but no
331 * exception is generated and therefore performance degradation
332 * is *incomparable* with RISCs. What we should weight here is
333 * costs of unaligned access against costs of aligning data.
334 * According to my measurements allowing unaligned access results
335 * in ~9% performance improvement on Pentium II operating at
336 * 266MHz. I won't be surprised if the difference will be higher
337 * on faster systems:-)
339 * <appro@fy.chalmers.se>
341 #define md5_block_data_order md5_block_host_order
344 #define DATA_ORDER_IS_LITTLE_ENDIAN
346 #define HASH_LONG mDNSu32
347 #define HASH_LONG_LOG2 MD5_LONG_LOG2
348 #define HASH_CTX MD5_CTX
349 #define HASH_CBLOCK MD5_CBLOCK
350 #define HASH_LBLOCK MD5_LBLOCK
352 #define HASH_UPDATE MD5_Update
353 #define HASH_TRANSFORM MD5_Transform
354 #define HASH_FINAL MD5_Final
356 #define HASH_MAKE_STRING(c,s) do { \
358 ll=(c)->A; HOST_l2c(ll,(s)); \
359 ll=(c)->B; HOST_l2c(ll,(s)); \
360 ll=(c)->C; HOST_l2c(ll,(s)); \
361 ll=(c)->D; HOST_l2c(ll,(s)); \
363 #define HASH_BLOCK_HOST_ORDER md5_block_host_order
364 #if !defined(L_ENDIAN) || defined(md5_block_data_order)
365 #define HASH_BLOCK_DATA_ORDER md5_block_data_order
367 * Little-endians (Intel and Alpha) feel better without this.
368 * It looks like memcpy does better job than generic
369 * md5_block_data_order on copying-n-aligning input data.
370 * But frankly speaking I didn't expect such result on Alpha.
371 * On the other hand I've got this with egcs-1.0.2 and if
372 * program is compiled with another (better?) compiler it
373 * might turn out other way around.
375 * <appro@fy.chalmers.se>
380 // from md32_common.h
383 * This is a generic 32 bit "collector" for message digest algorithms.
384 * Whenever needed it collects input character stream into chunks of
385 * 32 bit values and invokes a block function that performs actual hash
392 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
393 * this macro defines byte order of input stream.
395 * size of a unit chunk HASH_BLOCK operates on.
397 * has to be at lest 32 bit wide, if it's wider, then
398 * HASH_LONG_LOG2 *has to* be defined along
400 * context structure that at least contains following
405 * HASH_LONG data[HASH_LBLOCK];
410 * name of "Update" function, implemented here.
412 * name of "Transform" function, implemented here.
414 * name of "Final" function, implemented here.
415 * HASH_BLOCK_HOST_ORDER
416 * name of "block" function treating *aligned* input message
417 * in host byte order, implemented externally.
418 * HASH_BLOCK_DATA_ORDER
419 * name of "block" function treating *unaligned* input message
420 * in original (data) byte order, implemented externally (it
421 * actually is optional if data and host are of the same
424 * macro convering context variables to an ASCII hash string.
428 * B_ENDIAN or L_ENDIAN
429 * defines host byte-order.
431 * defaults to 2 if not states otherwise.
433 * assumed to be HASH_CBLOCK/4 if not stated otherwise.
434 * HASH_BLOCK_DATA_ORDER_ALIGNED
435 * alternative "block" function capable of treating
436 * aligned input message in original (data) order,
437 * implemented externally.
441 * #define DATA_ORDER_IS_LITTLE_ENDIAN
443 * #define HASH_LONG mDNSu32
444 * #define HASH_LONG_LOG2 mDNSu32_LOG2
445 * #define HASH_CTX MD5_CTX
446 * #define HASH_CBLOCK MD5_CBLOCK
447 * #define HASH_LBLOCK MD5_LBLOCK
448 * #define HASH_UPDATE MD5_Update
449 * #define HASH_TRANSFORM MD5_Transform
450 * #define HASH_FINAL MD5_Final
451 * #define HASH_BLOCK_HOST_ORDER md5_block_host_order
452 * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
454 * <appro@fy.chalmers.se>
457 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
458 #error "DATA_ORDER must be defined!"
462 #error "HASH_CBLOCK must be defined!"
465 #error "HASH_LONG must be defined!"
468 #error "HASH_CTX must be defined!"
472 #error "HASH_UPDATE must be defined!"
474 #ifndef HASH_TRANSFORM
475 #error "HASH_TRANSFORM must be defined!"
478 #error "HASH_FINAL must be defined!"
481 #ifndef HASH_BLOCK_HOST_ORDER
482 #error "HASH_BLOCK_HOST_ORDER must be defined!"
487 * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
490 #ifndef HASH_BLOCK_DATA_ORDER
491 #error "HASH_BLOCK_DATA_ORDER must be defined!"
496 #define HASH_LBLOCK (HASH_CBLOCK/4)
499 #ifndef HASH_LONG_LOG2
500 #define HASH_LONG_LOG2 2
504 * Engage compiler specific rotate intrinsic function if available.
508 # if 0 /* defined(_MSC_VER) */
509 # define ROTATE(a,n) _lrotl(a,n)
510 # elif defined(__MWERKS__)
511 # if defined(__POWERPC__)
512 # define ROTATE(a,n) (unsigned MD32_REG_T)__rlwinm((int)a,n,0,31)
513 # elif defined(__MC68K__)
514 /* Motorola specific tweak. <appro@fy.chalmers.se> */
515 # define ROTATE(a,n) (n<24 ? __rol(a,n) : __ror(a,32-n))
517 # define ROTATE(a,n) __rol(a,n)
519 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
521 * Some GNU C inline assembler templates. Note that these are
522 * rotates by *constant* number of bits! But that's exactly
523 * what we need here...
525 * <appro@fy.chalmers.se>
527 # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
528 # define ROTATE(a,n) ({ register unsigned int ret; \
536 # elif defined(__powerpc) || defined(__ppc)
537 # define ROTATE(a,n) ({ register unsigned int ret; \
539 "rlwinm %0,%1,%2,0,31" \
548 * Engage compiler specific "fetch in reverse byte order"
549 * intrinsic function if available.
551 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
552 /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
553 # if (defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)) && !defined(I386_ONLY)
554 # define BE_FETCH32(a) ({ register unsigned int l=(a);\
557 : "=r"(l) : "0"(l)); \
560 # elif defined(__powerpc)
561 # define LE_FETCH32(a) ({ register unsigned int l; \
569 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
570 # define LE_FETCH32(a) ({ register unsigned int l; \
572 "lda [%1]#ASI_PRIMARY_LITTLE,%0"\
579 #endif /* PEDANTIC */
581 #if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */
582 /* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
584 /* 5 instructions with rotate instruction, else 9 */
585 #define REVERSE_FETCH32(a,l) ( \
586 l=*(const HASH_LONG *)(a), \
587 ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \
590 /* 6 instructions with rotate instruction, else 8 */
591 #define REVERSE_FETCH32(a,l) ( \
592 l=*(const HASH_LONG *)(a), \
593 l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \
597 * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
598 * It's rewritten as above for two reasons:
599 * - RISCs aren't good at long constants and have to explicitely
600 * compose 'em with several (well, usually 2) instructions in a
601 * register before performing the actual operation and (as you
602 * already realized:-) having same constant should inspire the
603 * compiler to permanently allocate the only register for it;
604 * - most modern CPUs have two ALUs, but usually only one has
605 * circuitry for shifts:-( this minor tweak inspires compiler
606 * to schedule shift instructions in a better way...
608 * <appro@fy.chalmers.se>
614 #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
618 * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
619 * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
620 * and host are of the same "endianess". It's possible to mask
621 * this with blank #define HASH_BLOCK_DATA_ORDER though...
623 * <appro@fy.chalmers.se>
625 #if defined(B_ENDIAN)
626 # if defined(DATA_ORDER_IS_BIG_ENDIAN)
627 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
628 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
630 # elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
631 # ifndef HOST_FETCH32
633 # define HOST_FETCH32(p,l) LE_FETCH32(p)
634 # elif defined(REVERSE_FETCH32)
635 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
639 #elif defined(L_ENDIAN)
640 # if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
641 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
642 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
644 # elif defined(DATA_ORDER_IS_BIG_ENDIAN)
645 # ifndef HOST_FETCH32
647 # define HOST_FETCH32(p,l) BE_FETCH32(p)
648 # elif defined(REVERSE_FETCH32)
649 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
655 #if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
656 #ifndef HASH_BLOCK_DATA_ORDER
657 #error "HASH_BLOCK_DATA_ORDER must be defined!"
661 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
663 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
664 l|=(((unsigned long)(*((c)++)))<<16), \
665 l|=(((unsigned long)(*((c)++)))<< 8), \
666 l|=(((unsigned long)(*((c)++))) ), \
668 #define HOST_p_c2l(c,l,n) { \
670 case 0: l =((unsigned long)(*((c)++)))<<24; \
671 case 1: l|=((unsigned long)(*((c)++)))<<16; \
672 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
673 case 3: l|=((unsigned long)(*((c)++))); \
675 #define HOST_p_c2l_p(c,l,sc,len) { \
677 case 0: l =((unsigned long)(*((c)++)))<<24; \
678 if (--len == 0) break; \
679 case 1: l|=((unsigned long)(*((c)++)))<<16; \
680 if (--len == 0) break; \
681 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
683 /* NOTE the pointer is not incremented at the end of this */
684 #define HOST_c2l_p(c,l,n) { \
687 case 3: l =((unsigned long)(*(--(c))))<< 8; \
688 case 2: l|=((unsigned long)(*(--(c))))<<16; \
689 case 1: l|=((unsigned long)(*(--(c))))<<24; \
691 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
692 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
693 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
694 *((c)++)=(unsigned char)(((l) )&0xff), \
697 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
699 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
700 l|=(((unsigned long)(*((c)++)))<< 8), \
701 l|=(((unsigned long)(*((c)++)))<<16), \
702 l|=(((unsigned long)(*((c)++)))<<24), \
704 #define HOST_p_c2l(c,l,n) { \
706 case 0: l =((unsigned long)(*((c)++))); \
707 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
708 case 2: l|=((unsigned long)(*((c)++)))<<16; \
709 case 3: l|=((unsigned long)(*((c)++)))<<24; \
711 #define HOST_p_c2l_p(c,l,sc,len) { \
713 case 0: l =((unsigned long)(*((c)++))); \
714 if (--len == 0) break; \
715 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
716 if (--len == 0) break; \
717 case 2: l|=((unsigned long)(*((c)++)))<<16; \
719 /* NOTE the pointer is not incremented at the end of this */
720 #define HOST_c2l_p(c,l,n) { \
723 case 3: l =((unsigned long)(*(--(c))))<<16; \
724 case 2: l|=((unsigned long)(*(--(c))))<< 8; \
725 case 1: l|=((unsigned long)(*(--(c)))); \
727 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
728 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
729 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
730 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
736 * Time for some action:-)
739 int HASH_UPDATE (HASH_CTX
*c
, const void *data_
, unsigned long len
)
741 const unsigned char *data
=(const unsigned char *)data_
;
742 register HASH_LONG
* p
;
743 register unsigned long l
;
746 if (len
==0) return 1;
748 l
=(c
->Nl
+(len
<<3))&0xffffffffL
;
749 /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
750 * Wei Dai <weidai@eskimo.com> for pointing it out. */
751 if (l
< c
->Nl
) /* overflow */
762 if ((c
->num
+len
) >= HASH_CBLOCK
)
764 l
=p
[sw
]; HOST_p_c2l(data
,l
,sc
); p
[sw
++]=l
;
765 for (; sw
<HASH_LBLOCK
; sw
++)
767 HOST_c2l(data
,l
); p
[sw
]=l
;
769 HASH_BLOCK_HOST_ORDER (c
,p
,1);
770 len
-=(HASH_CBLOCK
-c
->num
);
772 /* drop through and do the rest */
777 if ((sc
+len
) < 4) /* ugly, add char's to a word */
779 l
=p
[sw
]; HOST_p_c2l_p(data
,l
,sc
,len
); p
[sw
]=l
;
787 HOST_p_c2l(data
,l
,sc
);
789 for (; sw
< ew
; sw
++)
791 HOST_c2l(data
,l
); p
[sw
]=l
;
795 HOST_c2l_p(data
,l
,ec
); p
[sw
]=l
;
802 sw
=(int)(len
/HASH_CBLOCK
);
805 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
807 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
808 * only if sizeof(HASH_LONG)==4.
810 if ((((unsigned long)data
)%4
) == 0)
812 /* data is properly aligned so that we can cast it: */
813 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,(HASH_LONG
*)data
,sw
);
819 #if !defined(HASH_BLOCK_DATA_ORDER)
822 mDNSPlatformMemCopy(p
=c
->data
,data
,HASH_CBLOCK
);
823 HASH_BLOCK_DATA_ORDER_ALIGNED(c
,p
,1);
829 #if defined(HASH_BLOCK_DATA_ORDER)
831 HASH_BLOCK_DATA_ORDER(c
,data
,sw
);
843 ew
=(int)(len
>>2); /* words to copy */
847 HOST_c2l(data
,l
); *p
=l
;
849 HOST_c2l_p(data
,l
,ec
);
856 void HASH_TRANSFORM (HASH_CTX
*c
, const unsigned char *data
)
858 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
859 if ((((unsigned long)data
)%4
) == 0)
860 /* data is properly aligned so that we can cast it: */
861 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,(HASH_LONG
*)data
,1);
863 #if !defined(HASH_BLOCK_DATA_ORDER)
865 mDNSPlatformMemCopy(c
->data
,data
,HASH_CBLOCK
);
866 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,c
->data
,1);
870 #if defined(HASH_BLOCK_DATA_ORDER)
871 HASH_BLOCK_DATA_ORDER (c
,data
,1);
876 int HASH_FINAL (unsigned char *md
, HASH_CTX
*c
)
878 register HASH_LONG
*p
;
879 register unsigned long l
;
881 static const unsigned char end
[4]={0x80,0x00,0x00,0x00};
882 const unsigned char *cp
=end
;
884 /* c->num should definitly have room for at least one more byte. */
890 /* purify often complains about the following line as an
891 * Uninitialized Memory Read. While this can be true, the
892 * following p_c2l macro will reset l when that case is true.
893 * This is because j&0x03 contains the number of 'valid' bytes
894 * already in p[i]. If and only if j&0x03 == 0, the UMR will
895 * occur but this is also the only time p_c2l will do
896 * l= *(cp++) instead of l|= *(cp++)
897 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
900 if (j
==0) p
[i
]=0; /* Yeah, but that's not the way to fix it:-) */
904 l
= (j
==0) ? 0 : p
[i
];
906 HOST_p_c2l(cp
,l
,j
); p
[i
++]=l
; /* i is the next 'undefined word' */
908 if (i
>(HASH_LBLOCK
-2)) /* save room for Nl and Nh */
910 if (i
<HASH_LBLOCK
) p
[i
]=0;
911 HASH_BLOCK_HOST_ORDER (c
,p
,1);
914 for (; i
<(HASH_LBLOCK
-2); i
++)
917 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
918 p
[HASH_LBLOCK
-2]=c
->Nh
;
919 p
[HASH_LBLOCK
-1]=c
->Nl
;
920 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
921 p
[HASH_LBLOCK
-2]=c
->Nl
;
922 p
[HASH_LBLOCK
-1]=c
->Nh
;
924 HASH_BLOCK_HOST_ORDER (c
,p
,1);
926 #ifndef HASH_MAKE_STRING
927 #error "HASH_MAKE_STRING must be defined!"
929 HASH_MAKE_STRING(c
,md
);
933 /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
934 * but I'm not worried :-)
935 OPENSSL_cleanse((void *)c,sizeof(HASH_CTX));
941 #define MD32_REG_T long
943 * This comment was originaly written for MD5, which is why it
944 * discusses A-D. But it basically applies to all 32-bit digests,
945 * which is why it was moved to common header file.
947 * In case you wonder why A-D are declared as long and not
948 * as mDNSu32. Doing so results in slight performance
949 * boost on LP64 architectures. The catch is we don't
950 * really care if 32 MSBs of a 64-bit register get polluted
951 * with eventual overflows as we *save* only 32 LSBs in
952 * *either* case. Now declaring 'em long excuses the compiler
953 * from keeping 32 MSBs zeroed resulting in 13% performance
954 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
955 * Well, to be honest it should say that this *prevents*
956 * performance degradation.
957 * <appro@fy.chalmers.se>
958 * Apparently there're LP64 compilers that generate better
959 * code if A-D are declared int. Most notably GCC-x86_64
960 * generates better code.
961 * <appro@fy.chalmers.se>
966 // from md5_locl.h (continued)
969 #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
970 #define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
973 /* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
974 * simplified to the code below. Wei attributes these optimizations
975 * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
977 #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
978 #define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c))
979 #define H(b,c,d) ((b) ^ (c) ^ (d))
980 #define I(b,c,d) (((~(d)) | (b)) ^ (c))
982 #define R0(a,b,c,d,k,s,t) { \
983 a+=((k)+(t)+F((b),(c),(d))); \
987 #define R1(a,b,c,d,k,s,t) { \
988 a+=((k)+(t)+G((b),(c),(d))); \
992 #define R2(a,b,c,d,k,s,t) { \
993 a+=((k)+(t)+H((b),(c),(d))); \
997 #define R3(a,b,c,d,k,s,t) { \
998 a+=((k)+(t)+I((b),(c),(d))); \
1005 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
1008 #define INIT_DATA_A (unsigned long)0x67452301L
1009 #define INIT_DATA_B (unsigned long)0xefcdab89L
1010 #define INIT_DATA_C (unsigned long)0x98badcfeL
1011 #define INIT_DATA_D (unsigned long)0x10325476L
1013 int MD5_Init(MD5_CTX
*c
)
1025 #ifndef md5_block_host_order
1026 void md5_block_host_order (MD5_CTX
*c
, const void *data
, int num
)
1028 const mDNSu32
*X
=(const mDNSu32
*)data
;
1029 register unsigned MD32_REG_T A
,B
,C
,D
;
1036 for (;num
--;X
+=HASH_LBLOCK
)
1039 R0(A
,B
,C
,D
,X
[ 0], 7,0xd76aa478L
);
1040 R0(D
,A
,B
,C
,X
[ 1],12,0xe8c7b756L
);
1041 R0(C
,D
,A
,B
,X
[ 2],17,0x242070dbL
);
1042 R0(B
,C
,D
,A
,X
[ 3],22,0xc1bdceeeL
);
1043 R0(A
,B
,C
,D
,X
[ 4], 7,0xf57c0fafL
);
1044 R0(D
,A
,B
,C
,X
[ 5],12,0x4787c62aL
);
1045 R0(C
,D
,A
,B
,X
[ 6],17,0xa8304613L
);
1046 R0(B
,C
,D
,A
,X
[ 7],22,0xfd469501L
);
1047 R0(A
,B
,C
,D
,X
[ 8], 7,0x698098d8L
);
1048 R0(D
,A
,B
,C
,X
[ 9],12,0x8b44f7afL
);
1049 R0(C
,D
,A
,B
,X
[10],17,0xffff5bb1L
);
1050 R0(B
,C
,D
,A
,X
[11],22,0x895cd7beL
);
1051 R0(A
,B
,C
,D
,X
[12], 7,0x6b901122L
);
1052 R0(D
,A
,B
,C
,X
[13],12,0xfd987193L
);
1053 R0(C
,D
,A
,B
,X
[14],17,0xa679438eL
);
1054 R0(B
,C
,D
,A
,X
[15],22,0x49b40821L
);
1056 R1(A
,B
,C
,D
,X
[ 1], 5,0xf61e2562L
);
1057 R1(D
,A
,B
,C
,X
[ 6], 9,0xc040b340L
);
1058 R1(C
,D
,A
,B
,X
[11],14,0x265e5a51L
);
1059 R1(B
,C
,D
,A
,X
[ 0],20,0xe9b6c7aaL
);
1060 R1(A
,B
,C
,D
,X
[ 5], 5,0xd62f105dL
);
1061 R1(D
,A
,B
,C
,X
[10], 9,0x02441453L
);
1062 R1(C
,D
,A
,B
,X
[15],14,0xd8a1e681L
);
1063 R1(B
,C
,D
,A
,X
[ 4],20,0xe7d3fbc8L
);
1064 R1(A
,B
,C
,D
,X
[ 9], 5,0x21e1cde6L
);
1065 R1(D
,A
,B
,C
,X
[14], 9,0xc33707d6L
);
1066 R1(C
,D
,A
,B
,X
[ 3],14,0xf4d50d87L
);
1067 R1(B
,C
,D
,A
,X
[ 8],20,0x455a14edL
);
1068 R1(A
,B
,C
,D
,X
[13], 5,0xa9e3e905L
);
1069 R1(D
,A
,B
,C
,X
[ 2], 9,0xfcefa3f8L
);
1070 R1(C
,D
,A
,B
,X
[ 7],14,0x676f02d9L
);
1071 R1(B
,C
,D
,A
,X
[12],20,0x8d2a4c8aL
);
1073 R2(A
,B
,C
,D
,X
[ 5], 4,0xfffa3942L
);
1074 R2(D
,A
,B
,C
,X
[ 8],11,0x8771f681L
);
1075 R2(C
,D
,A
,B
,X
[11],16,0x6d9d6122L
);
1076 R2(B
,C
,D
,A
,X
[14],23,0xfde5380cL
);
1077 R2(A
,B
,C
,D
,X
[ 1], 4,0xa4beea44L
);
1078 R2(D
,A
,B
,C
,X
[ 4],11,0x4bdecfa9L
);
1079 R2(C
,D
,A
,B
,X
[ 7],16,0xf6bb4b60L
);
1080 R2(B
,C
,D
,A
,X
[10],23,0xbebfbc70L
);
1081 R2(A
,B
,C
,D
,X
[13], 4,0x289b7ec6L
);
1082 R2(D
,A
,B
,C
,X
[ 0],11,0xeaa127faL
);
1083 R2(C
,D
,A
,B
,X
[ 3],16,0xd4ef3085L
);
1084 R2(B
,C
,D
,A
,X
[ 6],23,0x04881d05L
);
1085 R2(A
,B
,C
,D
,X
[ 9], 4,0xd9d4d039L
);
1086 R2(D
,A
,B
,C
,X
[12],11,0xe6db99e5L
);
1087 R2(C
,D
,A
,B
,X
[15],16,0x1fa27cf8L
);
1088 R2(B
,C
,D
,A
,X
[ 2],23,0xc4ac5665L
);
1090 R3(A
,B
,C
,D
,X
[ 0], 6,0xf4292244L
);
1091 R3(D
,A
,B
,C
,X
[ 7],10,0x432aff97L
);
1092 R3(C
,D
,A
,B
,X
[14],15,0xab9423a7L
);
1093 R3(B
,C
,D
,A
,X
[ 5],21,0xfc93a039L
);
1094 R3(A
,B
,C
,D
,X
[12], 6,0x655b59c3L
);
1095 R3(D
,A
,B
,C
,X
[ 3],10,0x8f0ccc92L
);
1096 R3(C
,D
,A
,B
,X
[10],15,0xffeff47dL
);
1097 R3(B
,C
,D
,A
,X
[ 1],21,0x85845dd1L
);
1098 R3(A
,B
,C
,D
,X
[ 8], 6,0x6fa87e4fL
);
1099 R3(D
,A
,B
,C
,X
[15],10,0xfe2ce6e0L
);
1100 R3(C
,D
,A
,B
,X
[ 6],15,0xa3014314L
);
1101 R3(B
,C
,D
,A
,X
[13],21,0x4e0811a1L
);
1102 R3(A
,B
,C
,D
,X
[ 4], 6,0xf7537e82L
);
1103 R3(D
,A
,B
,C
,X
[11],10,0xbd3af235L
);
1104 R3(C
,D
,A
,B
,X
[ 2],15,0x2ad7d2bbL
);
1105 R3(B
,C
,D
,A
,X
[ 9],21,0xeb86d391L
);
1115 #ifndef md5_block_data_order
1119 void md5_block_data_order (MD5_CTX
*c
, const void *data_
, int num
)
1121 const unsigned char *data
=data_
;
1122 register unsigned MD32_REG_T A
,B
,C
,D
,l
;
1124 /* See comment in crypto/sha/sha_locl.h for details. */
1125 unsigned MD32_REG_T XX0
, XX1
, XX2
, XX3
, XX4
, XX5
, XX6
, XX7
,
1126 XX8
, XX9
,XX10
,XX11
,XX12
,XX13
,XX14
,XX15
;
1129 mDNSu32 XX
[MD5_LBLOCK
];
1140 HOST_c2l(data
,l
); X( 0)=l
; HOST_c2l(data
,l
); X( 1)=l
;
1142 R0(A
,B
,C
,D
,X( 0), 7,0xd76aa478L
); HOST_c2l(data
,l
); X( 2)=l
;
1143 R0(D
,A
,B
,C
,X( 1),12,0xe8c7b756L
); HOST_c2l(data
,l
); X( 3)=l
;
1144 R0(C
,D
,A
,B
,X( 2),17,0x242070dbL
); HOST_c2l(data
,l
); X( 4)=l
;
1145 R0(B
,C
,D
,A
,X( 3),22,0xc1bdceeeL
); HOST_c2l(data
,l
); X( 5)=l
;
1146 R0(A
,B
,C
,D
,X( 4), 7,0xf57c0fafL
); HOST_c2l(data
,l
); X( 6)=l
;
1147 R0(D
,A
,B
,C
,X( 5),12,0x4787c62aL
); HOST_c2l(data
,l
); X( 7)=l
;
1148 R0(C
,D
,A
,B
,X( 6),17,0xa8304613L
); HOST_c2l(data
,l
); X( 8)=l
;
1149 R0(B
,C
,D
,A
,X( 7),22,0xfd469501L
); HOST_c2l(data
,l
); X( 9)=l
;
1150 R0(A
,B
,C
,D
,X( 8), 7,0x698098d8L
); HOST_c2l(data
,l
); X(10)=l
;
1151 R0(D
,A
,B
,C
,X( 9),12,0x8b44f7afL
); HOST_c2l(data
,l
); X(11)=l
;
1152 R0(C
,D
,A
,B
,X(10),17,0xffff5bb1L
); HOST_c2l(data
,l
); X(12)=l
;
1153 R0(B
,C
,D
,A
,X(11),22,0x895cd7beL
); HOST_c2l(data
,l
); X(13)=l
;
1154 R0(A
,B
,C
,D
,X(12), 7,0x6b901122L
); HOST_c2l(data
,l
); X(14)=l
;
1155 R0(D
,A
,B
,C
,X(13),12,0xfd987193L
); HOST_c2l(data
,l
); X(15)=l
;
1156 R0(C
,D
,A
,B
,X(14),17,0xa679438eL
);
1157 R0(B
,C
,D
,A
,X(15),22,0x49b40821L
);
1159 R1(A
,B
,C
,D
,X( 1), 5,0xf61e2562L
);
1160 R1(D
,A
,B
,C
,X( 6), 9,0xc040b340L
);
1161 R1(C
,D
,A
,B
,X(11),14,0x265e5a51L
);
1162 R1(B
,C
,D
,A
,X( 0),20,0xe9b6c7aaL
);
1163 R1(A
,B
,C
,D
,X( 5), 5,0xd62f105dL
);
1164 R1(D
,A
,B
,C
,X(10), 9,0x02441453L
);
1165 R1(C
,D
,A
,B
,X(15),14,0xd8a1e681L
);
1166 R1(B
,C
,D
,A
,X( 4),20,0xe7d3fbc8L
);
1167 R1(A
,B
,C
,D
,X( 9), 5,0x21e1cde6L
);
1168 R1(D
,A
,B
,C
,X(14), 9,0xc33707d6L
);
1169 R1(C
,D
,A
,B
,X( 3),14,0xf4d50d87L
);
1170 R1(B
,C
,D
,A
,X( 8),20,0x455a14edL
);
1171 R1(A
,B
,C
,D
,X(13), 5,0xa9e3e905L
);
1172 R1(D
,A
,B
,C
,X( 2), 9,0xfcefa3f8L
);
1173 R1(C
,D
,A
,B
,X( 7),14,0x676f02d9L
);
1174 R1(B
,C
,D
,A
,X(12),20,0x8d2a4c8aL
);
1176 R2(A
,B
,C
,D
,X( 5), 4,0xfffa3942L
);
1177 R2(D
,A
,B
,C
,X( 8),11,0x8771f681L
);
1178 R2(C
,D
,A
,B
,X(11),16,0x6d9d6122L
);
1179 R2(B
,C
,D
,A
,X(14),23,0xfde5380cL
);
1180 R2(A
,B
,C
,D
,X( 1), 4,0xa4beea44L
);
1181 R2(D
,A
,B
,C
,X( 4),11,0x4bdecfa9L
);
1182 R2(C
,D
,A
,B
,X( 7),16,0xf6bb4b60L
);
1183 R2(B
,C
,D
,A
,X(10),23,0xbebfbc70L
);
1184 R2(A
,B
,C
,D
,X(13), 4,0x289b7ec6L
);
1185 R2(D
,A
,B
,C
,X( 0),11,0xeaa127faL
);
1186 R2(C
,D
,A
,B
,X( 3),16,0xd4ef3085L
);
1187 R2(B
,C
,D
,A
,X( 6),23,0x04881d05L
);
1188 R2(A
,B
,C
,D
,X( 9), 4,0xd9d4d039L
);
1189 R2(D
,A
,B
,C
,X(12),11,0xe6db99e5L
);
1190 R2(C
,D
,A
,B
,X(15),16,0x1fa27cf8L
);
1191 R2(B
,C
,D
,A
,X( 2),23,0xc4ac5665L
);
1193 R3(A
,B
,C
,D
,X( 0), 6,0xf4292244L
);
1194 R3(D
,A
,B
,C
,X( 7),10,0x432aff97L
);
1195 R3(C
,D
,A
,B
,X(14),15,0xab9423a7L
);
1196 R3(B
,C
,D
,A
,X( 5),21,0xfc93a039L
);
1197 R3(A
,B
,C
,D
,X(12), 6,0x655b59c3L
);
1198 R3(D
,A
,B
,C
,X( 3),10,0x8f0ccc92L
);
1199 R3(C
,D
,A
,B
,X(10),15,0xffeff47dL
);
1200 R3(B
,C
,D
,A
,X( 1),21,0x85845dd1L
);
1201 R3(A
,B
,C
,D
,X( 8), 6,0x6fa87e4fL
);
1202 R3(D
,A
,B
,C
,X(15),10,0xfe2ce6e0L
);
1203 R3(C
,D
,A
,B
,X( 6),15,0xa3014314L
);
1204 R3(B
,C
,D
,A
,X(13),21,0x4e0811a1L
);
1205 R3(A
,B
,C
,D
,X( 4), 6,0xf7537e82L
);
1206 R3(D
,A
,B
,C
,X(11),10,0xbd3af235L
);
1207 R3(C
,D
,A
,B
,X( 2),15,0x2ad7d2bbL
);
1208 R3(B
,C
,D
,A
,X( 9),21,0xeb86d391L
);
1219 // ***************************************************************************
1220 #if COMPILER_LIKES_PRAGMA_MARK
1221 #pragma mark - base64 -> binary conversion
1224 static const char Base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1225 static const char Pad64
= '=';
1228 #define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
1230 mDNSlocal
const char *mDNSstrchr(const char *s
, int c
)
1234 if (c
== *s
) return s
;
1235 if (!*s
) return mDNSNULL
;
1240 // skips all whitespace anywhere.
1241 // converts characters, four at a time, starting at (or after)
1242 // src from base - 64 numbers into three 8 bit bytes in the target area.
1243 // it returns the number of data bytes stored at the target, or -1 on error.
1244 // adapted from BIND sources
1246 mDNSlocal mDNSs32
DNSDigest_Base64ToBin(const char *src
, mDNSu8
*target
, mDNSu32 targsize
)
1248 int tarindex
, state
, ch
;
1254 while ((ch
= *src
++) != '\0') {
1255 if (mDNSisspace(ch
)) /* Skip whitespace anywhere. */
1261 pos
= mDNSstrchr(Base64
, ch
);
1262 if (pos
== 0) /* A non-base64 character. */
1268 if ((mDNSu32
)tarindex
>= targsize
)
1270 target
[tarindex
] = (mDNSu8
)((pos
- Base64
) << 2);
1276 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1278 target
[tarindex
] |= (pos
- Base64
) >> 4;
1279 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x0f) << 4);
1286 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1288 target
[tarindex
] |= (pos
- Base64
) >> 2;
1289 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x03) << 6);
1296 if ((mDNSu32
)tarindex
>= targsize
)
1298 target
[tarindex
] |= (pos
- Base64
);
1309 * We are done decoding Base-64 chars. Let's see if we ended
1310 * on a byte boundary, and/or with erroneous trailing characters.
1313 if (ch
== Pad64
) { /* We got a pad char. */
1314 ch
= *src
++; /* Skip it, get next. */
1316 case 0: /* Invalid = in first position */
1317 case 1: /* Invalid = in second position */
1320 case 2: /* Valid, means one byte of info */
1321 /* Skip any number of spaces. */
1322 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1323 if (!mDNSisspace(ch
))
1325 /* Make sure there is another trailing = sign. */
1328 ch
= *src
++; /* Skip the = */
1329 /* Fall through to "single trailing =" case. */
1332 case 3: /* Valid, means two bytes of info */
1334 * We know this char is an =. Is there anything but
1335 * whitespace after it?
1337 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1338 if (!mDNSisspace(ch
))
1342 * Now make sure for cases 2 and 3 that the "extra"
1343 * bits that slopped past the last full byte were
1344 * zeros. If we don't check them, they become a
1345 * subliminal channel.
1347 if (target
&& target
[tarindex
] != 0)
1352 * We ended by seeing the end of the string. Make sure we
1353 * have no partial bytes lying around.
1363 // ***************************************************************************
1364 #if COMPILER_LIKES_PRAGMA_MARK
1365 #pragma mark - API exported to mDNS Core
1369 #define HMAC_IPAD 0x36
1370 #define HMAC_OPAD 0x5c
1373 #define HMAC_MD5_AlgName (*(const domainname*) "\010" "hmac-md5" "\007" "sig-alg" "\003" "reg" "\003" "int")
1375 // Adapted from Appendix, RFC 2104
1376 mDNSlocal
void DNSDigest_ConstructHMACKey(DomainAuthInfo
*info
, const mDNSu8
*key
, mDNSu32 len
)
1379 mDNSu8 buf
[MD5_LEN
];
1382 // If key is longer than HMAC_LEN reset it to MD5(key)
1386 MD5_Update(&k
, key
, len
);
1392 // store key in pads
1393 mDNSPlatformMemZero(info
->keydata_ipad
, HMAC_LEN
);
1394 mDNSPlatformMemZero(info
->keydata_opad
, HMAC_LEN
);
1395 mDNSPlatformMemCopy(info
->keydata_ipad
, key
, len
);
1396 mDNSPlatformMemCopy(info
->keydata_opad
, key
, len
);
1398 // XOR key with ipad and opad values
1399 for (i
= 0; i
< HMAC_LEN
; i
++)
1401 info
->keydata_ipad
[i
] ^= HMAC_IPAD
;
1402 info
->keydata_opad
[i
] ^= HMAC_OPAD
;
1407 mDNSexport mDNSs32
DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo
*info
, const char *b64key
)
1409 mDNSu8 keybuf
[1024];
1410 mDNSs32 keylen
= DNSDigest_Base64ToBin(b64key
, keybuf
, sizeof(keybuf
));
1411 if (keylen
< 0) return(keylen
);
1412 DNSDigest_ConstructHMACKey(info
, keybuf
, (mDNSu32
)keylen
);
1416 mDNSexport
void DNSDigest_SignMessage(DNSMessage
*msg
, mDNSu8
**end
, DomainAuthInfo
*info
, mDNSu16 tcode
)
1419 mDNSu8
*rdata
, *const countPtr
= (mDNSu8
*)&msg
->h
.numAdditionals
; // Get existing numAdditionals value
1422 mDNSu8 digest
[MD5_LEN
];
1427 mDNSu16 numAdditionals
= (mDNSu16
)((mDNSu16
)countPtr
[0] << 8 | countPtr
[1]);
1429 // Init MD5 context, digest inner key pad and message
1431 MD5_Update(&c
, info
->keydata_ipad
, HMAC_LEN
);
1432 MD5_Update(&c
, (mDNSu8
*)msg
, (unsigned long)(*end
- (mDNSu8
*)msg
));
1434 // Construct TSIG RR, digesting variables as apporpriate
1435 mDNS_SetupResourceRecord(&tsig
, mDNSNULL
, 0, kDNSType_TSIG
, 0, kDNSRecordTypeKnownUnique
, mDNSNULL
, mDNSNULL
);
1438 AssignDomainName(&tsig
.namestorage
, &info
->keyname
);
1439 MD5_Update(&c
, info
->keyname
.c
, DomainNameLength(&info
->keyname
));
1442 tsig
.resrec
.rrclass
= kDNSQClass_ANY
;
1443 buf
= mDNSOpaque16fromIntVal(kDNSQClass_ANY
);
1444 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1447 tsig
.resrec
.rroriginalttl
= 0;
1448 MD5_Update(&c
, (mDNSu8
*)&tsig
.resrec
.rroriginalttl
, sizeof(tsig
.resrec
.rroriginalttl
));
1451 AssignDomainName(&tsig
.resrec
.rdata
->u
.name
, &HMAC_MD5_AlgName
);
1452 len
= DomainNameLength(&HMAC_MD5_AlgName
);
1453 rdata
= tsig
.resrec
.rdata
->u
.data
+ len
;
1454 MD5_Update(&c
, HMAC_MD5_AlgName
.c
, len
);
1457 // get UTC (universal time), convert to 48-bit unsigned in network byte order
1458 utc32
= (mDNSu32
)mDNSPlatformUTC();
1459 if (utc32
== (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); *end
= mDNSNULL
; }
1462 utc48
[2] = (mDNSu8
)((utc32
>> 24) & 0xff);
1463 utc48
[3] = (mDNSu8
)((utc32
>> 16) & 0xff);
1464 utc48
[4] = (mDNSu8
)((utc32
>> 8) & 0xff);
1465 utc48
[5] = (mDNSu8
)( utc32
& 0xff);
1467 mDNSPlatformMemCopy(rdata
, utc48
, 6);
1469 MD5_Update(&c
, utc48
, 6);
1471 // 300 sec is fudge recommended in RFC 2485
1472 rdata
[0] = (mDNSu8
)((300 >> 8) & 0xff);
1473 rdata
[1] = (mDNSu8
)( 300 & 0xff);
1474 MD5_Update(&c
, rdata
, sizeof(mDNSOpaque16
));
1475 rdata
+= sizeof(mDNSOpaque16
);
1477 // digest error (tcode) and other data len (zero) - we'll add them to the rdata later
1478 buf
.b
[0] = (mDNSu8
)((tcode
>> 8) & 0xff);
1479 buf
.b
[1] = (mDNSu8
)( tcode
& 0xff);
1480 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // error
1481 buf
.NotAnInteger
= 0;
1482 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // other data len
1484 // finish the message & tsig var hash
1485 MD5_Final(digest
, &c
);
1487 // perform outer MD5 (outer key pad, inner digest)
1489 MD5_Update(&c
, info
->keydata_opad
, HMAC_LEN
);
1490 MD5_Update(&c
, digest
, MD5_LEN
);
1491 MD5_Final(digest
, &c
);
1493 // set remaining rdata fields
1494 rdata
[0] = (mDNSu8
)((MD5_LEN
>> 8) & 0xff);
1495 rdata
[1] = (mDNSu8
)( MD5_LEN
& 0xff);
1496 rdata
+= sizeof(mDNSOpaque16
);
1497 mDNSPlatformMemCopy(rdata
, digest
, MD5_LEN
); // MAC
1499 rdata
[0] = msg
->h
.id
.b
[0]; // original ID
1500 rdata
[1] = msg
->h
.id
.b
[1];
1501 rdata
[2] = (mDNSu8
)((tcode
>> 8) & 0xff);
1502 rdata
[3] = (mDNSu8
)( tcode
& 0xff);
1503 rdata
[4] = 0; // other data len
1507 tsig
.resrec
.rdlength
= (mDNSu16
)(rdata
- tsig
.resrec
.rdata
->u
.data
);
1508 *end
= PutResourceRecordTTLJumbo(msg
, ptr
, &numAdditionals
, &tsig
.resrec
, 0);
1509 if (!*end
) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); *end
= mDNSNULL
; return; }
1511 // Write back updated numAdditionals value
1512 countPtr
[0] = (mDNSu8
)(numAdditionals
>> 8);
1513 countPtr
[1] = (mDNSu8
)(numAdditionals
& 0xFF);
1516 mDNSexport mDNSBool
DNSDigest_VerifyMessage(DNSMessage
*msg
, mDNSu8
*end
, LargeCacheRecord
* lcr
, DomainAuthInfo
*info
, mDNSu16
* rcode
, mDNSu16
* tcode
)
1518 mDNSu8
* ptr
= (mDNSu8
*) &lcr
->r
.resrec
.rdata
->u
.data
;
1521 mDNSu8 thisDigest
[MD5_LEN
];
1522 mDNSu8 thatDigest
[MD5_LEN
];
1530 mDNSBool ok
= mDNSfalse
;
1532 // We only support HMAC-MD5 for now
1534 algo
= (domainname
*) ptr
;
1536 if (!SameDomainName(algo
, &HMAC_MD5_AlgName
))
1538 LogMsg("ERROR: DNSDigest_VerifyMessage - TSIG algorithm not supported: %##s", algo
->c
);
1539 *rcode
= kDNSFlag1_RC_NotAuth
;
1540 *tcode
= TSIG_ErrBadKey
;
1545 ptr
+= DomainNameLength(algo
);
1549 now
= mDNSPlatformUTC();
1552 LogMsg("ERROR: DNSDigest_VerifyMessage - mDNSPlatformUTC returned bad time -1");
1553 *rcode
= kDNSFlag1_RC_NotAuth
;
1554 *tcode
= TSIG_ErrBadTime
;
1559 // Get the 48 bit time field, skipping over the first word
1568 then
= (mDNSs32
)NToH32(utc48
+ sizeof(mDNSu16
));
1570 fudge
= NToH16(ptr
);
1572 ptr
+= sizeof(mDNSu16
);
1574 delta
= (now
> then
) ? now
- then
: then
- now
;
1578 LogMsg("ERROR: DNSDigest_VerifyMessage - time skew > %d", fudge
);
1579 *rcode
= kDNSFlag1_RC_NotAuth
;
1580 *tcode
= TSIG_ErrBadTime
;
1587 macsize
= (mDNSu32
) NToH16(ptr
);
1589 ptr
+= sizeof(mDNSu16
);
1593 mDNSPlatformMemCopy(thatDigest
, ptr
, MD5_LEN
);
1595 // Init MD5 context, digest inner key pad and message
1598 MD5_Update(&c
, info
->keydata_ipad
, HMAC_LEN
);
1599 MD5_Update(&c
, (mDNSu8
*) msg
, (unsigned long)(end
- (mDNSu8
*) msg
));
1603 MD5_Update(&c
, lcr
->r
.resrec
.name
->c
, DomainNameLength(lcr
->r
.resrec
.name
));
1607 buf
= mDNSOpaque16fromIntVal(lcr
->r
.resrec
.rrclass
);
1608 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1612 MD5_Update(&c
, (mDNSu8
*) &lcr
->r
.resrec
.rroriginalttl
, sizeof(lcr
->r
.resrec
.rroriginalttl
));
1616 MD5_Update(&c
, algo
->c
, DomainNameLength(algo
));
1620 MD5_Update(&c
, utc48
, 6);
1624 buf
= mDNSOpaque16fromIntVal(fudge
);
1625 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1627 // Digest error and other data len (both zero) - we'll add them to the rdata later
1629 buf
.NotAnInteger
= 0;
1630 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // error
1631 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // other data len
1633 // Finish the message & tsig var hash
1635 MD5_Final(thisDigest
, &c
);
1637 // perform outer MD5 (outer key pad, inner digest)
1640 MD5_Update(&c
, info
->keydata_opad
, HMAC_LEN
);
1641 MD5_Update(&c
, thisDigest
, MD5_LEN
);
1642 MD5_Final(thisDigest
, &c
);
1644 if (!mDNSPlatformMemSame(thisDigest
, thatDigest
, MD5_LEN
))
1646 LogMsg("ERROR: DNSDigest_VerifyMessage - bad signature");
1647 *rcode
= kDNSFlag1_RC_NotAuth
;
1648 *tcode
= TSIG_ErrBadSig
;
1653 // set remaining rdata fields