2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
26 Revision 1.13 2004/12/16 20:12:59 cheshire
27 <rdar://problem/3324626> Cache memory management improvements
29 Revision 1.12 2004/12/03 07:20:50 ksekar
30 <rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
32 Revision 1.11 2004/12/02 01:10:27 cheshire
33 Fix to compile cleanly on 64-bit x86
35 Revision 1.10 2004/11/01 20:36:04 ksekar
36 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
38 Revision 1.9 2004/10/26 09:00:12 cheshire
39 Save a few bytes by creating HMAC_MD5_AlgName as a C string instead of a 256-byte object
41 Revision 1.8 2004/09/17 01:08:48 cheshire
42 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
43 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
44 declared in that file are ONLY appropriate to single-address-space embedded applications.
45 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
47 Revision 1.7 2004/08/15 18:36:38 cheshire
48 Don't use strcpy() and strlen() on "struct domainname" objects;
49 use AssignDomainName() and DomainNameLength() instead
50 (A "struct domainname" is a collection of packed pascal strings, not a C string.)
52 Revision 1.6 2004/06/02 00:17:46 ksekar
53 Referenced original OpenSSL license headers in source file description.
55 Revision 1.5 2004/05/20 18:37:37 cheshire
58 Revision 1.4 2004/04/22 20:28:20 cheshire
59 Use existing facility of PutResourceRecordTTL() to update count field for us
61 Revision 1.3 2004/04/22 03:05:28 cheshire
62 kDNSClass_ANY should be kDNSQClass_ANY
64 Revision 1.2 2004/04/15 00:51:28 bradley
65 Minor tweaks for Windows and C++ builds. Added casts for signed/unsigned integers and 64-bit pointers.
66 Prefix some functions with mDNS to avoid conflicts. Disable benign warnings on Microsoft compilers.
68 Revision 1.1 2004/04/14 23:09:28 ksekar
69 Support for TSIG signed dynamic updates.
80 #include "mDNSEmbeddedAPI.h"
81 #include "DNSCommon.h"
83 // Disable certain benign warnings with Microsoft compilers
84 #if(defined(_MSC_VER))
85 // Disable "conditional expression is constant" warning for debug macros.
86 // Otherwise, this generates warnings for the perfectly natural construct "while(1)"
87 // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
88 #pragma warning(disable:4127)
91 // ***************************************************************************
92 #if COMPILER_LIKES_PRAGMA_MARK
93 #pragma mark - MD5 Hash Functions
97 /* The source for the has is derived CommonCrypto files CommonDigest.h, md32_common.h, md5_locl.h, md5_locl.h, and openssl/md5.h.
98 * The following changes have been made to the original sources:
99 * replaced CC_LONG w/ mDNSu32
100 * replaced CC_MD5* with MD5*
101 * replaced CC_LONG w/ mDNSu32, removed conditional #defines from md5.h
102 * removed extern decls for MD5_Init/Update/Final from CommonDigest.h
103 * removed APPLE_COMMON_DIGEST specific #defines from md5_locl.h
105 * Note: machine archetecure specific conditionals from the original sources are turned off, but are left in the code
106 * to aid in platform-specific optimizations and debugging.
107 * Sources originally distributed under the following license headers:
108 * CommonDigest.c - APSL
111 * ====================================================================
112 * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
114 * Redistribution and use in source and binary forms, with or without
115 * modification, are permitted provided that the following conditions
118 * 1. Redistributions of source code must retain the above copyright
119 * notice, this list of conditions and the following disclaimer.
121 * 2. Redistributions in binary form must reproduce the above copyright
122 * notice, this list of conditions and the following disclaimer in
123 * the documentation and/or other materials provided with the
126 * 3. All advertising materials mentioning features or use of this
127 * software must display the following acknowledgment:
128 * "This product includes software developed by the OpenSSL Project
129 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
131 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
132 * endorse or promote products derived from this software without
133 * prior written permission. For written permission, please contact
134 * licensing@OpenSSL.org.
136 * 5. Products derived from this software may not be called "OpenSSL"
137 * nor may "OpenSSL" appear in their names without prior written
138 * permission of the OpenSSL Project.
140 * 6. Redistributions of any form whatsoever must retain the following
142 * "This product includes software developed by the OpenSSL Project
143 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
145 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
146 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
147 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
148 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
149 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
150 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
151 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
152 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
153 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
154 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
155 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
156 * OF THE POSSIBILITY OF SUCH DAMAGE.
159 * md5_dgst.c, md5_locl.h
160 * ====================================================================
162 * This product includes cryptographic software written by Eric Young
163 * (eay@cryptsoft.com). This product includes software written by Tim
164 * Hudson (tjh@cryptsoft.com).
166 * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
167 * All rights reserved.
169 * This package is an SSL implementation written
170 * by Eric Young (eay@cryptsoft.com).
171 * The implementation was written so as to conform with Netscapes SSL.
173 * This library is free for commercial and non-commercial use as long as
174 * the following conditions are aheared to. The following conditions
175 * apply to all code found in this distribution, be it the RC4, RSA,
176 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
177 * included with this distribution is covered by the same copyright terms
178 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
180 * Copyright remains Eric Young's, and as such any Copyright notices in
181 * the code are not to be removed.
182 * If this package is used in a product, Eric Young should be given attribution
183 * as the author of the parts of the library used.
184 * This can be in the form of a textual message at program startup or
185 * in documentation (online or textual) provided with the package.
187 * Redistribution and use in source and binary forms, with or without
188 * modification, are permitted provided that the following conditions
190 * 1. Redistributions of source code must retain the copyright
191 * notice, this list of conditions and the following disclaimer.
192 * 2. Redistributions in binary form must reproduce the above copyright
193 * notice, this list of conditions and the following disclaimer in the
194 * documentation and/or other materials provided with the distribution.
195 * 3. All advertising materials mentioning features or use of this software
196 * must display the following acknowledgement:
197 * "This product includes cryptographic software written by
198 * Eric Young (eay@cryptsoft.com)"
199 * The word 'cryptographic' can be left out if the rouines from the library
200 * being used are not cryptographic related :-).
201 * 4. If you include any Windows specific code (or a derivative thereof) from
202 * the apps directory (application code) you must include an acknowledgement:
203 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
205 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
206 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
207 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
208 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
209 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
211 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
213 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
214 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
217 * The licence and distribution terms for any publically available version or
218 * derivative of this code cannot be changed. i.e. this code cannot simply be
219 * copied and put under another distribution licence
220 * [including the GNU Public Licence.]
224 //from CommonDigest.h
226 #define MD5_DIGEST_LENGTH 16 /* digest length in bytes */
227 #define MD5_BLOCK_BYTES 64 /* block size in bytes */
228 #define MD5_BLOCK_LONG (MD5_BLOCK_BYTES / sizeof(mDNSu32))
230 typedef struct MD5state_st
234 mDNSu32 data
[MD5_BLOCK_LONG
];
239 // from openssl/md5.h
241 #define MD5_CBLOCK 64
242 #define MD5_LBLOCK (MD5_CBLOCK/4)
243 #define MD5_DIGEST_LENGTH 16
245 int MD5_Init(MD5_CTX
*c
);
246 int MD5_Update(MD5_CTX
*c
, const void *data
, unsigned long len
);
247 int MD5_Final(unsigned char *md
, MD5_CTX
*c
);
248 void MD5_Transform(MD5_CTX
*c
, const unsigned char *b
);
252 #ifndef MD5_LONG_LOG2
253 #define MD5_LONG_LOG2 2 /* default to 32 bits */
257 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
258 # define md5_block_host_order md5_block_asm_host_order
259 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
260 void md5_block_asm_data_order_aligned (MD5_CTX
*c
, const mDNSu32
*p
,int num
);
261 # define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned
265 void md5_block_host_order (MD5_CTX
*c
, const void *p
,int num
);
266 void md5_block_data_order (MD5_CTX
*c
, const void *p
,int num
);
268 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
270 * *_block_host_order is expected to handle aligned data while
271 * *_block_data_order - unaligned. As algorithm and host (x86)
272 * are in this case of the same "endianness" these two are
273 * otherwise indistinguishable. But normally you don't want to
274 * call the same function because unaligned access in places
275 * where alignment is expected is usually a "Bad Thing". Indeed,
276 * on RISCs you get punished with BUS ERROR signal or *severe*
277 * performance degradation. Intel CPUs are in turn perfectly
278 * capable of loading unaligned data without such drastic side
279 * effect. Yes, they say it's slower than aligned load, but no
280 * exception is generated and therefore performance degradation
281 * is *incomparable* with RISCs. What we should weight here is
282 * costs of unaligned access against costs of aligning data.
283 * According to my measurements allowing unaligned access results
284 * in ~9% performance improvement on Pentium II operating at
285 * 266MHz. I won't be surprised if the difference will be higher
286 * on faster systems:-)
288 * <appro@fy.chalmers.se>
290 #define md5_block_data_order md5_block_host_order
293 #define DATA_ORDER_IS_LITTLE_ENDIAN
295 #define HASH_LONG mDNSu32
296 #define HASH_LONG_LOG2 MD5_LONG_LOG2
297 #define HASH_CTX MD5_CTX
298 #define HASH_CBLOCK MD5_CBLOCK
299 #define HASH_LBLOCK MD5_LBLOCK
301 #define HASH_UPDATE MD5_Update
302 #define HASH_TRANSFORM MD5_Transform
303 #define HASH_FINAL MD5_Final
305 #define HASH_MAKE_STRING(c,s) do { \
307 ll=(c)->A; HOST_l2c(ll,(s)); \
308 ll=(c)->B; HOST_l2c(ll,(s)); \
309 ll=(c)->C; HOST_l2c(ll,(s)); \
310 ll=(c)->D; HOST_l2c(ll,(s)); \
312 #define HASH_BLOCK_HOST_ORDER md5_block_host_order
313 #if !defined(L_ENDIAN) || defined(md5_block_data_order)
314 #define HASH_BLOCK_DATA_ORDER md5_block_data_order
316 * Little-endians (Intel and Alpha) feel better without this.
317 * It looks like memcpy does better job than generic
318 * md5_block_data_order on copying-n-aligning input data.
319 * But frankly speaking I didn't expect such result on Alpha.
320 * On the other hand I've got this with egcs-1.0.2 and if
321 * program is compiled with another (better?) compiler it
322 * might turn out other way around.
324 * <appro@fy.chalmers.se>
329 // from md32_common.h
332 * This is a generic 32 bit "collector" for message digest algorithms.
333 * Whenever needed it collects input character stream into chunks of
334 * 32 bit values and invokes a block function that performs actual hash
341 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
342 * this macro defines byte order of input stream.
344 * size of a unit chunk HASH_BLOCK operates on.
346 * has to be at lest 32 bit wide, if it's wider, then
347 * HASH_LONG_LOG2 *has to* be defined along
349 * context structure that at least contains following
354 * HASH_LONG data[HASH_LBLOCK];
359 * name of "Update" function, implemented here.
361 * name of "Transform" function, implemented here.
363 * name of "Final" function, implemented here.
364 * HASH_BLOCK_HOST_ORDER
365 * name of "block" function treating *aligned* input message
366 * in host byte order, implemented externally.
367 * HASH_BLOCK_DATA_ORDER
368 * name of "block" function treating *unaligned* input message
369 * in original (data) byte order, implemented externally (it
370 * actually is optional if data and host are of the same
373 * macro convering context variables to an ASCII hash string.
377 * B_ENDIAN or L_ENDIAN
378 * defines host byte-order.
380 * defaults to 2 if not states otherwise.
382 * assumed to be HASH_CBLOCK/4 if not stated otherwise.
383 * HASH_BLOCK_DATA_ORDER_ALIGNED
384 * alternative "block" function capable of treating
385 * aligned input message in original (data) order,
386 * implemented externally.
390 * #define DATA_ORDER_IS_LITTLE_ENDIAN
392 * #define HASH_LONG mDNSu32
393 * #define HASH_LONG_LOG2 mDNSu32_LOG2
394 * #define HASH_CTX MD5_CTX
395 * #define HASH_CBLOCK MD5_CBLOCK
396 * #define HASH_LBLOCK MD5_LBLOCK
397 * #define HASH_UPDATE MD5_Update
398 * #define HASH_TRANSFORM MD5_Transform
399 * #define HASH_FINAL MD5_Final
400 * #define HASH_BLOCK_HOST_ORDER md5_block_host_order
401 * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
403 * <appro@fy.chalmers.se>
406 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
407 #error "DATA_ORDER must be defined!"
411 #error "HASH_CBLOCK must be defined!"
414 #error "HASH_LONG must be defined!"
417 #error "HASH_CTX must be defined!"
421 #error "HASH_UPDATE must be defined!"
423 #ifndef HASH_TRANSFORM
424 #error "HASH_TRANSFORM must be defined!"
427 #error "HASH_FINAL must be defined!"
430 #ifndef HASH_BLOCK_HOST_ORDER
431 #error "HASH_BLOCK_HOST_ORDER must be defined!"
436 * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
439 #ifndef HASH_BLOCK_DATA_ORDER
440 #error "HASH_BLOCK_DATA_ORDER must be defined!"
445 #define HASH_LBLOCK (HASH_CBLOCK/4)
448 #ifndef HASH_LONG_LOG2
449 #define HASH_LONG_LOG2 2
453 * Engage compiler specific rotate intrinsic function if available.
457 # if 0 /* defined(_MSC_VER) */
458 # define ROTATE(a,n) _lrotl(a,n)
459 # elif defined(__MWERKS__)
460 # if defined(__POWERPC__)
461 # define ROTATE(a,n) (unsigned MD32_REG_T)__rlwinm((int)a,n,0,31)
462 # elif defined(__MC68K__)
463 /* Motorola specific tweak. <appro@fy.chalmers.se> */
464 # define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) )
466 # define ROTATE(a,n) __rol(a,n)
468 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
470 * Some GNU C inline assembler templates. Note that these are
471 * rotates by *constant* number of bits! But that's exactly
472 * what we need here...
474 * <appro@fy.chalmers.se>
476 # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
477 # define ROTATE(a,n) ({ register unsigned int ret; \
485 # elif defined(__powerpc) || defined(__ppc)
486 # define ROTATE(a,n) ({ register unsigned int ret; \
488 "rlwinm %0,%1,%2,0,31" \
497 * Engage compiler specific "fetch in reverse byte order"
498 * intrinsic function if available.
500 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
501 /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
502 # if (defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)) && !defined(I386_ONLY)
503 # define BE_FETCH32(a) ({ register unsigned int l=(a);\
506 : "=r"(l) : "0"(l)); \
509 # elif defined(__powerpc)
510 # define LE_FETCH32(a) ({ register unsigned int l; \
518 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
519 # define LE_FETCH32(a) ({ register unsigned int l; \
521 "lda [%1]#ASI_PRIMARY_LITTLE,%0"\
528 #endif /* PEDANTIC */
530 #if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */
531 /* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
533 /* 5 instructions with rotate instruction, else 9 */
534 #define REVERSE_FETCH32(a,l) ( \
535 l=*(const HASH_LONG *)(a), \
536 ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \
539 /* 6 instructions with rotate instruction, else 8 */
540 #define REVERSE_FETCH32(a,l) ( \
541 l=*(const HASH_LONG *)(a), \
542 l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \
546 * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
547 * It's rewritten as above for two reasons:
548 * - RISCs aren't good at long constants and have to explicitely
549 * compose 'em with several (well, usually 2) instructions in a
550 * register before performing the actual operation and (as you
551 * already realized:-) having same constant should inspire the
552 * compiler to permanently allocate the only register for it;
553 * - most modern CPUs have two ALUs, but usually only one has
554 * circuitry for shifts:-( this minor tweak inspires compiler
555 * to schedule shift instructions in a better way...
557 * <appro@fy.chalmers.se>
563 #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
567 * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
568 * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
569 * and host are of the same "endianess". It's possible to mask
570 * this with blank #define HASH_BLOCK_DATA_ORDER though...
572 * <appro@fy.chalmers.se>
574 #if defined(B_ENDIAN)
575 # if defined(DATA_ORDER_IS_BIG_ENDIAN)
576 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
577 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
579 # elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
580 # ifndef HOST_FETCH32
582 # define HOST_FETCH32(p,l) LE_FETCH32(p)
583 # elif defined(REVERSE_FETCH32)
584 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
588 #elif defined(L_ENDIAN)
589 # if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
590 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
591 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
593 # elif defined(DATA_ORDER_IS_BIG_ENDIAN)
594 # ifndef HOST_FETCH32
596 # define HOST_FETCH32(p,l) BE_FETCH32(p)
597 # elif defined(REVERSE_FETCH32)
598 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
604 #if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
605 #ifndef HASH_BLOCK_DATA_ORDER
606 #error "HASH_BLOCK_DATA_ORDER must be defined!"
610 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
612 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
613 l|=(((unsigned long)(*((c)++)))<<16), \
614 l|=(((unsigned long)(*((c)++)))<< 8), \
615 l|=(((unsigned long)(*((c)++))) ), \
617 #define HOST_p_c2l(c,l,n) { \
619 case 0: l =((unsigned long)(*((c)++)))<<24; \
620 case 1: l|=((unsigned long)(*((c)++)))<<16; \
621 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
622 case 3: l|=((unsigned long)(*((c)++))); \
624 #define HOST_p_c2l_p(c,l,sc,len) { \
626 case 0: l =((unsigned long)(*((c)++)))<<24; \
627 if (--len == 0) break; \
628 case 1: l|=((unsigned long)(*((c)++)))<<16; \
629 if (--len == 0) break; \
630 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
632 /* NOTE the pointer is not incremented at the end of this */
633 #define HOST_c2l_p(c,l,n) { \
636 case 3: l =((unsigned long)(*(--(c))))<< 8; \
637 case 2: l|=((unsigned long)(*(--(c))))<<16; \
638 case 1: l|=((unsigned long)(*(--(c))))<<24; \
640 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
641 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
642 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
643 *((c)++)=(unsigned char)(((l) )&0xff), \
646 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
648 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
649 l|=(((unsigned long)(*((c)++)))<< 8), \
650 l|=(((unsigned long)(*((c)++)))<<16), \
651 l|=(((unsigned long)(*((c)++)))<<24), \
653 #define HOST_p_c2l(c,l,n) { \
655 case 0: l =((unsigned long)(*((c)++))); \
656 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
657 case 2: l|=((unsigned long)(*((c)++)))<<16; \
658 case 3: l|=((unsigned long)(*((c)++)))<<24; \
660 #define HOST_p_c2l_p(c,l,sc,len) { \
662 case 0: l =((unsigned long)(*((c)++))); \
663 if (--len == 0) break; \
664 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
665 if (--len == 0) break; \
666 case 2: l|=((unsigned long)(*((c)++)))<<16; \
668 /* NOTE the pointer is not incremented at the end of this */
669 #define HOST_c2l_p(c,l,n) { \
672 case 3: l =((unsigned long)(*(--(c))))<<16; \
673 case 2: l|=((unsigned long)(*(--(c))))<< 8; \
674 case 1: l|=((unsigned long)(*(--(c)))); \
676 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
677 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
678 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
679 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
685 * Time for some action:-)
688 int HASH_UPDATE (HASH_CTX
*c
, const void *data_
, unsigned long len
)
690 const unsigned char *data
=(const unsigned char *)data_
;
691 register HASH_LONG
* p
;
692 register unsigned long l
;
695 if (len
==0) return 1;
697 l
=(c
->Nl
+(len
<<3))&0xffffffffL
;
698 /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
699 * Wei Dai <weidai@eskimo.com> for pointing it out. */
700 if (l
< c
->Nl
) /* overflow */
711 if ((c
->num
+len
) >= HASH_CBLOCK
)
713 l
=p
[sw
]; HOST_p_c2l(data
,l
,sc
); p
[sw
++]=l
;
714 for (; sw
<HASH_LBLOCK
; sw
++)
716 HOST_c2l(data
,l
); p
[sw
]=l
;
718 HASH_BLOCK_HOST_ORDER (c
,p
,1);
719 len
-=(HASH_CBLOCK
-c
->num
);
721 /* drop through and do the rest */
726 if ((sc
+len
) < 4) /* ugly, add char's to a word */
728 l
=p
[sw
]; HOST_p_c2l_p(data
,l
,sc
,len
); p
[sw
]=l
;
736 HOST_p_c2l(data
,l
,sc
);
738 for (; sw
< ew
; sw
++)
740 HOST_c2l(data
,l
); p
[sw
]=l
;
744 HOST_c2l_p(data
,l
,ec
); p
[sw
]=l
;
751 sw
=(int)(len
/HASH_CBLOCK
);
754 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
756 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
757 * only if sizeof(HASH_LONG)==4.
759 if ((((unsigned long)data
)%4
) == 0)
761 /* data is properly aligned so that we can cast it: */
762 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,(HASH_LONG
*)data
,sw
);
768 #if !defined(HASH_BLOCK_DATA_ORDER)
771 memcpy (p
=c
->data
,data
,HASH_CBLOCK
);
772 HASH_BLOCK_DATA_ORDER_ALIGNED(c
,p
,1);
778 #if defined(HASH_BLOCK_DATA_ORDER)
780 HASH_BLOCK_DATA_ORDER(c
,data
,sw
);
792 ew
=(int)(len
>>2); /* words to copy */
796 HOST_c2l(data
,l
); *p
=l
;
798 HOST_c2l_p(data
,l
,ec
);
805 void HASH_TRANSFORM (HASH_CTX
*c
, const unsigned char *data
)
807 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
808 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
,1);
812 #if !defined(HASH_BLOCK_DATA_ORDER)
814 memcpy (c
->data
,data
,HASH_CBLOCK
);
815 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,c
->data
,1);
819 #if defined(HASH_BLOCK_DATA_ORDER)
820 HASH_BLOCK_DATA_ORDER (c
,data
,1);
825 int HASH_FINAL (unsigned char *md
, HASH_CTX
*c
)
827 register HASH_LONG
*p
;
828 register unsigned long l
;
830 static const unsigned char end
[4]={0x80,0x00,0x00,0x00};
831 const unsigned char *cp
=end
;
833 /* c->num should definitly have room for at least one more byte. */
839 /* purify often complains about the following line as an
840 * Uninitialized Memory Read. While this can be true, the
841 * following p_c2l macro will reset l when that case is true.
842 * This is because j&0x03 contains the number of 'valid' bytes
843 * already in p[i]. If and only if j&0x03 == 0, the UMR will
844 * occur but this is also the only time p_c2l will do
845 * l= *(cp++) instead of l|= *(cp++)
846 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
849 if (j
==0) p
[i
]=0; /* Yeah, but that's not the way to fix it:-) */
853 l
= (j
==0) ? 0 : p
[i
];
855 HOST_p_c2l(cp
,l
,j
); p
[i
++]=l
; /* i is the next 'undefined word' */
857 if (i
>(HASH_LBLOCK
-2)) /* save room for Nl and Nh */
859 if (i
<HASH_LBLOCK
) p
[i
]=0;
860 HASH_BLOCK_HOST_ORDER (c
,p
,1);
863 for (; i
<(HASH_LBLOCK
-2); i
++)
866 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
867 p
[HASH_LBLOCK
-2]=c
->Nh
;
868 p
[HASH_LBLOCK
-1]=c
->Nl
;
869 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
870 p
[HASH_LBLOCK
-2]=c
->Nl
;
871 p
[HASH_LBLOCK
-1]=c
->Nh
;
873 HASH_BLOCK_HOST_ORDER (c
,p
,1);
875 #ifndef HASH_MAKE_STRING
876 #error "HASH_MAKE_STRING must be defined!"
878 HASH_MAKE_STRING(c
,md
);
882 /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
883 * but I'm not worried :-)
884 OPENSSL_cleanse((void *)c,sizeof(HASH_CTX));
890 #define MD32_REG_T long
892 * This comment was originaly written for MD5, which is why it
893 * discusses A-D. But it basically applies to all 32-bit digests,
894 * which is why it was moved to common header file.
896 * In case you wonder why A-D are declared as long and not
897 * as mDNSu32. Doing so results in slight performance
898 * boost on LP64 architectures. The catch is we don't
899 * really care if 32 MSBs of a 64-bit register get polluted
900 * with eventual overflows as we *save* only 32 LSBs in
901 * *either* case. Now declaring 'em long excuses the compiler
902 * from keeping 32 MSBs zeroed resulting in 13% performance
903 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
904 * Well, to be honest it should say that this *prevents*
905 * performance degradation.
906 * <appro@fy.chalmers.se>
907 * Apparently there're LP64 compilers that generate better
908 * code if A-D are declared int. Most notably GCC-x86_64
909 * generates better code.
910 * <appro@fy.chalmers.se>
915 // from md5_locl.h (continued)
918 #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
919 #define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
922 /* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
923 * simplified to the code below. Wei attributes these optimizations
924 * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
926 #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
927 #define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c))
928 #define H(b,c,d) ((b) ^ (c) ^ (d))
929 #define I(b,c,d) (((~(d)) | (b)) ^ (c))
931 #define R0(a,b,c,d,k,s,t) { \
932 a+=((k)+(t)+F((b),(c),(d))); \
936 #define R1(a,b,c,d,k,s,t) { \
937 a+=((k)+(t)+G((b),(c),(d))); \
941 #define R2(a,b,c,d,k,s,t) { \
942 a+=((k)+(t)+H((b),(c),(d))); \
946 #define R3(a,b,c,d,k,s,t) { \
947 a+=((k)+(t)+I((b),(c),(d))); \
954 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
957 #define INIT_DATA_A (unsigned long)0x67452301L
958 #define INIT_DATA_B (unsigned long)0xefcdab89L
959 #define INIT_DATA_C (unsigned long)0x98badcfeL
960 #define INIT_DATA_D (unsigned long)0x10325476L
962 int MD5_Init(MD5_CTX
*c
)
974 #ifndef md5_block_host_order
975 void md5_block_host_order (MD5_CTX
*c
, const void *data
, int num
)
977 const mDNSu32
*X
=(const mDNSu32
*)data
;
978 register unsigned MD32_REG_T A
,B
,C
,D
;
985 for (;num
--;X
+=HASH_LBLOCK
)
988 R0(A
,B
,C
,D
,X
[ 0], 7,0xd76aa478L
);
989 R0(D
,A
,B
,C
,X
[ 1],12,0xe8c7b756L
);
990 R0(C
,D
,A
,B
,X
[ 2],17,0x242070dbL
);
991 R0(B
,C
,D
,A
,X
[ 3],22,0xc1bdceeeL
);
992 R0(A
,B
,C
,D
,X
[ 4], 7,0xf57c0fafL
);
993 R0(D
,A
,B
,C
,X
[ 5],12,0x4787c62aL
);
994 R0(C
,D
,A
,B
,X
[ 6],17,0xa8304613L
);
995 R0(B
,C
,D
,A
,X
[ 7],22,0xfd469501L
);
996 R0(A
,B
,C
,D
,X
[ 8], 7,0x698098d8L
);
997 R0(D
,A
,B
,C
,X
[ 9],12,0x8b44f7afL
);
998 R0(C
,D
,A
,B
,X
[10],17,0xffff5bb1L
);
999 R0(B
,C
,D
,A
,X
[11],22,0x895cd7beL
);
1000 R0(A
,B
,C
,D
,X
[12], 7,0x6b901122L
);
1001 R0(D
,A
,B
,C
,X
[13],12,0xfd987193L
);
1002 R0(C
,D
,A
,B
,X
[14],17,0xa679438eL
);
1003 R0(B
,C
,D
,A
,X
[15],22,0x49b40821L
);
1005 R1(A
,B
,C
,D
,X
[ 1], 5,0xf61e2562L
);
1006 R1(D
,A
,B
,C
,X
[ 6], 9,0xc040b340L
);
1007 R1(C
,D
,A
,B
,X
[11],14,0x265e5a51L
);
1008 R1(B
,C
,D
,A
,X
[ 0],20,0xe9b6c7aaL
);
1009 R1(A
,B
,C
,D
,X
[ 5], 5,0xd62f105dL
);
1010 R1(D
,A
,B
,C
,X
[10], 9,0x02441453L
);
1011 R1(C
,D
,A
,B
,X
[15],14,0xd8a1e681L
);
1012 R1(B
,C
,D
,A
,X
[ 4],20,0xe7d3fbc8L
);
1013 R1(A
,B
,C
,D
,X
[ 9], 5,0x21e1cde6L
);
1014 R1(D
,A
,B
,C
,X
[14], 9,0xc33707d6L
);
1015 R1(C
,D
,A
,B
,X
[ 3],14,0xf4d50d87L
);
1016 R1(B
,C
,D
,A
,X
[ 8],20,0x455a14edL
);
1017 R1(A
,B
,C
,D
,X
[13], 5,0xa9e3e905L
);
1018 R1(D
,A
,B
,C
,X
[ 2], 9,0xfcefa3f8L
);
1019 R1(C
,D
,A
,B
,X
[ 7],14,0x676f02d9L
);
1020 R1(B
,C
,D
,A
,X
[12],20,0x8d2a4c8aL
);
1022 R2(A
,B
,C
,D
,X
[ 5], 4,0xfffa3942L
);
1023 R2(D
,A
,B
,C
,X
[ 8],11,0x8771f681L
);
1024 R2(C
,D
,A
,B
,X
[11],16,0x6d9d6122L
);
1025 R2(B
,C
,D
,A
,X
[14],23,0xfde5380cL
);
1026 R2(A
,B
,C
,D
,X
[ 1], 4,0xa4beea44L
);
1027 R2(D
,A
,B
,C
,X
[ 4],11,0x4bdecfa9L
);
1028 R2(C
,D
,A
,B
,X
[ 7],16,0xf6bb4b60L
);
1029 R2(B
,C
,D
,A
,X
[10],23,0xbebfbc70L
);
1030 R2(A
,B
,C
,D
,X
[13], 4,0x289b7ec6L
);
1031 R2(D
,A
,B
,C
,X
[ 0],11,0xeaa127faL
);
1032 R2(C
,D
,A
,B
,X
[ 3],16,0xd4ef3085L
);
1033 R2(B
,C
,D
,A
,X
[ 6],23,0x04881d05L
);
1034 R2(A
,B
,C
,D
,X
[ 9], 4,0xd9d4d039L
);
1035 R2(D
,A
,B
,C
,X
[12],11,0xe6db99e5L
);
1036 R2(C
,D
,A
,B
,X
[15],16,0x1fa27cf8L
);
1037 R2(B
,C
,D
,A
,X
[ 2],23,0xc4ac5665L
);
1039 R3(A
,B
,C
,D
,X
[ 0], 6,0xf4292244L
);
1040 R3(D
,A
,B
,C
,X
[ 7],10,0x432aff97L
);
1041 R3(C
,D
,A
,B
,X
[14],15,0xab9423a7L
);
1042 R3(B
,C
,D
,A
,X
[ 5],21,0xfc93a039L
);
1043 R3(A
,B
,C
,D
,X
[12], 6,0x655b59c3L
);
1044 R3(D
,A
,B
,C
,X
[ 3],10,0x8f0ccc92L
);
1045 R3(C
,D
,A
,B
,X
[10],15,0xffeff47dL
);
1046 R3(B
,C
,D
,A
,X
[ 1],21,0x85845dd1L
);
1047 R3(A
,B
,C
,D
,X
[ 8], 6,0x6fa87e4fL
);
1048 R3(D
,A
,B
,C
,X
[15],10,0xfe2ce6e0L
);
1049 R3(C
,D
,A
,B
,X
[ 6],15,0xa3014314L
);
1050 R3(B
,C
,D
,A
,X
[13],21,0x4e0811a1L
);
1051 R3(A
,B
,C
,D
,X
[ 4], 6,0xf7537e82L
);
1052 R3(D
,A
,B
,C
,X
[11],10,0xbd3af235L
);
1053 R3(C
,D
,A
,B
,X
[ 2],15,0x2ad7d2bbL
);
1054 R3(B
,C
,D
,A
,X
[ 9],21,0xeb86d391L
);
1064 #ifndef md5_block_data_order
1068 void md5_block_data_order (MD5_CTX
*c
, const void *data_
, int num
)
1070 const unsigned char *data
=data_
;
1071 register unsigned MD32_REG_T A
,B
,C
,D
,l
;
1073 /* See comment in crypto/sha/sha_locl.h for details. */
1074 unsigned MD32_REG_T XX0
, XX1
, XX2
, XX3
, XX4
, XX5
, XX6
, XX7
,
1075 XX8
, XX9
,XX10
,XX11
,XX12
,XX13
,XX14
,XX15
;
1078 mDNSu32 XX
[MD5_LBLOCK
];
1089 HOST_c2l(data
,l
); X( 0)=l
; HOST_c2l(data
,l
); X( 1)=l
;
1091 R0(A
,B
,C
,D
,X( 0), 7,0xd76aa478L
); HOST_c2l(data
,l
); X( 2)=l
;
1092 R0(D
,A
,B
,C
,X( 1),12,0xe8c7b756L
); HOST_c2l(data
,l
); X( 3)=l
;
1093 R0(C
,D
,A
,B
,X( 2),17,0x242070dbL
); HOST_c2l(data
,l
); X( 4)=l
;
1094 R0(B
,C
,D
,A
,X( 3),22,0xc1bdceeeL
); HOST_c2l(data
,l
); X( 5)=l
;
1095 R0(A
,B
,C
,D
,X( 4), 7,0xf57c0fafL
); HOST_c2l(data
,l
); X( 6)=l
;
1096 R0(D
,A
,B
,C
,X( 5),12,0x4787c62aL
); HOST_c2l(data
,l
); X( 7)=l
;
1097 R0(C
,D
,A
,B
,X( 6),17,0xa8304613L
); HOST_c2l(data
,l
); X( 8)=l
;
1098 R0(B
,C
,D
,A
,X( 7),22,0xfd469501L
); HOST_c2l(data
,l
); X( 9)=l
;
1099 R0(A
,B
,C
,D
,X( 8), 7,0x698098d8L
); HOST_c2l(data
,l
); X(10)=l
;
1100 R0(D
,A
,B
,C
,X( 9),12,0x8b44f7afL
); HOST_c2l(data
,l
); X(11)=l
;
1101 R0(C
,D
,A
,B
,X(10),17,0xffff5bb1L
); HOST_c2l(data
,l
); X(12)=l
;
1102 R0(B
,C
,D
,A
,X(11),22,0x895cd7beL
); HOST_c2l(data
,l
); X(13)=l
;
1103 R0(A
,B
,C
,D
,X(12), 7,0x6b901122L
); HOST_c2l(data
,l
); X(14)=l
;
1104 R0(D
,A
,B
,C
,X(13),12,0xfd987193L
); HOST_c2l(data
,l
); X(15)=l
;
1105 R0(C
,D
,A
,B
,X(14),17,0xa679438eL
);
1106 R0(B
,C
,D
,A
,X(15),22,0x49b40821L
);
1108 R1(A
,B
,C
,D
,X( 1), 5,0xf61e2562L
);
1109 R1(D
,A
,B
,C
,X( 6), 9,0xc040b340L
);
1110 R1(C
,D
,A
,B
,X(11),14,0x265e5a51L
);
1111 R1(B
,C
,D
,A
,X( 0),20,0xe9b6c7aaL
);
1112 R1(A
,B
,C
,D
,X( 5), 5,0xd62f105dL
);
1113 R1(D
,A
,B
,C
,X(10), 9,0x02441453L
);
1114 R1(C
,D
,A
,B
,X(15),14,0xd8a1e681L
);
1115 R1(B
,C
,D
,A
,X( 4),20,0xe7d3fbc8L
);
1116 R1(A
,B
,C
,D
,X( 9), 5,0x21e1cde6L
);
1117 R1(D
,A
,B
,C
,X(14), 9,0xc33707d6L
);
1118 R1(C
,D
,A
,B
,X( 3),14,0xf4d50d87L
);
1119 R1(B
,C
,D
,A
,X( 8),20,0x455a14edL
);
1120 R1(A
,B
,C
,D
,X(13), 5,0xa9e3e905L
);
1121 R1(D
,A
,B
,C
,X( 2), 9,0xfcefa3f8L
);
1122 R1(C
,D
,A
,B
,X( 7),14,0x676f02d9L
);
1123 R1(B
,C
,D
,A
,X(12),20,0x8d2a4c8aL
);
1125 R2(A
,B
,C
,D
,X( 5), 4,0xfffa3942L
);
1126 R2(D
,A
,B
,C
,X( 8),11,0x8771f681L
);
1127 R2(C
,D
,A
,B
,X(11),16,0x6d9d6122L
);
1128 R2(B
,C
,D
,A
,X(14),23,0xfde5380cL
);
1129 R2(A
,B
,C
,D
,X( 1), 4,0xa4beea44L
);
1130 R2(D
,A
,B
,C
,X( 4),11,0x4bdecfa9L
);
1131 R2(C
,D
,A
,B
,X( 7),16,0xf6bb4b60L
);
1132 R2(B
,C
,D
,A
,X(10),23,0xbebfbc70L
);
1133 R2(A
,B
,C
,D
,X(13), 4,0x289b7ec6L
);
1134 R2(D
,A
,B
,C
,X( 0),11,0xeaa127faL
);
1135 R2(C
,D
,A
,B
,X( 3),16,0xd4ef3085L
);
1136 R2(B
,C
,D
,A
,X( 6),23,0x04881d05L
);
1137 R2(A
,B
,C
,D
,X( 9), 4,0xd9d4d039L
);
1138 R2(D
,A
,B
,C
,X(12),11,0xe6db99e5L
);
1139 R2(C
,D
,A
,B
,X(15),16,0x1fa27cf8L
);
1140 R2(B
,C
,D
,A
,X( 2),23,0xc4ac5665L
);
1142 R3(A
,B
,C
,D
,X( 0), 6,0xf4292244L
);
1143 R3(D
,A
,B
,C
,X( 7),10,0x432aff97L
);
1144 R3(C
,D
,A
,B
,X(14),15,0xab9423a7L
);
1145 R3(B
,C
,D
,A
,X( 5),21,0xfc93a039L
);
1146 R3(A
,B
,C
,D
,X(12), 6,0x655b59c3L
);
1147 R3(D
,A
,B
,C
,X( 3),10,0x8f0ccc92L
);
1148 R3(C
,D
,A
,B
,X(10),15,0xffeff47dL
);
1149 R3(B
,C
,D
,A
,X( 1),21,0x85845dd1L
);
1150 R3(A
,B
,C
,D
,X( 8), 6,0x6fa87e4fL
);
1151 R3(D
,A
,B
,C
,X(15),10,0xfe2ce6e0L
);
1152 R3(C
,D
,A
,B
,X( 6),15,0xa3014314L
);
1153 R3(B
,C
,D
,A
,X(13),21,0x4e0811a1L
);
1154 R3(A
,B
,C
,D
,X( 4), 6,0xf7537e82L
);
1155 R3(D
,A
,B
,C
,X(11),10,0xbd3af235L
);
1156 R3(C
,D
,A
,B
,X( 2),15,0x2ad7d2bbL
);
1157 R3(B
,C
,D
,A
,X( 9),21,0xeb86d391L
);
1169 // ***************************************************************************
1170 #if COMPILER_LIKES_PRAGMA_MARK
1171 #pragma mark - base64 -> binary conversion
1174 static const char Base64
[] =
1175 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1176 static const char Pad64
= '=';
1179 #define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
1181 static const char *mDNSstrchr(const char *s
, int c
)
1185 if (c
== *s
) return s
;
1186 if (!*s
) return mDNSNULL
;
1191 // skips all whitespace anywhere.
1192 // converts characters, four at a time, starting at (or after)
1193 // src from base - 64 numbers into three 8 bit bytes in the target area.
1194 // it returns the number of data bytes stored at the target, or -1 on error.
1195 // adapted from BIND sources
1197 mDNSexport mDNSs32
DNSDigest_Base64ToBin(const char *src
, mDNSu8
*target
, mDNSu32 targsize
)
1199 int tarindex
, state
, ch
;
1205 while ((ch
= *src
++) != '\0') {
1206 if (mDNSisspace(ch
)) /* Skip whitespace anywhere. */
1212 pos
= mDNSstrchr(Base64
, ch
);
1213 if (pos
== 0) /* A non-base64 character. */
1219 if ((mDNSu32
)tarindex
>= targsize
)
1221 target
[tarindex
] = (mDNSu8
)((pos
- Base64
) << 2);
1227 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1229 target
[tarindex
] |= (pos
- Base64
) >> 4;
1230 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x0f) << 4);
1237 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1239 target
[tarindex
] |= (pos
- Base64
) >> 2;
1240 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x03) << 6);
1247 if ((mDNSu32
)tarindex
>= targsize
)
1249 target
[tarindex
] |= (pos
- Base64
);
1260 * We are done decoding Base-64 chars. Let's see if we ended
1261 * on a byte boundary, and/or with erroneous trailing characters.
1264 if (ch
== Pad64
) { /* We got a pad char. */
1265 ch
= *src
++; /* Skip it, get next. */
1267 case 0: /* Invalid = in first position */
1268 case 1: /* Invalid = in second position */
1271 case 2: /* Valid, means one byte of info */
1272 /* Skip any number of spaces. */
1273 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1274 if (!mDNSisspace(ch
))
1276 /* Make sure there is another trailing = sign. */
1279 ch
= *src
++; /* Skip the = */
1280 /* Fall through to "single trailing =" case. */
1283 case 3: /* Valid, means two bytes of info */
1285 * We know this char is an =. Is there anything but
1286 * whitespace after it?
1288 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1289 if (!mDNSisspace(ch
))
1293 * Now make sure for cases 2 and 3 that the "extra"
1294 * bits that slopped past the last full byte were
1295 * zeros. If we don't check them, they become a
1296 * subliminal channel.
1298 if (target
&& target
[tarindex
] != 0)
1303 * We ended by seeing the end of the string. Make sure we
1304 * have no partial bytes lying around.
1314 // ***************************************************************************
1315 #if COMPILER_LIKES_PRAGMA_MARK
1316 #pragma mark - API exported to mDNS Core
1320 #define HMAC_IPAD 0x36
1321 #define HMAC_OPAD 0x5c
1324 #define HMAC_MD5_AlgName (*(const domainname*) "\010" "hmac-md5" "\007" "sig-alg" "\003" "reg" "\003" "int")
1326 // Adapted from Appendix, RFC 2104
1327 mDNSexport
void DNSDigest_ConstructHMACKey(uDNS_AuthInfo
*info
, const mDNSu8
*key
, mDNSu32 len
)
1330 mDNSu8 buf
[MD5_LEN
];
1333 // If key is longer than HMAC_LEN reset it to MD5(key)
1337 MD5_Update(&k
, key
, len
);
1343 // store key in pads
1344 mDNSPlatformMemZero(info
->key
.ipad
, HMAC_LEN
);
1345 mDNSPlatformMemZero(info
->key
.opad
, HMAC_LEN
);
1346 mDNSPlatformMemCopy(key
, info
->key
.ipad
, len
);
1347 mDNSPlatformMemCopy(key
, info
->key
.opad
, len
);
1349 // XOR key with ipad and opad values
1350 for (i
= 0; i
< HMAC_LEN
; i
++)
1352 info
->key
.ipad
[i
] ^= HMAC_IPAD
;
1353 info
->key
.opad
[i
] ^= HMAC_OPAD
;
1358 mDNSexport mDNSu8
*DNSDigest_SignMessage(DNSMessage
*msg
, mDNSu8
**end
, mDNSu16
*numAdditionals
, uDNS_AuthInfo
*info
)
1361 mDNSu8
*countPtr
, *rdata
;
1364 mDNSu8 digest
[MD5_LEN
];
1370 // Init MD5 context, digest inner key pad and message
1372 MD5_Update(&c
, info
->key
.ipad
, HMAC_LEN
);
1373 MD5_Update(&c
, (mDNSu8
*)msg
, (unsigned long)(*end
- (mDNSu8
*)msg
));
1375 // Construct TSIG RR, digesting variables as apporpriate
1376 mDNSPlatformMemZero(&tsig
, sizeof(AuthRecord
));
1377 mDNS_SetupResourceRecord(&tsig
, mDNSNULL
, 0, kDNSType_TSIG
, 0, kDNSRecordTypeKnownUnique
, mDNSNULL
, mDNSNULL
);
1380 AssignDomainName(tsig
.resrec
.name
, &info
->keyname
);
1381 MD5_Update(&c
, info
->keyname
.c
, DomainNameLength(&info
->keyname
));
1384 tsig
.resrec
.rrclass
= kDNSQClass_ANY
;
1385 buf
= mDNSOpaque16fromIntVal(kDNSQClass_ANY
);
1386 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1389 tsig
.resrec
.rroriginalttl
= 0;
1390 MD5_Update(&c
, (mDNSu8
*)&tsig
.resrec
.rroriginalttl
, sizeof(tsig
.resrec
.rroriginalttl
));
1393 AssignDomainName(&tsig
.resrec
.rdata
->u
.name
, &HMAC_MD5_AlgName
);
1394 len
= DomainNameLength(&HMAC_MD5_AlgName
);
1395 rdata
= tsig
.resrec
.rdata
->u
.data
+ len
;
1396 MD5_Update(&c
, HMAC_MD5_AlgName
.c
, len
);
1399 // get UTC (universal time), convert to 48-bit unsigned in network byte order
1400 utc32
= (mDNSu32
)mDNSPlatformUTC();
1401 if (utc32
== (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); return mDNSNULL
; }
1404 utc48
[2] = (mDNSu8
)((utc32
>> 24) & 0xff);
1405 utc48
[3] = (mDNSu8
)((utc32
>> 16) & 0xff);
1406 utc48
[4] = (mDNSu8
)((utc32
>> 8) & 0xff);
1407 utc48
[5] = (mDNSu8
)( utc32
& 0xff);
1409 mDNSPlatformMemCopy(utc48
, rdata
, 6);
1411 MD5_Update(&c
, utc48
, 6);
1414 buf
= mDNSOpaque16fromIntVal(300); // 300 sec is fudge recommended in RFC 2485
1415 rdata
[0] = buf
.b
[0];
1416 rdata
[1] = buf
.b
[1];
1417 rdata
+= sizeof(mDNSOpaque16
);
1418 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1420 // digest error and other data len (both zero) - we'll add them to the rdata later
1421 buf
.NotAnInteger
= 0;
1422 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // error
1423 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // other data len
1425 // finish the message & tsig var hash
1426 MD5_Final(digest
, &c
);
1428 // perform outer MD5 (outer key pad, inner digest)
1430 MD5_Update(&c
, info
->key
.opad
, HMAC_LEN
);
1431 MD5_Update(&c
, digest
, MD5_LEN
);
1432 MD5_Final(digest
, &c
);
1434 // set remaining rdata fields
1435 rdata
[0] = (mDNSu8
)((MD5_LEN
>> 8) & 0xff);
1436 rdata
[1] = (mDNSu8
)( MD5_LEN
& 0xff);
1437 rdata
+= sizeof(mDNSOpaque16
);
1438 mDNSPlatformMemCopy(digest
, rdata
, MD5_LEN
); // MAC
1440 rdata
[0] = msg
->h
.id
.b
[0]; // original ID
1441 rdata
[1] = msg
->h
.id
.b
[1];
1442 rdata
[2] = 0; // no error
1444 rdata
[4] = 0; // other data len
1448 tsig
.resrec
.rdlength
= (mDNSu16
)(rdata
- tsig
.resrec
.rdata
->u
.data
);
1449 *end
= PutResourceRecordTTLJumbo(msg
, ptr
, numAdditionals
, &tsig
.resrec
, 0);
1450 if (!*end
) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); return mDNSNULL
; }
1452 // update num additionals
1453 countPtr
= (mDNSu8
*)&msg
->h
.numAdditionals
; // increment (network-byte ordered) header value
1454 *countPtr
++ = (mDNSu8
)(*numAdditionals
>> 8);
1455 *countPtr
++ = (mDNSu8
)(*numAdditionals
& 0xFF);