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.12 2004/12/03 07:20:50 ksekar
27 <rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
29 Revision 1.11 2004/12/02 01:10:27 cheshire
30 Fix to compile cleanly on 64-bit x86
32 Revision 1.10 2004/11/01 20:36:04 ksekar
33 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
35 Revision 1.9 2004/10/26 09:00:12 cheshire
36 Save a few bytes by creating HMAC_MD5_AlgName as a C string instead of a 256-byte object
38 Revision 1.8 2004/09/17 01:08:48 cheshire
39 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
40 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
41 declared in that file are ONLY appropriate to single-address-space embedded applications.
42 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
44 Revision 1.7 2004/08/15 18:36:38 cheshire
45 Don't use strcpy() and strlen() on "struct domainname" objects;
46 use AssignDomainName() and DomainNameLength() instead
47 (A "struct domainname" is a collection of packed pascal strings, not a C string.)
49 Revision 1.6 2004/06/02 00:17:46 ksekar
50 Referenced original OpenSSL license headers in source file description.
52 Revision 1.5 2004/05/20 18:37:37 cheshire
55 Revision 1.4 2004/04/22 20:28:20 cheshire
56 Use existing facility of PutResourceRecordTTL() to update count field for us
58 Revision 1.3 2004/04/22 03:05:28 cheshire
59 kDNSClass_ANY should be kDNSQClass_ANY
61 Revision 1.2 2004/04/15 00:51:28 bradley
62 Minor tweaks for Windows and C++ builds. Added casts for signed/unsigned integers and 64-bit pointers.
63 Prefix some functions with mDNS to avoid conflicts. Disable benign warnings on Microsoft compilers.
65 Revision 1.1 2004/04/14 23:09:28 ksekar
66 Support for TSIG signed dynamic updates.
77 #include "mDNSEmbeddedAPI.h"
78 #include "DNSCommon.h"
80 // Disable certain benign warnings with Microsoft compilers
81 #if(defined(_MSC_VER))
82 // Disable "conditional expression is constant" warning for debug macros.
83 // Otherwise, this generates warnings for the perfectly natural construct "while(1)"
84 // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
85 #pragma warning(disable:4127)
88 // ***************************************************************************
89 #if COMPILER_LIKES_PRAGMA_MARK
90 #pragma mark - MD5 Hash Functions
94 /* The source for the has is derived CommonCrypto files CommonDigest.h, md32_common.h, md5_locl.h, md5_locl.h, and openssl/md5.h.
95 * The following changes have been made to the original sources:
96 * replaced CC_LONG w/ mDNSu32
97 * replaced CC_MD5* with MD5*
98 * replaced CC_LONG w/ mDNSu32, removed conditional #defines from md5.h
99 * removed extern decls for MD5_Init/Update/Final from CommonDigest.h
100 * removed APPLE_COMMON_DIGEST specific #defines from md5_locl.h
102 * Note: machine archetecure specific conditionals from the original sources are turned off, but are left in the code
103 * to aid in platform-specific optimizations and debugging.
104 * Sources originally distributed under the following license headers:
105 * CommonDigest.c - APSL
108 * ====================================================================
109 * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
111 * Redistribution and use in source and binary forms, with or without
112 * modification, are permitted provided that the following conditions
115 * 1. Redistributions of source code must retain the above copyright
116 * notice, this list of conditions and the following disclaimer.
118 * 2. Redistributions in binary form must reproduce the above copyright
119 * notice, this list of conditions and the following disclaimer in
120 * the documentation and/or other materials provided with the
123 * 3. All advertising materials mentioning features or use of this
124 * software must display the following acknowledgment:
125 * "This product includes software developed by the OpenSSL Project
126 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
128 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
129 * endorse or promote products derived from this software without
130 * prior written permission. For written permission, please contact
131 * licensing@OpenSSL.org.
133 * 5. Products derived from this software may not be called "OpenSSL"
134 * nor may "OpenSSL" appear in their names without prior written
135 * permission of the OpenSSL Project.
137 * 6. Redistributions of any form whatsoever must retain the following
139 * "This product includes software developed by the OpenSSL Project
140 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
142 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
143 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
144 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
145 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
146 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
147 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
148 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
149 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
150 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
151 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
152 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
153 * OF THE POSSIBILITY OF SUCH DAMAGE.
156 * md5_dgst.c, md5_locl.h
157 * ====================================================================
159 * This product includes cryptographic software written by Eric Young
160 * (eay@cryptsoft.com). This product includes software written by Tim
161 * Hudson (tjh@cryptsoft.com).
163 * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
164 * All rights reserved.
166 * This package is an SSL implementation written
167 * by Eric Young (eay@cryptsoft.com).
168 * The implementation was written so as to conform with Netscapes SSL.
170 * This library is free for commercial and non-commercial use as long as
171 * the following conditions are aheared to. The following conditions
172 * apply to all code found in this distribution, be it the RC4, RSA,
173 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
174 * included with this distribution is covered by the same copyright terms
175 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
177 * Copyright remains Eric Young's, and as such any Copyright notices in
178 * the code are not to be removed.
179 * If this package is used in a product, Eric Young should be given attribution
180 * as the author of the parts of the library used.
181 * This can be in the form of a textual message at program startup or
182 * in documentation (online or textual) provided with the package.
184 * Redistribution and use in source and binary forms, with or without
185 * modification, are permitted provided that the following conditions
187 * 1. Redistributions of source code must retain the copyright
188 * notice, this list of conditions and the following disclaimer.
189 * 2. Redistributions in binary form must reproduce the above copyright
190 * notice, this list of conditions and the following disclaimer in the
191 * documentation and/or other materials provided with the distribution.
192 * 3. All advertising materials mentioning features or use of this software
193 * must display the following acknowledgement:
194 * "This product includes cryptographic software written by
195 * Eric Young (eay@cryptsoft.com)"
196 * The word 'cryptographic' can be left out if the rouines from the library
197 * being used are not cryptographic related :-).
198 * 4. If you include any Windows specific code (or a derivative thereof) from
199 * the apps directory (application code) you must include an acknowledgement:
200 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
202 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
203 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
204 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
205 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
206 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
207 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
208 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
209 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
210 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
211 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
214 * The licence and distribution terms for any publically available version or
215 * derivative of this code cannot be changed. i.e. this code cannot simply be
216 * copied and put under another distribution licence
217 * [including the GNU Public Licence.]
221 //from CommonDigest.h
223 #define MD5_DIGEST_LENGTH 16 /* digest length in bytes */
224 #define MD5_BLOCK_BYTES 64 /* block size in bytes */
225 #define MD5_BLOCK_LONG (MD5_BLOCK_BYTES / sizeof(mDNSu32))
227 typedef struct MD5state_st
231 mDNSu32 data
[MD5_BLOCK_LONG
];
236 // from openssl/md5.h
238 #define MD5_CBLOCK 64
239 #define MD5_LBLOCK (MD5_CBLOCK/4)
240 #define MD5_DIGEST_LENGTH 16
242 int MD5_Init(MD5_CTX
*c
);
243 int MD5_Update(MD5_CTX
*c
, const void *data
, unsigned long len
);
244 int MD5_Final(unsigned char *md
, MD5_CTX
*c
);
245 void MD5_Transform(MD5_CTX
*c
, const unsigned char *b
);
249 #ifndef MD5_LONG_LOG2
250 #define MD5_LONG_LOG2 2 /* default to 32 bits */
254 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
255 # define md5_block_host_order md5_block_asm_host_order
256 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
257 void md5_block_asm_data_order_aligned (MD5_CTX
*c
, const mDNSu32
*p
,int num
);
258 # define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned
262 void md5_block_host_order (MD5_CTX
*c
, const void *p
,int num
);
263 void md5_block_data_order (MD5_CTX
*c
, const void *p
,int num
);
265 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
267 * *_block_host_order is expected to handle aligned data while
268 * *_block_data_order - unaligned. As algorithm and host (x86)
269 * are in this case of the same "endianness" these two are
270 * otherwise indistinguishable. But normally you don't want to
271 * call the same function because unaligned access in places
272 * where alignment is expected is usually a "Bad Thing". Indeed,
273 * on RISCs you get punished with BUS ERROR signal or *severe*
274 * performance degradation. Intel CPUs are in turn perfectly
275 * capable of loading unaligned data without such drastic side
276 * effect. Yes, they say it's slower than aligned load, but no
277 * exception is generated and therefore performance degradation
278 * is *incomparable* with RISCs. What we should weight here is
279 * costs of unaligned access against costs of aligning data.
280 * According to my measurements allowing unaligned access results
281 * in ~9% performance improvement on Pentium II operating at
282 * 266MHz. I won't be surprised if the difference will be higher
283 * on faster systems:-)
285 * <appro@fy.chalmers.se>
287 #define md5_block_data_order md5_block_host_order
290 #define DATA_ORDER_IS_LITTLE_ENDIAN
292 #define HASH_LONG mDNSu32
293 #define HASH_LONG_LOG2 MD5_LONG_LOG2
294 #define HASH_CTX MD5_CTX
295 #define HASH_CBLOCK MD5_CBLOCK
296 #define HASH_LBLOCK MD5_LBLOCK
298 #define HASH_UPDATE MD5_Update
299 #define HASH_TRANSFORM MD5_Transform
300 #define HASH_FINAL MD5_Final
302 #define HASH_MAKE_STRING(c,s) do { \
304 ll=(c)->A; HOST_l2c(ll,(s)); \
305 ll=(c)->B; HOST_l2c(ll,(s)); \
306 ll=(c)->C; HOST_l2c(ll,(s)); \
307 ll=(c)->D; HOST_l2c(ll,(s)); \
309 #define HASH_BLOCK_HOST_ORDER md5_block_host_order
310 #if !defined(L_ENDIAN) || defined(md5_block_data_order)
311 #define HASH_BLOCK_DATA_ORDER md5_block_data_order
313 * Little-endians (Intel and Alpha) feel better without this.
314 * It looks like memcpy does better job than generic
315 * md5_block_data_order on copying-n-aligning input data.
316 * But frankly speaking I didn't expect such result on Alpha.
317 * On the other hand I've got this with egcs-1.0.2 and if
318 * program is compiled with another (better?) compiler it
319 * might turn out other way around.
321 * <appro@fy.chalmers.se>
326 // from md32_common.h
329 * This is a generic 32 bit "collector" for message digest algorithms.
330 * Whenever needed it collects input character stream into chunks of
331 * 32 bit values and invokes a block function that performs actual hash
338 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
339 * this macro defines byte order of input stream.
341 * size of a unit chunk HASH_BLOCK operates on.
343 * has to be at lest 32 bit wide, if it's wider, then
344 * HASH_LONG_LOG2 *has to* be defined along
346 * context structure that at least contains following
351 * HASH_LONG data[HASH_LBLOCK];
356 * name of "Update" function, implemented here.
358 * name of "Transform" function, implemented here.
360 * name of "Final" function, implemented here.
361 * HASH_BLOCK_HOST_ORDER
362 * name of "block" function treating *aligned* input message
363 * in host byte order, implemented externally.
364 * HASH_BLOCK_DATA_ORDER
365 * name of "block" function treating *unaligned* input message
366 * in original (data) byte order, implemented externally (it
367 * actually is optional if data and host are of the same
370 * macro convering context variables to an ASCII hash string.
374 * B_ENDIAN or L_ENDIAN
375 * defines host byte-order.
377 * defaults to 2 if not states otherwise.
379 * assumed to be HASH_CBLOCK/4 if not stated otherwise.
380 * HASH_BLOCK_DATA_ORDER_ALIGNED
381 * alternative "block" function capable of treating
382 * aligned input message in original (data) order,
383 * implemented externally.
387 * #define DATA_ORDER_IS_LITTLE_ENDIAN
389 * #define HASH_LONG mDNSu32
390 * #define HASH_LONG_LOG2 mDNSu32_LOG2
391 * #define HASH_CTX MD5_CTX
392 * #define HASH_CBLOCK MD5_CBLOCK
393 * #define HASH_LBLOCK MD5_LBLOCK
394 * #define HASH_UPDATE MD5_Update
395 * #define HASH_TRANSFORM MD5_Transform
396 * #define HASH_FINAL MD5_Final
397 * #define HASH_BLOCK_HOST_ORDER md5_block_host_order
398 * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
400 * <appro@fy.chalmers.se>
403 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
404 #error "DATA_ORDER must be defined!"
408 #error "HASH_CBLOCK must be defined!"
411 #error "HASH_LONG must be defined!"
414 #error "HASH_CTX must be defined!"
418 #error "HASH_UPDATE must be defined!"
420 #ifndef HASH_TRANSFORM
421 #error "HASH_TRANSFORM must be defined!"
424 #error "HASH_FINAL must be defined!"
427 #ifndef HASH_BLOCK_HOST_ORDER
428 #error "HASH_BLOCK_HOST_ORDER must be defined!"
433 * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
436 #ifndef HASH_BLOCK_DATA_ORDER
437 #error "HASH_BLOCK_DATA_ORDER must be defined!"
442 #define HASH_LBLOCK (HASH_CBLOCK/4)
445 #ifndef HASH_LONG_LOG2
446 #define HASH_LONG_LOG2 2
450 * Engage compiler specific rotate intrinsic function if available.
454 # if 0 /* defined(_MSC_VER) */
455 # define ROTATE(a,n) _lrotl(a,n)
456 # elif defined(__MWERKS__)
457 # if defined(__POWERPC__)
458 # define ROTATE(a,n) (unsigned MD32_REG_T)__rlwinm((int)a,n,0,31)
459 # elif defined(__MC68K__)
460 /* Motorola specific tweak. <appro@fy.chalmers.se> */
461 # define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) )
463 # define ROTATE(a,n) __rol(a,n)
465 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
467 * Some GNU C inline assembler templates. Note that these are
468 * rotates by *constant* number of bits! But that's exactly
469 * what we need here...
471 * <appro@fy.chalmers.se>
473 # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
474 # define ROTATE(a,n) ({ register unsigned int ret; \
482 # elif defined(__powerpc) || defined(__ppc)
483 # define ROTATE(a,n) ({ register unsigned int ret; \
485 "rlwinm %0,%1,%2,0,31" \
494 * Engage compiler specific "fetch in reverse byte order"
495 * intrinsic function if available.
497 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
498 /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
499 # if (defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)) && !defined(I386_ONLY)
500 # define BE_FETCH32(a) ({ register unsigned int l=(a);\
503 : "=r"(l) : "0"(l)); \
506 # elif defined(__powerpc)
507 # define LE_FETCH32(a) ({ register unsigned int l; \
515 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
516 # define LE_FETCH32(a) ({ register unsigned int l; \
518 "lda [%1]#ASI_PRIMARY_LITTLE,%0"\
525 #endif /* PEDANTIC */
527 #if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */
528 /* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
530 /* 5 instructions with rotate instruction, else 9 */
531 #define REVERSE_FETCH32(a,l) ( \
532 l=*(const HASH_LONG *)(a), \
533 ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \
536 /* 6 instructions with rotate instruction, else 8 */
537 #define REVERSE_FETCH32(a,l) ( \
538 l=*(const HASH_LONG *)(a), \
539 l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \
543 * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
544 * It's rewritten as above for two reasons:
545 * - RISCs aren't good at long constants and have to explicitely
546 * compose 'em with several (well, usually 2) instructions in a
547 * register before performing the actual operation and (as you
548 * already realized:-) having same constant should inspire the
549 * compiler to permanently allocate the only register for it;
550 * - most modern CPUs have two ALUs, but usually only one has
551 * circuitry for shifts:-( this minor tweak inspires compiler
552 * to schedule shift instructions in a better way...
554 * <appro@fy.chalmers.se>
560 #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
564 * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
565 * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
566 * and host are of the same "endianess". It's possible to mask
567 * this with blank #define HASH_BLOCK_DATA_ORDER though...
569 * <appro@fy.chalmers.se>
571 #if defined(B_ENDIAN)
572 # if defined(DATA_ORDER_IS_BIG_ENDIAN)
573 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
574 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
576 # elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
577 # ifndef HOST_FETCH32
579 # define HOST_FETCH32(p,l) LE_FETCH32(p)
580 # elif defined(REVERSE_FETCH32)
581 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
585 #elif defined(L_ENDIAN)
586 # if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
587 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
588 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
590 # elif defined(DATA_ORDER_IS_BIG_ENDIAN)
591 # ifndef HOST_FETCH32
593 # define HOST_FETCH32(p,l) BE_FETCH32(p)
594 # elif defined(REVERSE_FETCH32)
595 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
601 #if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
602 #ifndef HASH_BLOCK_DATA_ORDER
603 #error "HASH_BLOCK_DATA_ORDER must be defined!"
607 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
609 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
610 l|=(((unsigned long)(*((c)++)))<<16), \
611 l|=(((unsigned long)(*((c)++)))<< 8), \
612 l|=(((unsigned long)(*((c)++))) ), \
614 #define HOST_p_c2l(c,l,n) { \
616 case 0: l =((unsigned long)(*((c)++)))<<24; \
617 case 1: l|=((unsigned long)(*((c)++)))<<16; \
618 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
619 case 3: l|=((unsigned long)(*((c)++))); \
621 #define HOST_p_c2l_p(c,l,sc,len) { \
623 case 0: l =((unsigned long)(*((c)++)))<<24; \
624 if (--len == 0) break; \
625 case 1: l|=((unsigned long)(*((c)++)))<<16; \
626 if (--len == 0) break; \
627 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
629 /* NOTE the pointer is not incremented at the end of this */
630 #define HOST_c2l_p(c,l,n) { \
633 case 3: l =((unsigned long)(*(--(c))))<< 8; \
634 case 2: l|=((unsigned long)(*(--(c))))<<16; \
635 case 1: l|=((unsigned long)(*(--(c))))<<24; \
637 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
638 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
639 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
640 *((c)++)=(unsigned char)(((l) )&0xff), \
643 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
645 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
646 l|=(((unsigned long)(*((c)++)))<< 8), \
647 l|=(((unsigned long)(*((c)++)))<<16), \
648 l|=(((unsigned long)(*((c)++)))<<24), \
650 #define HOST_p_c2l(c,l,n) { \
652 case 0: l =((unsigned long)(*((c)++))); \
653 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
654 case 2: l|=((unsigned long)(*((c)++)))<<16; \
655 case 3: l|=((unsigned long)(*((c)++)))<<24; \
657 #define HOST_p_c2l_p(c,l,sc,len) { \
659 case 0: l =((unsigned long)(*((c)++))); \
660 if (--len == 0) break; \
661 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
662 if (--len == 0) break; \
663 case 2: l|=((unsigned long)(*((c)++)))<<16; \
665 /* NOTE the pointer is not incremented at the end of this */
666 #define HOST_c2l_p(c,l,n) { \
669 case 3: l =((unsigned long)(*(--(c))))<<16; \
670 case 2: l|=((unsigned long)(*(--(c))))<< 8; \
671 case 1: l|=((unsigned long)(*(--(c)))); \
673 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
674 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
675 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
676 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
682 * Time for some action:-)
685 int HASH_UPDATE (HASH_CTX
*c
, const void *data_
, unsigned long len
)
687 const unsigned char *data
=(const unsigned char *)data_
;
688 register HASH_LONG
* p
;
689 register unsigned long l
;
692 if (len
==0) return 1;
694 l
=(c
->Nl
+(len
<<3))&0xffffffffL
;
695 /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
696 * Wei Dai <weidai@eskimo.com> for pointing it out. */
697 if (l
< c
->Nl
) /* overflow */
708 if ((c
->num
+len
) >= HASH_CBLOCK
)
710 l
=p
[sw
]; HOST_p_c2l(data
,l
,sc
); p
[sw
++]=l
;
711 for (; sw
<HASH_LBLOCK
; sw
++)
713 HOST_c2l(data
,l
); p
[sw
]=l
;
715 HASH_BLOCK_HOST_ORDER (c
,p
,1);
716 len
-=(HASH_CBLOCK
-c
->num
);
718 /* drop through and do the rest */
723 if ((sc
+len
) < 4) /* ugly, add char's to a word */
725 l
=p
[sw
]; HOST_p_c2l_p(data
,l
,sc
,len
); p
[sw
]=l
;
733 HOST_p_c2l(data
,l
,sc
);
735 for (; sw
< ew
; sw
++)
737 HOST_c2l(data
,l
); p
[sw
]=l
;
741 HOST_c2l_p(data
,l
,ec
); p
[sw
]=l
;
748 sw
=(int)(len
/HASH_CBLOCK
);
751 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
753 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
754 * only if sizeof(HASH_LONG)==4.
756 if ((((unsigned long)data
)%4
) == 0)
758 /* data is properly aligned so that we can cast it: */
759 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,(HASH_LONG
*)data
,sw
);
765 #if !defined(HASH_BLOCK_DATA_ORDER)
768 memcpy (p
=c
->data
,data
,HASH_CBLOCK
);
769 HASH_BLOCK_DATA_ORDER_ALIGNED(c
,p
,1);
775 #if defined(HASH_BLOCK_DATA_ORDER)
777 HASH_BLOCK_DATA_ORDER(c
,data
,sw
);
789 ew
=(int)(len
>>2); /* words to copy */
793 HOST_c2l(data
,l
); *p
=l
;
795 HOST_c2l_p(data
,l
,ec
);
802 void HASH_TRANSFORM (HASH_CTX
*c
, const unsigned char *data
)
804 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
805 if ((((unsigned long)data
)%4
) == 0)
806 /* data is properly aligned so that we can cast it: */
807 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,(HASH_LONG
*)data
,1);
809 #if !defined(HASH_BLOCK_DATA_ORDER)
811 memcpy (c
->data
,data
,HASH_CBLOCK
);
812 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,c
->data
,1);
816 #if defined(HASH_BLOCK_DATA_ORDER)
817 HASH_BLOCK_DATA_ORDER (c
,data
,1);
822 int HASH_FINAL (unsigned char *md
, HASH_CTX
*c
)
824 register HASH_LONG
*p
;
825 register unsigned long l
;
827 static const unsigned char end
[4]={0x80,0x00,0x00,0x00};
828 const unsigned char *cp
=end
;
830 /* c->num should definitly have room for at least one more byte. */
836 /* purify often complains about the following line as an
837 * Uninitialized Memory Read. While this can be true, the
838 * following p_c2l macro will reset l when that case is true.
839 * This is because j&0x03 contains the number of 'valid' bytes
840 * already in p[i]. If and only if j&0x03 == 0, the UMR will
841 * occur but this is also the only time p_c2l will do
842 * l= *(cp++) instead of l|= *(cp++)
843 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
846 if (j
==0) p
[i
]=0; /* Yeah, but that's not the way to fix it:-) */
850 l
= (j
==0) ? 0 : p
[i
];
852 HOST_p_c2l(cp
,l
,j
); p
[i
++]=l
; /* i is the next 'undefined word' */
854 if (i
>(HASH_LBLOCK
-2)) /* save room for Nl and Nh */
856 if (i
<HASH_LBLOCK
) p
[i
]=0;
857 HASH_BLOCK_HOST_ORDER (c
,p
,1);
860 for (; i
<(HASH_LBLOCK
-2); i
++)
863 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
864 p
[HASH_LBLOCK
-2]=c
->Nh
;
865 p
[HASH_LBLOCK
-1]=c
->Nl
;
866 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
867 p
[HASH_LBLOCK
-2]=c
->Nl
;
868 p
[HASH_LBLOCK
-1]=c
->Nh
;
870 HASH_BLOCK_HOST_ORDER (c
,p
,1);
872 #ifndef HASH_MAKE_STRING
873 #error "HASH_MAKE_STRING must be defined!"
875 HASH_MAKE_STRING(c
,md
);
879 /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
880 * but I'm not worried :-)
881 OPENSSL_cleanse((void *)c,sizeof(HASH_CTX));
887 #define MD32_REG_T long
889 * This comment was originaly written for MD5, which is why it
890 * discusses A-D. But it basically applies to all 32-bit digests,
891 * which is why it was moved to common header file.
893 * In case you wonder why A-D are declared as long and not
894 * as mDNSu32. Doing so results in slight performance
895 * boost on LP64 architectures. The catch is we don't
896 * really care if 32 MSBs of a 64-bit register get polluted
897 * with eventual overflows as we *save* only 32 LSBs in
898 * *either* case. Now declaring 'em long excuses the compiler
899 * from keeping 32 MSBs zeroed resulting in 13% performance
900 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
901 * Well, to be honest it should say that this *prevents*
902 * performance degradation.
903 * <appro@fy.chalmers.se>
904 * Apparently there're LP64 compilers that generate better
905 * code if A-D are declared int. Most notably GCC-x86_64
906 * generates better code.
907 * <appro@fy.chalmers.se>
912 // from md5_locl.h (continued)
915 #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
916 #define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
919 /* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
920 * simplified to the code below. Wei attributes these optimizations
921 * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
923 #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
924 #define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c))
925 #define H(b,c,d) ((b) ^ (c) ^ (d))
926 #define I(b,c,d) (((~(d)) | (b)) ^ (c))
928 #define R0(a,b,c,d,k,s,t) { \
929 a+=((k)+(t)+F((b),(c),(d))); \
933 #define R1(a,b,c,d,k,s,t) { \
934 a+=((k)+(t)+G((b),(c),(d))); \
938 #define R2(a,b,c,d,k,s,t) { \
939 a+=((k)+(t)+H((b),(c),(d))); \
943 #define R3(a,b,c,d,k,s,t) { \
944 a+=((k)+(t)+I((b),(c),(d))); \
951 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
954 #define INIT_DATA_A (unsigned long)0x67452301L
955 #define INIT_DATA_B (unsigned long)0xefcdab89L
956 #define INIT_DATA_C (unsigned long)0x98badcfeL
957 #define INIT_DATA_D (unsigned long)0x10325476L
959 int MD5_Init(MD5_CTX
*c
)
971 #ifndef md5_block_host_order
972 void md5_block_host_order (MD5_CTX
*c
, const void *data
, int num
)
974 const mDNSu32
*X
=(const mDNSu32
*)data
;
975 register unsigned MD32_REG_T A
,B
,C
,D
;
982 for (;num
--;X
+=HASH_LBLOCK
)
985 R0(A
,B
,C
,D
,X
[ 0], 7,0xd76aa478L
);
986 R0(D
,A
,B
,C
,X
[ 1],12,0xe8c7b756L
);
987 R0(C
,D
,A
,B
,X
[ 2],17,0x242070dbL
);
988 R0(B
,C
,D
,A
,X
[ 3],22,0xc1bdceeeL
);
989 R0(A
,B
,C
,D
,X
[ 4], 7,0xf57c0fafL
);
990 R0(D
,A
,B
,C
,X
[ 5],12,0x4787c62aL
);
991 R0(C
,D
,A
,B
,X
[ 6],17,0xa8304613L
);
992 R0(B
,C
,D
,A
,X
[ 7],22,0xfd469501L
);
993 R0(A
,B
,C
,D
,X
[ 8], 7,0x698098d8L
);
994 R0(D
,A
,B
,C
,X
[ 9],12,0x8b44f7afL
);
995 R0(C
,D
,A
,B
,X
[10],17,0xffff5bb1L
);
996 R0(B
,C
,D
,A
,X
[11],22,0x895cd7beL
);
997 R0(A
,B
,C
,D
,X
[12], 7,0x6b901122L
);
998 R0(D
,A
,B
,C
,X
[13],12,0xfd987193L
);
999 R0(C
,D
,A
,B
,X
[14],17,0xa679438eL
);
1000 R0(B
,C
,D
,A
,X
[15],22,0x49b40821L
);
1002 R1(A
,B
,C
,D
,X
[ 1], 5,0xf61e2562L
);
1003 R1(D
,A
,B
,C
,X
[ 6], 9,0xc040b340L
);
1004 R1(C
,D
,A
,B
,X
[11],14,0x265e5a51L
);
1005 R1(B
,C
,D
,A
,X
[ 0],20,0xe9b6c7aaL
);
1006 R1(A
,B
,C
,D
,X
[ 5], 5,0xd62f105dL
);
1007 R1(D
,A
,B
,C
,X
[10], 9,0x02441453L
);
1008 R1(C
,D
,A
,B
,X
[15],14,0xd8a1e681L
);
1009 R1(B
,C
,D
,A
,X
[ 4],20,0xe7d3fbc8L
);
1010 R1(A
,B
,C
,D
,X
[ 9], 5,0x21e1cde6L
);
1011 R1(D
,A
,B
,C
,X
[14], 9,0xc33707d6L
);
1012 R1(C
,D
,A
,B
,X
[ 3],14,0xf4d50d87L
);
1013 R1(B
,C
,D
,A
,X
[ 8],20,0x455a14edL
);
1014 R1(A
,B
,C
,D
,X
[13], 5,0xa9e3e905L
);
1015 R1(D
,A
,B
,C
,X
[ 2], 9,0xfcefa3f8L
);
1016 R1(C
,D
,A
,B
,X
[ 7],14,0x676f02d9L
);
1017 R1(B
,C
,D
,A
,X
[12],20,0x8d2a4c8aL
);
1019 R2(A
,B
,C
,D
,X
[ 5], 4,0xfffa3942L
);
1020 R2(D
,A
,B
,C
,X
[ 8],11,0x8771f681L
);
1021 R2(C
,D
,A
,B
,X
[11],16,0x6d9d6122L
);
1022 R2(B
,C
,D
,A
,X
[14],23,0xfde5380cL
);
1023 R2(A
,B
,C
,D
,X
[ 1], 4,0xa4beea44L
);
1024 R2(D
,A
,B
,C
,X
[ 4],11,0x4bdecfa9L
);
1025 R2(C
,D
,A
,B
,X
[ 7],16,0xf6bb4b60L
);
1026 R2(B
,C
,D
,A
,X
[10],23,0xbebfbc70L
);
1027 R2(A
,B
,C
,D
,X
[13], 4,0x289b7ec6L
);
1028 R2(D
,A
,B
,C
,X
[ 0],11,0xeaa127faL
);
1029 R2(C
,D
,A
,B
,X
[ 3],16,0xd4ef3085L
);
1030 R2(B
,C
,D
,A
,X
[ 6],23,0x04881d05L
);
1031 R2(A
,B
,C
,D
,X
[ 9], 4,0xd9d4d039L
);
1032 R2(D
,A
,B
,C
,X
[12],11,0xe6db99e5L
);
1033 R2(C
,D
,A
,B
,X
[15],16,0x1fa27cf8L
);
1034 R2(B
,C
,D
,A
,X
[ 2],23,0xc4ac5665L
);
1036 R3(A
,B
,C
,D
,X
[ 0], 6,0xf4292244L
);
1037 R3(D
,A
,B
,C
,X
[ 7],10,0x432aff97L
);
1038 R3(C
,D
,A
,B
,X
[14],15,0xab9423a7L
);
1039 R3(B
,C
,D
,A
,X
[ 5],21,0xfc93a039L
);
1040 R3(A
,B
,C
,D
,X
[12], 6,0x655b59c3L
);
1041 R3(D
,A
,B
,C
,X
[ 3],10,0x8f0ccc92L
);
1042 R3(C
,D
,A
,B
,X
[10],15,0xffeff47dL
);
1043 R3(B
,C
,D
,A
,X
[ 1],21,0x85845dd1L
);
1044 R3(A
,B
,C
,D
,X
[ 8], 6,0x6fa87e4fL
);
1045 R3(D
,A
,B
,C
,X
[15],10,0xfe2ce6e0L
);
1046 R3(C
,D
,A
,B
,X
[ 6],15,0xa3014314L
);
1047 R3(B
,C
,D
,A
,X
[13],21,0x4e0811a1L
);
1048 R3(A
,B
,C
,D
,X
[ 4], 6,0xf7537e82L
);
1049 R3(D
,A
,B
,C
,X
[11],10,0xbd3af235L
);
1050 R3(C
,D
,A
,B
,X
[ 2],15,0x2ad7d2bbL
);
1051 R3(B
,C
,D
,A
,X
[ 9],21,0xeb86d391L
);
1061 #ifndef md5_block_data_order
1065 void md5_block_data_order (MD5_CTX
*c
, const void *data_
, int num
)
1067 const unsigned char *data
=data_
;
1068 register unsigned MD32_REG_T A
,B
,C
,D
,l
;
1070 /* See comment in crypto/sha/sha_locl.h for details. */
1071 unsigned MD32_REG_T XX0
, XX1
, XX2
, XX3
, XX4
, XX5
, XX6
, XX7
,
1072 XX8
, XX9
,XX10
,XX11
,XX12
,XX13
,XX14
,XX15
;
1075 mDNSu32 XX
[MD5_LBLOCK
];
1086 HOST_c2l(data
,l
); X( 0)=l
; HOST_c2l(data
,l
); X( 1)=l
;
1088 R0(A
,B
,C
,D
,X( 0), 7,0xd76aa478L
); HOST_c2l(data
,l
); X( 2)=l
;
1089 R0(D
,A
,B
,C
,X( 1),12,0xe8c7b756L
); HOST_c2l(data
,l
); X( 3)=l
;
1090 R0(C
,D
,A
,B
,X( 2),17,0x242070dbL
); HOST_c2l(data
,l
); X( 4)=l
;
1091 R0(B
,C
,D
,A
,X( 3),22,0xc1bdceeeL
); HOST_c2l(data
,l
); X( 5)=l
;
1092 R0(A
,B
,C
,D
,X( 4), 7,0xf57c0fafL
); HOST_c2l(data
,l
); X( 6)=l
;
1093 R0(D
,A
,B
,C
,X( 5),12,0x4787c62aL
); HOST_c2l(data
,l
); X( 7)=l
;
1094 R0(C
,D
,A
,B
,X( 6),17,0xa8304613L
); HOST_c2l(data
,l
); X( 8)=l
;
1095 R0(B
,C
,D
,A
,X( 7),22,0xfd469501L
); HOST_c2l(data
,l
); X( 9)=l
;
1096 R0(A
,B
,C
,D
,X( 8), 7,0x698098d8L
); HOST_c2l(data
,l
); X(10)=l
;
1097 R0(D
,A
,B
,C
,X( 9),12,0x8b44f7afL
); HOST_c2l(data
,l
); X(11)=l
;
1098 R0(C
,D
,A
,B
,X(10),17,0xffff5bb1L
); HOST_c2l(data
,l
); X(12)=l
;
1099 R0(B
,C
,D
,A
,X(11),22,0x895cd7beL
); HOST_c2l(data
,l
); X(13)=l
;
1100 R0(A
,B
,C
,D
,X(12), 7,0x6b901122L
); HOST_c2l(data
,l
); X(14)=l
;
1101 R0(D
,A
,B
,C
,X(13),12,0xfd987193L
); HOST_c2l(data
,l
); X(15)=l
;
1102 R0(C
,D
,A
,B
,X(14),17,0xa679438eL
);
1103 R0(B
,C
,D
,A
,X(15),22,0x49b40821L
);
1105 R1(A
,B
,C
,D
,X( 1), 5,0xf61e2562L
);
1106 R1(D
,A
,B
,C
,X( 6), 9,0xc040b340L
);
1107 R1(C
,D
,A
,B
,X(11),14,0x265e5a51L
);
1108 R1(B
,C
,D
,A
,X( 0),20,0xe9b6c7aaL
);
1109 R1(A
,B
,C
,D
,X( 5), 5,0xd62f105dL
);
1110 R1(D
,A
,B
,C
,X(10), 9,0x02441453L
);
1111 R1(C
,D
,A
,B
,X(15),14,0xd8a1e681L
);
1112 R1(B
,C
,D
,A
,X( 4),20,0xe7d3fbc8L
);
1113 R1(A
,B
,C
,D
,X( 9), 5,0x21e1cde6L
);
1114 R1(D
,A
,B
,C
,X(14), 9,0xc33707d6L
);
1115 R1(C
,D
,A
,B
,X( 3),14,0xf4d50d87L
);
1116 R1(B
,C
,D
,A
,X( 8),20,0x455a14edL
);
1117 R1(A
,B
,C
,D
,X(13), 5,0xa9e3e905L
);
1118 R1(D
,A
,B
,C
,X( 2), 9,0xfcefa3f8L
);
1119 R1(C
,D
,A
,B
,X( 7),14,0x676f02d9L
);
1120 R1(B
,C
,D
,A
,X(12),20,0x8d2a4c8aL
);
1122 R2(A
,B
,C
,D
,X( 5), 4,0xfffa3942L
);
1123 R2(D
,A
,B
,C
,X( 8),11,0x8771f681L
);
1124 R2(C
,D
,A
,B
,X(11),16,0x6d9d6122L
);
1125 R2(B
,C
,D
,A
,X(14),23,0xfde5380cL
);
1126 R2(A
,B
,C
,D
,X( 1), 4,0xa4beea44L
);
1127 R2(D
,A
,B
,C
,X( 4),11,0x4bdecfa9L
);
1128 R2(C
,D
,A
,B
,X( 7),16,0xf6bb4b60L
);
1129 R2(B
,C
,D
,A
,X(10),23,0xbebfbc70L
);
1130 R2(A
,B
,C
,D
,X(13), 4,0x289b7ec6L
);
1131 R2(D
,A
,B
,C
,X( 0),11,0xeaa127faL
);
1132 R2(C
,D
,A
,B
,X( 3),16,0xd4ef3085L
);
1133 R2(B
,C
,D
,A
,X( 6),23,0x04881d05L
);
1134 R2(A
,B
,C
,D
,X( 9), 4,0xd9d4d039L
);
1135 R2(D
,A
,B
,C
,X(12),11,0xe6db99e5L
);
1136 R2(C
,D
,A
,B
,X(15),16,0x1fa27cf8L
);
1137 R2(B
,C
,D
,A
,X( 2),23,0xc4ac5665L
);
1139 R3(A
,B
,C
,D
,X( 0), 6,0xf4292244L
);
1140 R3(D
,A
,B
,C
,X( 7),10,0x432aff97L
);
1141 R3(C
,D
,A
,B
,X(14),15,0xab9423a7L
);
1142 R3(B
,C
,D
,A
,X( 5),21,0xfc93a039L
);
1143 R3(A
,B
,C
,D
,X(12), 6,0x655b59c3L
);
1144 R3(D
,A
,B
,C
,X( 3),10,0x8f0ccc92L
);
1145 R3(C
,D
,A
,B
,X(10),15,0xffeff47dL
);
1146 R3(B
,C
,D
,A
,X( 1),21,0x85845dd1L
);
1147 R3(A
,B
,C
,D
,X( 8), 6,0x6fa87e4fL
);
1148 R3(D
,A
,B
,C
,X(15),10,0xfe2ce6e0L
);
1149 R3(C
,D
,A
,B
,X( 6),15,0xa3014314L
);
1150 R3(B
,C
,D
,A
,X(13),21,0x4e0811a1L
);
1151 R3(A
,B
,C
,D
,X( 4), 6,0xf7537e82L
);
1152 R3(D
,A
,B
,C
,X(11),10,0xbd3af235L
);
1153 R3(C
,D
,A
,B
,X( 2),15,0x2ad7d2bbL
);
1154 R3(B
,C
,D
,A
,X( 9),21,0xeb86d391L
);
1166 // ***************************************************************************
1167 #if COMPILER_LIKES_PRAGMA_MARK
1168 #pragma mark - base64 -> binary conversion
1171 static const char Base64
[] =
1172 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1173 static const char Pad64
= '=';
1176 #define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
1178 static const char *mDNSstrchr(const char *s
, int c
)
1182 if (c
== *s
) return s
;
1183 if (!*s
) return mDNSNULL
;
1188 // skips all whitespace anywhere.
1189 // converts characters, four at a time, starting at (or after)
1190 // src from base - 64 numbers into three 8 bit bytes in the target area.
1191 // it returns the number of data bytes stored at the target, or -1 on error.
1192 // adapted from BIND sources
1194 mDNSexport mDNSs32
DNSDigest_Base64ToBin(const char *src
, mDNSu8
*target
, mDNSu32 targsize
)
1196 int tarindex
, state
, ch
;
1202 while ((ch
= *src
++) != '\0') {
1203 if (mDNSisspace(ch
)) /* Skip whitespace anywhere. */
1209 pos
= mDNSstrchr(Base64
, ch
);
1210 if (pos
== 0) /* A non-base64 character. */
1216 if ((mDNSu32
)tarindex
>= targsize
)
1218 target
[tarindex
] = (mDNSu8
)((pos
- Base64
) << 2);
1224 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1226 target
[tarindex
] |= (pos
- Base64
) >> 4;
1227 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x0f) << 4);
1234 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1236 target
[tarindex
] |= (pos
- Base64
) >> 2;
1237 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x03) << 6);
1244 if ((mDNSu32
)tarindex
>= targsize
)
1246 target
[tarindex
] |= (pos
- Base64
);
1257 * We are done decoding Base-64 chars. Let's see if we ended
1258 * on a byte boundary, and/or with erroneous trailing characters.
1261 if (ch
== Pad64
) { /* We got a pad char. */
1262 ch
= *src
++; /* Skip it, get next. */
1264 case 0: /* Invalid = in first position */
1265 case 1: /* Invalid = in second position */
1268 case 2: /* Valid, means one byte of info */
1269 /* Skip any number of spaces. */
1270 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1271 if (!mDNSisspace(ch
))
1273 /* Make sure there is another trailing = sign. */
1276 ch
= *src
++; /* Skip the = */
1277 /* Fall through to "single trailing =" case. */
1280 case 3: /* Valid, means two bytes of info */
1282 * We know this char is an =. Is there anything but
1283 * whitespace after it?
1285 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1286 if (!mDNSisspace(ch
))
1290 * Now make sure for cases 2 and 3 that the "extra"
1291 * bits that slopped past the last full byte were
1292 * zeros. If we don't check them, they become a
1293 * subliminal channel.
1295 if (target
&& target
[tarindex
] != 0)
1300 * We ended by seeing the end of the string. Make sure we
1301 * have no partial bytes lying around.
1311 // ***************************************************************************
1312 #if COMPILER_LIKES_PRAGMA_MARK
1313 #pragma mark - API exported to mDNS Core
1317 #define HMAC_IPAD 0x36
1318 #define HMAC_OPAD 0x5c
1321 #define HMAC_MD5_AlgName (*(const domainname*) "\010" "hmac-md5" "\007" "sig-alg" "\003" "reg" "\003" "int")
1323 // Adapted from Appendix, RFC 2104
1324 mDNSexport
void DNSDigest_ConstructHMACKey(uDNS_AuthInfo
*info
, const mDNSu8
*key
, mDNSu32 len
)
1327 mDNSu8 buf
[MD5_LEN
];
1330 // If key is longer than HMAC_LEN reset it to MD5(key)
1334 MD5_Update(&k
, key
, len
);
1340 // store key in pads
1341 mDNSPlatformMemZero(info
->key
.ipad
, HMAC_LEN
);
1342 mDNSPlatformMemZero(info
->key
.opad
, HMAC_LEN
);
1343 mDNSPlatformMemCopy(key
, info
->key
.ipad
, len
);
1344 mDNSPlatformMemCopy(key
, info
->key
.opad
, len
);
1346 // XOR key with ipad and opad values
1347 for (i
= 0; i
< HMAC_LEN
; i
++)
1349 info
->key
.ipad
[i
] ^= HMAC_IPAD
;
1350 info
->key
.opad
[i
] ^= HMAC_OPAD
;
1355 mDNSexport mDNSu8
*DNSDigest_SignMessage(DNSMessage
*msg
, mDNSu8
**end
, mDNSu16
*numAdditionals
, uDNS_AuthInfo
*info
)
1358 mDNSu8
*countPtr
, *rdata
;
1361 mDNSu8 digest
[MD5_LEN
];
1367 // Init MD5 context, digest inner key pad and message
1369 MD5_Update(&c
, info
->key
.ipad
, HMAC_LEN
);
1370 MD5_Update(&c
, (mDNSu8
*)msg
, (unsigned long)(*end
- (mDNSu8
*)msg
));
1372 // Construct TSIG RR, digesting variables as apporpriate
1373 mDNSPlatformMemZero(&tsig
, sizeof(AuthRecord
));
1374 mDNS_SetupResourceRecord(&tsig
, mDNSNULL
, 0, kDNSType_TSIG
, 0, kDNSRecordTypeKnownUnique
, mDNSNULL
, mDNSNULL
);
1377 AssignDomainName(tsig
.resrec
.name
, info
->keyname
);
1378 MD5_Update(&c
, info
->keyname
.c
, DomainNameLength(&info
->keyname
));
1381 tsig
.resrec
.rrclass
= kDNSQClass_ANY
;
1382 buf
= mDNSOpaque16fromIntVal(kDNSQClass_ANY
);
1383 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1386 tsig
.resrec
.rroriginalttl
= 0;
1387 MD5_Update(&c
, (mDNSu8
*)&tsig
.resrec
.rroriginalttl
, sizeof(tsig
.resrec
.rroriginalttl
));
1390 AssignDomainName(tsig
.resrec
.rdata
->u
.name
, HMAC_MD5_AlgName
);
1391 len
= DomainNameLength(&HMAC_MD5_AlgName
);
1392 rdata
= tsig
.resrec
.rdata
->u
.data
+ len
;
1393 MD5_Update(&c
, HMAC_MD5_AlgName
.c
, len
);
1396 // get UTC (universal time), convert to 48-bit unsigned in network byte order
1397 utc32
= (mDNSu32
)mDNSPlatformUTC();
1398 if (utc32
== (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); return mDNSNULL
; }
1401 utc48
[2] = (mDNSu8
)((utc32
>> 24) & 0xff);
1402 utc48
[3] = (mDNSu8
)((utc32
>> 16) & 0xff);
1403 utc48
[4] = (mDNSu8
)((utc32
>> 8) & 0xff);
1404 utc48
[5] = (mDNSu8
)( utc32
& 0xff);
1406 mDNSPlatformMemCopy(utc48
, rdata
, 6);
1408 MD5_Update(&c
, utc48
, 6);
1411 buf
= mDNSOpaque16fromIntVal(300); // 300 sec is fudge recommended in RFC 2485
1412 rdata
[0] = buf
.b
[0];
1413 rdata
[1] = buf
.b
[1];
1414 rdata
+= sizeof(mDNSOpaque16
);
1415 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1417 // digest error and other data len (both zero) - we'll add them to the rdata later
1418 buf
.NotAnInteger
= 0;
1419 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // error
1420 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // other data len
1422 // finish the message & tsig var hash
1423 MD5_Final(digest
, &c
);
1425 // perform outer MD5 (outer key pad, inner digest)
1427 MD5_Update(&c
, info
->key
.opad
, HMAC_LEN
);
1428 MD5_Update(&c
, digest
, MD5_LEN
);
1429 MD5_Final(digest
, &c
);
1431 // set remaining rdata fields
1432 rdata
[0] = (mDNSu8
)((MD5_LEN
>> 8) & 0xff);
1433 rdata
[1] = (mDNSu8
)( MD5_LEN
& 0xff);
1434 rdata
+= sizeof(mDNSOpaque16
);
1435 mDNSPlatformMemCopy(digest
, rdata
, MD5_LEN
); // MAC
1437 rdata
[0] = msg
->h
.id
.b
[0]; // original ID
1438 rdata
[1] = msg
->h
.id
.b
[1];
1439 rdata
[2] = 0; // no error
1441 rdata
[4] = 0; // other data len
1445 tsig
.resrec
.rdlength
= (mDNSu16
)(rdata
- tsig
.resrec
.rdata
->u
.data
);
1446 *end
= PutResourceRecordTTLJumbo(msg
, ptr
, numAdditionals
, &tsig
.resrec
, 0);
1447 if (!*end
) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); return mDNSNULL
; }
1449 // update num additionals
1450 countPtr
= (mDNSu8
*)&msg
->h
.numAdditionals
; // increment (network-byte ordered) header value
1451 *countPtr
++ = (mDNSu8
)(*numAdditionals
>> 8);
1452 *countPtr
++ = (mDNSu8
)(*numAdditionals
& 0xFF);