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.15.2.1 2006/08/29 06:24:22 cheshire
21 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
23 Revision 1.15 2006/06/20 04:12:30 cheshire
24 <rdar://problem/4490961> DNS Update broken
26 Revision 1.14 2006/02/25 23:12:07 cheshire
27 <rdar://problem/4427969> Fix to avoid code generation warning/error on FreeBSD 7
29 Revision 1.13 2004/12/16 20:12:59 cheshire
30 <rdar://problem/3324626> Cache memory management improvements
32 Revision 1.12 2004/12/03 07:20:50 ksekar
33 <rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
35 Revision 1.11 2004/12/02 01:10:27 cheshire
36 Fix to compile cleanly on 64-bit x86
38 Revision 1.10 2004/11/01 20:36:04 ksekar
39 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
41 Revision 1.9 2004/10/26 09:00:12 cheshire
42 Save a few bytes by creating HMAC_MD5_AlgName as a C string instead of a 256-byte object
44 Revision 1.8 2004/09/17 01:08:48 cheshire
45 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
46 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
47 declared in that file are ONLY appropriate to single-address-space embedded applications.
48 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
50 Revision 1.7 2004/08/15 18:36:38 cheshire
51 Don't use strcpy() and strlen() on "struct domainname" objects;
52 use AssignDomainName() and DomainNameLength() instead
53 (A "struct domainname" is a collection of packed pascal strings, not a C string.)
55 Revision 1.6 2004/06/02 00:17:46 ksekar
56 Referenced original OpenSSL license headers in source file description.
58 Revision 1.5 2004/05/20 18:37:37 cheshire
61 Revision 1.4 2004/04/22 20:28:20 cheshire
62 Use existing facility of PutResourceRecordTTL() to update count field for us
64 Revision 1.3 2004/04/22 03:05:28 cheshire
65 kDNSClass_ANY should be kDNSQClass_ANY
67 Revision 1.2 2004/04/15 00:51:28 bradley
68 Minor tweaks for Windows and C++ builds. Added casts for signed/unsigned integers and 64-bit pointers.
69 Prefix some functions with mDNS to avoid conflicts. Disable benign warnings on Microsoft compilers.
71 Revision 1.1 2004/04/14 23:09:28 ksekar
72 Support for TSIG signed dynamic updates.
83 #include "mDNSEmbeddedAPI.h"
84 #include "DNSCommon.h"
86 // Disable certain benign warnings with Microsoft compilers
87 #if(defined(_MSC_VER))
88 // Disable "conditional expression is constant" warning for debug macros.
89 // Otherwise, this generates warnings for the perfectly natural construct "while(1)"
90 // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
91 #pragma warning(disable:4127)
94 // ***************************************************************************
95 #if COMPILER_LIKES_PRAGMA_MARK
96 #pragma mark - MD5 Hash Functions
100 /* The source for the has is derived CommonCrypto files CommonDigest.h, md32_common.h, md5_locl.h, md5_locl.h, and openssl/md5.h.
101 * The following changes have been made to the original sources:
102 * replaced CC_LONG w/ mDNSu32
103 * replaced CC_MD5* with MD5*
104 * replaced CC_LONG w/ mDNSu32, removed conditional #defines from md5.h
105 * removed extern decls for MD5_Init/Update/Final from CommonDigest.h
106 * removed APPLE_COMMON_DIGEST specific #defines from md5_locl.h
108 * Note: machine archetecure specific conditionals from the original sources are turned off, but are left in the code
109 * to aid in platform-specific optimizations and debugging.
110 * Sources originally distributed under the following license headers:
111 * CommonDigest.c - APSL
114 * ====================================================================
115 * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
117 * Redistribution and use in source and binary forms, with or without
118 * modification, are permitted provided that the following conditions
121 * 1. Redistributions of source code must retain the above copyright
122 * notice, this list of conditions and the following disclaimer.
124 * 2. Redistributions in binary form must reproduce the above copyright
125 * notice, this list of conditions and the following disclaimer in
126 * the documentation and/or other materials provided with the
129 * 3. All advertising materials mentioning features or use of this
130 * software must display the following acknowledgment:
131 * "This product includes software developed by the OpenSSL Project
132 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
134 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
135 * endorse or promote products derived from this software without
136 * prior written permission. For written permission, please contact
137 * licensing@OpenSSL.org.
139 * 5. Products derived from this software may not be called "OpenSSL"
140 * nor may "OpenSSL" appear in their names without prior written
141 * permission of the OpenSSL Project.
143 * 6. Redistributions of any form whatsoever must retain the following
145 * "This product includes software developed by the OpenSSL Project
146 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
148 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
149 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
150 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
151 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
152 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
153 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
154 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
155 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
156 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
157 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
158 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
159 * OF THE POSSIBILITY OF SUCH DAMAGE.
162 * md5_dgst.c, md5_locl.h
163 * ====================================================================
165 * This product includes cryptographic software written by Eric Young
166 * (eay@cryptsoft.com). This product includes software written by Tim
167 * Hudson (tjh@cryptsoft.com).
169 * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
170 * All rights reserved.
172 * This package is an SSL implementation written
173 * by Eric Young (eay@cryptsoft.com).
174 * The implementation was written so as to conform with Netscapes SSL.
176 * This library is free for commercial and non-commercial use as long as
177 * the following conditions are aheared to. The following conditions
178 * apply to all code found in this distribution, be it the RC4, RSA,
179 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
180 * included with this distribution is covered by the same copyright terms
181 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
183 * Copyright remains Eric Young's, and as such any Copyright notices in
184 * the code are not to be removed.
185 * If this package is used in a product, Eric Young should be given attribution
186 * as the author of the parts of the library used.
187 * This can be in the form of a textual message at program startup or
188 * in documentation (online or textual) provided with the package.
190 * Redistribution and use in source and binary forms, with or without
191 * modification, are permitted provided that the following conditions
193 * 1. Redistributions of source code must retain the copyright
194 * notice, this list of conditions and the following disclaimer.
195 * 2. Redistributions in binary form must reproduce the above copyright
196 * notice, this list of conditions and the following disclaimer in the
197 * documentation and/or other materials provided with the distribution.
198 * 3. All advertising materials mentioning features or use of this software
199 * must display the following acknowledgement:
200 * "This product includes cryptographic software written by
201 * Eric Young (eay@cryptsoft.com)"
202 * The word 'cryptographic' can be left out if the rouines from the library
203 * being used are not cryptographic related :-).
204 * 4. If you include any Windows specific code (or a derivative thereof) from
205 * the apps directory (application code) you must include an acknowledgement:
206 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
208 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
209 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
210 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
211 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
212 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
213 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
214 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
215 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
216 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
217 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
220 * The licence and distribution terms for any publically available version or
221 * derivative of this code cannot be changed. i.e. this code cannot simply be
222 * copied and put under another distribution licence
223 * [including the GNU Public Licence.]
227 //from CommonDigest.h
229 #define MD5_DIGEST_LENGTH 16 /* digest length in bytes */
230 #define MD5_BLOCK_BYTES 64 /* block size in bytes */
231 #define MD5_BLOCK_LONG (MD5_BLOCK_BYTES / sizeof(mDNSu32))
233 typedef struct MD5state_st
237 mDNSu32 data
[MD5_BLOCK_LONG
];
242 // from openssl/md5.h
244 #define MD5_CBLOCK 64
245 #define MD5_LBLOCK (MD5_CBLOCK/4)
246 #define MD5_DIGEST_LENGTH 16
248 int MD5_Init(MD5_CTX
*c
);
249 int MD5_Update(MD5_CTX
*c
, const void *data
, unsigned long len
);
250 int MD5_Final(unsigned char *md
, MD5_CTX
*c
);
251 void MD5_Transform(MD5_CTX
*c
, const unsigned char *b
);
255 #ifndef MD5_LONG_LOG2
256 #define MD5_LONG_LOG2 2 /* default to 32 bits */
260 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
261 # define md5_block_host_order md5_block_asm_host_order
262 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
263 void md5_block_asm_data_order_aligned (MD5_CTX
*c
, const mDNSu32
*p
,int num
);
264 # define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned
268 void md5_block_host_order (MD5_CTX
*c
, const void *p
,int num
);
269 void md5_block_data_order (MD5_CTX
*c
, const void *p
,int num
);
271 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
273 * *_block_host_order is expected to handle aligned data while
274 * *_block_data_order - unaligned. As algorithm and host (x86)
275 * are in this case of the same "endianness" these two are
276 * otherwise indistinguishable. But normally you don't want to
277 * call the same function because unaligned access in places
278 * where alignment is expected is usually a "Bad Thing". Indeed,
279 * on RISCs you get punished with BUS ERROR signal or *severe*
280 * performance degradation. Intel CPUs are in turn perfectly
281 * capable of loading unaligned data without such drastic side
282 * effect. Yes, they say it's slower than aligned load, but no
283 * exception is generated and therefore performance degradation
284 * is *incomparable* with RISCs. What we should weight here is
285 * costs of unaligned access against costs of aligning data.
286 * According to my measurements allowing unaligned access results
287 * in ~9% performance improvement on Pentium II operating at
288 * 266MHz. I won't be surprised if the difference will be higher
289 * on faster systems:-)
291 * <appro@fy.chalmers.se>
293 #define md5_block_data_order md5_block_host_order
296 #define DATA_ORDER_IS_LITTLE_ENDIAN
298 #define HASH_LONG mDNSu32
299 #define HASH_LONG_LOG2 MD5_LONG_LOG2
300 #define HASH_CTX MD5_CTX
301 #define HASH_CBLOCK MD5_CBLOCK
302 #define HASH_LBLOCK MD5_LBLOCK
304 #define HASH_UPDATE MD5_Update
305 #define HASH_TRANSFORM MD5_Transform
306 #define HASH_FINAL MD5_Final
308 #define HASH_MAKE_STRING(c,s) do { \
310 ll=(c)->A; HOST_l2c(ll,(s)); \
311 ll=(c)->B; HOST_l2c(ll,(s)); \
312 ll=(c)->C; HOST_l2c(ll,(s)); \
313 ll=(c)->D; HOST_l2c(ll,(s)); \
315 #define HASH_BLOCK_HOST_ORDER md5_block_host_order
316 #if !defined(L_ENDIAN) || defined(md5_block_data_order)
317 #define HASH_BLOCK_DATA_ORDER md5_block_data_order
319 * Little-endians (Intel and Alpha) feel better without this.
320 * It looks like memcpy does better job than generic
321 * md5_block_data_order on copying-n-aligning input data.
322 * But frankly speaking I didn't expect such result on Alpha.
323 * On the other hand I've got this with egcs-1.0.2 and if
324 * program is compiled with another (better?) compiler it
325 * might turn out other way around.
327 * <appro@fy.chalmers.se>
332 // from md32_common.h
335 * This is a generic 32 bit "collector" for message digest algorithms.
336 * Whenever needed it collects input character stream into chunks of
337 * 32 bit values and invokes a block function that performs actual hash
344 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
345 * this macro defines byte order of input stream.
347 * size of a unit chunk HASH_BLOCK operates on.
349 * has to be at lest 32 bit wide, if it's wider, then
350 * HASH_LONG_LOG2 *has to* be defined along
352 * context structure that at least contains following
357 * HASH_LONG data[HASH_LBLOCK];
362 * name of "Update" function, implemented here.
364 * name of "Transform" function, implemented here.
366 * name of "Final" function, implemented here.
367 * HASH_BLOCK_HOST_ORDER
368 * name of "block" function treating *aligned* input message
369 * in host byte order, implemented externally.
370 * HASH_BLOCK_DATA_ORDER
371 * name of "block" function treating *unaligned* input message
372 * in original (data) byte order, implemented externally (it
373 * actually is optional if data and host are of the same
376 * macro convering context variables to an ASCII hash string.
380 * B_ENDIAN or L_ENDIAN
381 * defines host byte-order.
383 * defaults to 2 if not states otherwise.
385 * assumed to be HASH_CBLOCK/4 if not stated otherwise.
386 * HASH_BLOCK_DATA_ORDER_ALIGNED
387 * alternative "block" function capable of treating
388 * aligned input message in original (data) order,
389 * implemented externally.
393 * #define DATA_ORDER_IS_LITTLE_ENDIAN
395 * #define HASH_LONG mDNSu32
396 * #define HASH_LONG_LOG2 mDNSu32_LOG2
397 * #define HASH_CTX MD5_CTX
398 * #define HASH_CBLOCK MD5_CBLOCK
399 * #define HASH_LBLOCK MD5_LBLOCK
400 * #define HASH_UPDATE MD5_Update
401 * #define HASH_TRANSFORM MD5_Transform
402 * #define HASH_FINAL MD5_Final
403 * #define HASH_BLOCK_HOST_ORDER md5_block_host_order
404 * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
406 * <appro@fy.chalmers.se>
409 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
410 #error "DATA_ORDER must be defined!"
414 #error "HASH_CBLOCK must be defined!"
417 #error "HASH_LONG must be defined!"
420 #error "HASH_CTX must be defined!"
424 #error "HASH_UPDATE must be defined!"
426 #ifndef HASH_TRANSFORM
427 #error "HASH_TRANSFORM must be defined!"
430 #error "HASH_FINAL must be defined!"
433 #ifndef HASH_BLOCK_HOST_ORDER
434 #error "HASH_BLOCK_HOST_ORDER must be defined!"
439 * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
442 #ifndef HASH_BLOCK_DATA_ORDER
443 #error "HASH_BLOCK_DATA_ORDER must be defined!"
448 #define HASH_LBLOCK (HASH_CBLOCK/4)
451 #ifndef HASH_LONG_LOG2
452 #define HASH_LONG_LOG2 2
456 * Engage compiler specific rotate intrinsic function if available.
460 # if 0 /* defined(_MSC_VER) */
461 # define ROTATE(a,n) _lrotl(a,n)
462 # elif defined(__MWERKS__)
463 # if defined(__POWERPC__)
464 # define ROTATE(a,n) (unsigned MD32_REG_T)__rlwinm((int)a,n,0,31)
465 # elif defined(__MC68K__)
466 /* Motorola specific tweak. <appro@fy.chalmers.se> */
467 # define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) )
469 # define ROTATE(a,n) __rol(a,n)
471 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
473 * Some GNU C inline assembler templates. Note that these are
474 * rotates by *constant* number of bits! But that's exactly
475 * what we need here...
477 * <appro@fy.chalmers.se>
479 # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
480 # define ROTATE(a,n) ({ register unsigned int ret; \
488 # elif defined(__powerpc) || defined(__ppc)
489 # define ROTATE(a,n) ({ register unsigned int ret; \
491 "rlwinm %0,%1,%2,0,31" \
500 * Engage compiler specific "fetch in reverse byte order"
501 * intrinsic function if available.
503 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
504 /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
505 # if (defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)) && !defined(I386_ONLY)
506 # define BE_FETCH32(a) ({ register unsigned int l=(a);\
509 : "=r"(l) : "0"(l)); \
512 # elif defined(__powerpc)
513 # define LE_FETCH32(a) ({ register unsigned int l; \
521 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
522 # define LE_FETCH32(a) ({ register unsigned int l; \
524 "lda [%1]#ASI_PRIMARY_LITTLE,%0"\
531 #endif /* PEDANTIC */
533 #if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */
534 /* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
536 /* 5 instructions with rotate instruction, else 9 */
537 #define REVERSE_FETCH32(a,l) ( \
538 l=*(const HASH_LONG *)(a), \
539 ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \
542 /* 6 instructions with rotate instruction, else 8 */
543 #define REVERSE_FETCH32(a,l) ( \
544 l=*(const HASH_LONG *)(a), \
545 l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \
549 * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
550 * It's rewritten as above for two reasons:
551 * - RISCs aren't good at long constants and have to explicitely
552 * compose 'em with several (well, usually 2) instructions in a
553 * register before performing the actual operation and (as you
554 * already realized:-) having same constant should inspire the
555 * compiler to permanently allocate the only register for it;
556 * - most modern CPUs have two ALUs, but usually only one has
557 * circuitry for shifts:-( this minor tweak inspires compiler
558 * to schedule shift instructions in a better way...
560 * <appro@fy.chalmers.se>
566 #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
570 * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
571 * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
572 * and host are of the same "endianess". It's possible to mask
573 * this with blank #define HASH_BLOCK_DATA_ORDER though...
575 * <appro@fy.chalmers.se>
577 #if defined(B_ENDIAN)
578 # if defined(DATA_ORDER_IS_BIG_ENDIAN)
579 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
580 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
582 # elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
583 # ifndef HOST_FETCH32
585 # define HOST_FETCH32(p,l) LE_FETCH32(p)
586 # elif defined(REVERSE_FETCH32)
587 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
591 #elif defined(L_ENDIAN)
592 # if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
593 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
594 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
596 # elif defined(DATA_ORDER_IS_BIG_ENDIAN)
597 # ifndef HOST_FETCH32
599 # define HOST_FETCH32(p,l) BE_FETCH32(p)
600 # elif defined(REVERSE_FETCH32)
601 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
607 #if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
608 #ifndef HASH_BLOCK_DATA_ORDER
609 #error "HASH_BLOCK_DATA_ORDER must be defined!"
613 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
615 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
616 l|=(((unsigned long)(*((c)++)))<<16), \
617 l|=(((unsigned long)(*((c)++)))<< 8), \
618 l|=(((unsigned long)(*((c)++))) ), \
620 #define HOST_p_c2l(c,l,n) { \
622 case 0: l =((unsigned long)(*((c)++)))<<24; \
623 case 1: l|=((unsigned long)(*((c)++)))<<16; \
624 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
625 case 3: l|=((unsigned long)(*((c)++))); \
627 #define HOST_p_c2l_p(c,l,sc,len) { \
629 case 0: l =((unsigned long)(*((c)++)))<<24; \
630 if (--len == 0) break; \
631 case 1: l|=((unsigned long)(*((c)++)))<<16; \
632 if (--len == 0) break; \
633 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
635 /* NOTE the pointer is not incremented at the end of this */
636 #define HOST_c2l_p(c,l,n) { \
639 case 3: l =((unsigned long)(*(--(c))))<< 8; \
640 case 2: l|=((unsigned long)(*(--(c))))<<16; \
641 case 1: l|=((unsigned long)(*(--(c))))<<24; \
643 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
644 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
645 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
646 *((c)++)=(unsigned char)(((l) )&0xff), \
649 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
651 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
652 l|=(((unsigned long)(*((c)++)))<< 8), \
653 l|=(((unsigned long)(*((c)++)))<<16), \
654 l|=(((unsigned long)(*((c)++)))<<24), \
656 #define HOST_p_c2l(c,l,n) { \
658 case 0: l =((unsigned long)(*((c)++))); \
659 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
660 case 2: l|=((unsigned long)(*((c)++)))<<16; \
661 case 3: l|=((unsigned long)(*((c)++)))<<24; \
663 #define HOST_p_c2l_p(c,l,sc,len) { \
665 case 0: l =((unsigned long)(*((c)++))); \
666 if (--len == 0) break; \
667 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
668 if (--len == 0) break; \
669 case 2: l|=((unsigned long)(*((c)++)))<<16; \
671 /* NOTE the pointer is not incremented at the end of this */
672 #define HOST_c2l_p(c,l,n) { \
675 case 3: l =((unsigned long)(*(--(c))))<<16; \
676 case 2: l|=((unsigned long)(*(--(c))))<< 8; \
677 case 1: l|=((unsigned long)(*(--(c)))); \
679 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
680 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
681 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
682 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
688 * Time for some action:-)
691 int HASH_UPDATE (HASH_CTX
*c
, const void *data_
, unsigned long len
)
693 const unsigned char *data
=(const unsigned char *)data_
;
694 register HASH_LONG
* p
;
695 register unsigned long l
;
698 if (len
==0) return 1;
700 l
=(c
->Nl
+(len
<<3))&0xffffffffL
;
701 /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
702 * Wei Dai <weidai@eskimo.com> for pointing it out. */
703 if (l
< c
->Nl
) /* overflow */
714 if ((c
->num
+len
) >= HASH_CBLOCK
)
716 l
=p
[sw
]; HOST_p_c2l(data
,l
,sc
); p
[sw
++]=l
;
717 for (; sw
<HASH_LBLOCK
; sw
++)
719 HOST_c2l(data
,l
); p
[sw
]=l
;
721 HASH_BLOCK_HOST_ORDER (c
,p
,1);
722 len
-=(HASH_CBLOCK
-c
->num
);
724 /* drop through and do the rest */
729 if ((sc
+len
) < 4) /* ugly, add char's to a word */
731 l
=p
[sw
]; HOST_p_c2l_p(data
,l
,sc
,len
); p
[sw
]=l
;
739 HOST_p_c2l(data
,l
,sc
);
741 for (; sw
< ew
; sw
++)
743 HOST_c2l(data
,l
); p
[sw
]=l
;
747 HOST_c2l_p(data
,l
,ec
); p
[sw
]=l
;
754 sw
=(int)(len
/HASH_CBLOCK
);
757 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
759 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
760 * only if sizeof(HASH_LONG)==4.
762 if ((((unsigned long)data
)%4
) == 0)
764 /* data is properly aligned so that we can cast it: */
765 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,(HASH_LONG
*)data
,sw
);
771 #if !defined(HASH_BLOCK_DATA_ORDER)
774 memcpy (p
=c
->data
,data
,HASH_CBLOCK
);
775 HASH_BLOCK_DATA_ORDER_ALIGNED(c
,p
,1);
781 #if defined(HASH_BLOCK_DATA_ORDER)
783 HASH_BLOCK_DATA_ORDER(c
,data
,sw
);
795 ew
=(int)(len
>>2); /* words to copy */
799 HOST_c2l(data
,l
); *p
=l
;
801 HOST_c2l_p(data
,l
,ec
);
808 void HASH_TRANSFORM (HASH_CTX
*c
, const unsigned char *data
)
810 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
811 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
,1);
815 #if !defined(HASH_BLOCK_DATA_ORDER)
817 memcpy (c
->data
,data
,HASH_CBLOCK
);
818 HASH_BLOCK_DATA_ORDER_ALIGNED (c
,c
->data
,1);
822 #if defined(HASH_BLOCK_DATA_ORDER)
823 HASH_BLOCK_DATA_ORDER (c
,data
,1);
828 int HASH_FINAL (unsigned char *md
, HASH_CTX
*c
)
830 register HASH_LONG
*p
;
831 register unsigned long l
;
833 static const unsigned char end
[4]={0x80,0x00,0x00,0x00};
834 const unsigned char *cp
=end
;
836 /* c->num should definitly have room for at least one more byte. */
842 /* purify often complains about the following line as an
843 * Uninitialized Memory Read. While this can be true, the
844 * following p_c2l macro will reset l when that case is true.
845 * This is because j&0x03 contains the number of 'valid' bytes
846 * already in p[i]. If and only if j&0x03 == 0, the UMR will
847 * occur but this is also the only time p_c2l will do
848 * l= *(cp++) instead of l|= *(cp++)
849 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
852 if (j
==0) p
[i
]=0; /* Yeah, but that's not the way to fix it:-) */
856 l
= (j
==0) ? 0 : p
[i
];
858 HOST_p_c2l(cp
,l
,j
); p
[i
++]=l
; /* i is the next 'undefined word' */
860 if (i
>(HASH_LBLOCK
-2)) /* save room for Nl and Nh */
862 if (i
<HASH_LBLOCK
) p
[i
]=0;
863 HASH_BLOCK_HOST_ORDER (c
,p
,1);
866 for (; i
<(HASH_LBLOCK
-2); i
++)
869 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
870 p
[HASH_LBLOCK
-2]=c
->Nh
;
871 p
[HASH_LBLOCK
-1]=c
->Nl
;
872 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
873 p
[HASH_LBLOCK
-2]=c
->Nl
;
874 p
[HASH_LBLOCK
-1]=c
->Nh
;
876 HASH_BLOCK_HOST_ORDER (c
,p
,1);
878 #ifndef HASH_MAKE_STRING
879 #error "HASH_MAKE_STRING must be defined!"
881 HASH_MAKE_STRING(c
,md
);
885 /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
886 * but I'm not worried :-)
887 OPENSSL_cleanse((void *)c,sizeof(HASH_CTX));
893 #define MD32_REG_T long
895 * This comment was originaly written for MD5, which is why it
896 * discusses A-D. But it basically applies to all 32-bit digests,
897 * which is why it was moved to common header file.
899 * In case you wonder why A-D are declared as long and not
900 * as mDNSu32. Doing so results in slight performance
901 * boost on LP64 architectures. The catch is we don't
902 * really care if 32 MSBs of a 64-bit register get polluted
903 * with eventual overflows as we *save* only 32 LSBs in
904 * *either* case. Now declaring 'em long excuses the compiler
905 * from keeping 32 MSBs zeroed resulting in 13% performance
906 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
907 * Well, to be honest it should say that this *prevents*
908 * performance degradation.
909 * <appro@fy.chalmers.se>
910 * Apparently there're LP64 compilers that generate better
911 * code if A-D are declared int. Most notably GCC-x86_64
912 * generates better code.
913 * <appro@fy.chalmers.se>
918 // from md5_locl.h (continued)
921 #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
922 #define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
925 /* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
926 * simplified to the code below. Wei attributes these optimizations
927 * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
929 #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
930 #define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c))
931 #define H(b,c,d) ((b) ^ (c) ^ (d))
932 #define I(b,c,d) (((~(d)) | (b)) ^ (c))
934 #define R0(a,b,c,d,k,s,t) { \
935 a+=((k)+(t)+F((b),(c),(d))); \
939 #define R1(a,b,c,d,k,s,t) { \
940 a+=((k)+(t)+G((b),(c),(d))); \
944 #define R2(a,b,c,d,k,s,t) { \
945 a+=((k)+(t)+H((b),(c),(d))); \
949 #define R3(a,b,c,d,k,s,t) { \
950 a+=((k)+(t)+I((b),(c),(d))); \
957 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
960 #define INIT_DATA_A (unsigned long)0x67452301L
961 #define INIT_DATA_B (unsigned long)0xefcdab89L
962 #define INIT_DATA_C (unsigned long)0x98badcfeL
963 #define INIT_DATA_D (unsigned long)0x10325476L
965 int MD5_Init(MD5_CTX
*c
)
977 #ifndef md5_block_host_order
978 void md5_block_host_order (MD5_CTX
*c
, const void *data
, int num
)
980 const mDNSu32
*X
=(const mDNSu32
*)data
;
981 register unsigned MD32_REG_T A
,B
,C
,D
;
988 for (;num
--;X
+=HASH_LBLOCK
)
991 R0(A
,B
,C
,D
,X
[ 0], 7,0xd76aa478L
);
992 R0(D
,A
,B
,C
,X
[ 1],12,0xe8c7b756L
);
993 R0(C
,D
,A
,B
,X
[ 2],17,0x242070dbL
);
994 R0(B
,C
,D
,A
,X
[ 3],22,0xc1bdceeeL
);
995 R0(A
,B
,C
,D
,X
[ 4], 7,0xf57c0fafL
);
996 R0(D
,A
,B
,C
,X
[ 5],12,0x4787c62aL
);
997 R0(C
,D
,A
,B
,X
[ 6],17,0xa8304613L
);
998 R0(B
,C
,D
,A
,X
[ 7],22,0xfd469501L
);
999 R0(A
,B
,C
,D
,X
[ 8], 7,0x698098d8L
);
1000 R0(D
,A
,B
,C
,X
[ 9],12,0x8b44f7afL
);
1001 R0(C
,D
,A
,B
,X
[10],17,0xffff5bb1L
);
1002 R0(B
,C
,D
,A
,X
[11],22,0x895cd7beL
);
1003 R0(A
,B
,C
,D
,X
[12], 7,0x6b901122L
);
1004 R0(D
,A
,B
,C
,X
[13],12,0xfd987193L
);
1005 R0(C
,D
,A
,B
,X
[14],17,0xa679438eL
);
1006 R0(B
,C
,D
,A
,X
[15],22,0x49b40821L
);
1008 R1(A
,B
,C
,D
,X
[ 1], 5,0xf61e2562L
);
1009 R1(D
,A
,B
,C
,X
[ 6], 9,0xc040b340L
);
1010 R1(C
,D
,A
,B
,X
[11],14,0x265e5a51L
);
1011 R1(B
,C
,D
,A
,X
[ 0],20,0xe9b6c7aaL
);
1012 R1(A
,B
,C
,D
,X
[ 5], 5,0xd62f105dL
);
1013 R1(D
,A
,B
,C
,X
[10], 9,0x02441453L
);
1014 R1(C
,D
,A
,B
,X
[15],14,0xd8a1e681L
);
1015 R1(B
,C
,D
,A
,X
[ 4],20,0xe7d3fbc8L
);
1016 R1(A
,B
,C
,D
,X
[ 9], 5,0x21e1cde6L
);
1017 R1(D
,A
,B
,C
,X
[14], 9,0xc33707d6L
);
1018 R1(C
,D
,A
,B
,X
[ 3],14,0xf4d50d87L
);
1019 R1(B
,C
,D
,A
,X
[ 8],20,0x455a14edL
);
1020 R1(A
,B
,C
,D
,X
[13], 5,0xa9e3e905L
);
1021 R1(D
,A
,B
,C
,X
[ 2], 9,0xfcefa3f8L
);
1022 R1(C
,D
,A
,B
,X
[ 7],14,0x676f02d9L
);
1023 R1(B
,C
,D
,A
,X
[12],20,0x8d2a4c8aL
);
1025 R2(A
,B
,C
,D
,X
[ 5], 4,0xfffa3942L
);
1026 R2(D
,A
,B
,C
,X
[ 8],11,0x8771f681L
);
1027 R2(C
,D
,A
,B
,X
[11],16,0x6d9d6122L
);
1028 R2(B
,C
,D
,A
,X
[14],23,0xfde5380cL
);
1029 R2(A
,B
,C
,D
,X
[ 1], 4,0xa4beea44L
);
1030 R2(D
,A
,B
,C
,X
[ 4],11,0x4bdecfa9L
);
1031 R2(C
,D
,A
,B
,X
[ 7],16,0xf6bb4b60L
);
1032 R2(B
,C
,D
,A
,X
[10],23,0xbebfbc70L
);
1033 R2(A
,B
,C
,D
,X
[13], 4,0x289b7ec6L
);
1034 R2(D
,A
,B
,C
,X
[ 0],11,0xeaa127faL
);
1035 R2(C
,D
,A
,B
,X
[ 3],16,0xd4ef3085L
);
1036 R2(B
,C
,D
,A
,X
[ 6],23,0x04881d05L
);
1037 R2(A
,B
,C
,D
,X
[ 9], 4,0xd9d4d039L
);
1038 R2(D
,A
,B
,C
,X
[12],11,0xe6db99e5L
);
1039 R2(C
,D
,A
,B
,X
[15],16,0x1fa27cf8L
);
1040 R2(B
,C
,D
,A
,X
[ 2],23,0xc4ac5665L
);
1042 R3(A
,B
,C
,D
,X
[ 0], 6,0xf4292244L
);
1043 R3(D
,A
,B
,C
,X
[ 7],10,0x432aff97L
);
1044 R3(C
,D
,A
,B
,X
[14],15,0xab9423a7L
);
1045 R3(B
,C
,D
,A
,X
[ 5],21,0xfc93a039L
);
1046 R3(A
,B
,C
,D
,X
[12], 6,0x655b59c3L
);
1047 R3(D
,A
,B
,C
,X
[ 3],10,0x8f0ccc92L
);
1048 R3(C
,D
,A
,B
,X
[10],15,0xffeff47dL
);
1049 R3(B
,C
,D
,A
,X
[ 1],21,0x85845dd1L
);
1050 R3(A
,B
,C
,D
,X
[ 8], 6,0x6fa87e4fL
);
1051 R3(D
,A
,B
,C
,X
[15],10,0xfe2ce6e0L
);
1052 R3(C
,D
,A
,B
,X
[ 6],15,0xa3014314L
);
1053 R3(B
,C
,D
,A
,X
[13],21,0x4e0811a1L
);
1054 R3(A
,B
,C
,D
,X
[ 4], 6,0xf7537e82L
);
1055 R3(D
,A
,B
,C
,X
[11],10,0xbd3af235L
);
1056 R3(C
,D
,A
,B
,X
[ 2],15,0x2ad7d2bbL
);
1057 R3(B
,C
,D
,A
,X
[ 9],21,0xeb86d391L
);
1067 #ifndef md5_block_data_order
1071 void md5_block_data_order (MD5_CTX
*c
, const void *data_
, int num
)
1073 const unsigned char *data
=data_
;
1074 register unsigned MD32_REG_T A
,B
,C
,D
,l
;
1076 /* See comment in crypto/sha/sha_locl.h for details. */
1077 unsigned MD32_REG_T XX0
, XX1
, XX2
, XX3
, XX4
, XX5
, XX6
, XX7
,
1078 XX8
, XX9
,XX10
,XX11
,XX12
,XX13
,XX14
,XX15
;
1081 mDNSu32 XX
[MD5_LBLOCK
];
1092 HOST_c2l(data
,l
); X( 0)=l
; HOST_c2l(data
,l
); X( 1)=l
;
1094 R0(A
,B
,C
,D
,X( 0), 7,0xd76aa478L
); HOST_c2l(data
,l
); X( 2)=l
;
1095 R0(D
,A
,B
,C
,X( 1),12,0xe8c7b756L
); HOST_c2l(data
,l
); X( 3)=l
;
1096 R0(C
,D
,A
,B
,X( 2),17,0x242070dbL
); HOST_c2l(data
,l
); X( 4)=l
;
1097 R0(B
,C
,D
,A
,X( 3),22,0xc1bdceeeL
); HOST_c2l(data
,l
); X( 5)=l
;
1098 R0(A
,B
,C
,D
,X( 4), 7,0xf57c0fafL
); HOST_c2l(data
,l
); X( 6)=l
;
1099 R0(D
,A
,B
,C
,X( 5),12,0x4787c62aL
); HOST_c2l(data
,l
); X( 7)=l
;
1100 R0(C
,D
,A
,B
,X( 6),17,0xa8304613L
); HOST_c2l(data
,l
); X( 8)=l
;
1101 R0(B
,C
,D
,A
,X( 7),22,0xfd469501L
); HOST_c2l(data
,l
); X( 9)=l
;
1102 R0(A
,B
,C
,D
,X( 8), 7,0x698098d8L
); HOST_c2l(data
,l
); X(10)=l
;
1103 R0(D
,A
,B
,C
,X( 9),12,0x8b44f7afL
); HOST_c2l(data
,l
); X(11)=l
;
1104 R0(C
,D
,A
,B
,X(10),17,0xffff5bb1L
); HOST_c2l(data
,l
); X(12)=l
;
1105 R0(B
,C
,D
,A
,X(11),22,0x895cd7beL
); HOST_c2l(data
,l
); X(13)=l
;
1106 R0(A
,B
,C
,D
,X(12), 7,0x6b901122L
); HOST_c2l(data
,l
); X(14)=l
;
1107 R0(D
,A
,B
,C
,X(13),12,0xfd987193L
); HOST_c2l(data
,l
); X(15)=l
;
1108 R0(C
,D
,A
,B
,X(14),17,0xa679438eL
);
1109 R0(B
,C
,D
,A
,X(15),22,0x49b40821L
);
1111 R1(A
,B
,C
,D
,X( 1), 5,0xf61e2562L
);
1112 R1(D
,A
,B
,C
,X( 6), 9,0xc040b340L
);
1113 R1(C
,D
,A
,B
,X(11),14,0x265e5a51L
);
1114 R1(B
,C
,D
,A
,X( 0),20,0xe9b6c7aaL
);
1115 R1(A
,B
,C
,D
,X( 5), 5,0xd62f105dL
);
1116 R1(D
,A
,B
,C
,X(10), 9,0x02441453L
);
1117 R1(C
,D
,A
,B
,X(15),14,0xd8a1e681L
);
1118 R1(B
,C
,D
,A
,X( 4),20,0xe7d3fbc8L
);
1119 R1(A
,B
,C
,D
,X( 9), 5,0x21e1cde6L
);
1120 R1(D
,A
,B
,C
,X(14), 9,0xc33707d6L
);
1121 R1(C
,D
,A
,B
,X( 3),14,0xf4d50d87L
);
1122 R1(B
,C
,D
,A
,X( 8),20,0x455a14edL
);
1123 R1(A
,B
,C
,D
,X(13), 5,0xa9e3e905L
);
1124 R1(D
,A
,B
,C
,X( 2), 9,0xfcefa3f8L
);
1125 R1(C
,D
,A
,B
,X( 7),14,0x676f02d9L
);
1126 R1(B
,C
,D
,A
,X(12),20,0x8d2a4c8aL
);
1128 R2(A
,B
,C
,D
,X( 5), 4,0xfffa3942L
);
1129 R2(D
,A
,B
,C
,X( 8),11,0x8771f681L
);
1130 R2(C
,D
,A
,B
,X(11),16,0x6d9d6122L
);
1131 R2(B
,C
,D
,A
,X(14),23,0xfde5380cL
);
1132 R2(A
,B
,C
,D
,X( 1), 4,0xa4beea44L
);
1133 R2(D
,A
,B
,C
,X( 4),11,0x4bdecfa9L
);
1134 R2(C
,D
,A
,B
,X( 7),16,0xf6bb4b60L
);
1135 R2(B
,C
,D
,A
,X(10),23,0xbebfbc70L
);
1136 R2(A
,B
,C
,D
,X(13), 4,0x289b7ec6L
);
1137 R2(D
,A
,B
,C
,X( 0),11,0xeaa127faL
);
1138 R2(C
,D
,A
,B
,X( 3),16,0xd4ef3085L
);
1139 R2(B
,C
,D
,A
,X( 6),23,0x04881d05L
);
1140 R2(A
,B
,C
,D
,X( 9), 4,0xd9d4d039L
);
1141 R2(D
,A
,B
,C
,X(12),11,0xe6db99e5L
);
1142 R2(C
,D
,A
,B
,X(15),16,0x1fa27cf8L
);
1143 R2(B
,C
,D
,A
,X( 2),23,0xc4ac5665L
);
1145 R3(A
,B
,C
,D
,X( 0), 6,0xf4292244L
);
1146 R3(D
,A
,B
,C
,X( 7),10,0x432aff97L
);
1147 R3(C
,D
,A
,B
,X(14),15,0xab9423a7L
);
1148 R3(B
,C
,D
,A
,X( 5),21,0xfc93a039L
);
1149 R3(A
,B
,C
,D
,X(12), 6,0x655b59c3L
);
1150 R3(D
,A
,B
,C
,X( 3),10,0x8f0ccc92L
);
1151 R3(C
,D
,A
,B
,X(10),15,0xffeff47dL
);
1152 R3(B
,C
,D
,A
,X( 1),21,0x85845dd1L
);
1153 R3(A
,B
,C
,D
,X( 8), 6,0x6fa87e4fL
);
1154 R3(D
,A
,B
,C
,X(15),10,0xfe2ce6e0L
);
1155 R3(C
,D
,A
,B
,X( 6),15,0xa3014314L
);
1156 R3(B
,C
,D
,A
,X(13),21,0x4e0811a1L
);
1157 R3(A
,B
,C
,D
,X( 4), 6,0xf7537e82L
);
1158 R3(D
,A
,B
,C
,X(11),10,0xbd3af235L
);
1159 R3(C
,D
,A
,B
,X( 2),15,0x2ad7d2bbL
);
1160 R3(B
,C
,D
,A
,X( 9),21,0xeb86d391L
);
1172 // ***************************************************************************
1173 #if COMPILER_LIKES_PRAGMA_MARK
1174 #pragma mark - base64 -> binary conversion
1177 static const char Base64
[] =
1178 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1179 static const char Pad64
= '=';
1182 #define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
1184 static const char *mDNSstrchr(const char *s
, int c
)
1188 if (c
== *s
) return s
;
1189 if (!*s
) return mDNSNULL
;
1194 // skips all whitespace anywhere.
1195 // converts characters, four at a time, starting at (or after)
1196 // src from base - 64 numbers into three 8 bit bytes in the target area.
1197 // it returns the number of data bytes stored at the target, or -1 on error.
1198 // adapted from BIND sources
1200 mDNSexport mDNSs32
DNSDigest_Base64ToBin(const char *src
, mDNSu8
*target
, mDNSu32 targsize
)
1202 int tarindex
, state
, ch
;
1208 while ((ch
= *src
++) != '\0') {
1209 if (mDNSisspace(ch
)) /* Skip whitespace anywhere. */
1215 pos
= mDNSstrchr(Base64
, ch
);
1216 if (pos
== 0) /* A non-base64 character. */
1222 if ((mDNSu32
)tarindex
>= targsize
)
1224 target
[tarindex
] = (mDNSu8
)((pos
- Base64
) << 2);
1230 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1232 target
[tarindex
] |= (pos
- Base64
) >> 4;
1233 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x0f) << 4);
1240 if ((mDNSu32
)tarindex
+ 1 >= targsize
)
1242 target
[tarindex
] |= (pos
- Base64
) >> 2;
1243 target
[tarindex
+1] = (mDNSu8
)(((pos
- Base64
) & 0x03) << 6);
1250 if ((mDNSu32
)tarindex
>= targsize
)
1252 target
[tarindex
] |= (pos
- Base64
);
1263 * We are done decoding Base-64 chars. Let's see if we ended
1264 * on a byte boundary, and/or with erroneous trailing characters.
1267 if (ch
== Pad64
) { /* We got a pad char. */
1268 ch
= *src
++; /* Skip it, get next. */
1270 case 0: /* Invalid = in first position */
1271 case 1: /* Invalid = in second position */
1274 case 2: /* Valid, means one byte of info */
1275 /* Skip any number of spaces. */
1276 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1277 if (!mDNSisspace(ch
))
1279 /* Make sure there is another trailing = sign. */
1282 ch
= *src
++; /* Skip the = */
1283 /* Fall through to "single trailing =" case. */
1286 case 3: /* Valid, means two bytes of info */
1288 * We know this char is an =. Is there anything but
1289 * whitespace after it?
1291 for ((void)mDNSNULL
; ch
!= '\0'; ch
= *src
++)
1292 if (!mDNSisspace(ch
))
1296 * Now make sure for cases 2 and 3 that the "extra"
1297 * bits that slopped past the last full byte were
1298 * zeros. If we don't check them, they become a
1299 * subliminal channel.
1301 if (target
&& target
[tarindex
] != 0)
1306 * We ended by seeing the end of the string. Make sure we
1307 * have no partial bytes lying around.
1317 // ***************************************************************************
1318 #if COMPILER_LIKES_PRAGMA_MARK
1319 #pragma mark - API exported to mDNS Core
1323 #define HMAC_IPAD 0x36
1324 #define HMAC_OPAD 0x5c
1327 #define HMAC_MD5_AlgName (*(const domainname*) "\010" "hmac-md5" "\007" "sig-alg" "\003" "reg" "\003" "int")
1329 // Adapted from Appendix, RFC 2104
1330 mDNSexport
void DNSDigest_ConstructHMACKey(uDNS_AuthInfo
*info
, const mDNSu8
*key
, mDNSu32 len
)
1333 mDNSu8 buf
[MD5_LEN
];
1336 // If key is longer than HMAC_LEN reset it to MD5(key)
1340 MD5_Update(&k
, key
, len
);
1346 // store key in pads
1347 mDNSPlatformMemZero(info
->key
.ipad
, HMAC_LEN
);
1348 mDNSPlatformMemZero(info
->key
.opad
, HMAC_LEN
);
1349 mDNSPlatformMemCopy(key
, info
->key
.ipad
, len
);
1350 mDNSPlatformMemCopy(key
, info
->key
.opad
, len
);
1352 // XOR key with ipad and opad values
1353 for (i
= 0; i
< HMAC_LEN
; i
++)
1355 info
->key
.ipad
[i
] ^= HMAC_IPAD
;
1356 info
->key
.opad
[i
] ^= HMAC_OPAD
;
1361 mDNSexport mDNSu8
*DNSDigest_SignMessage(DNSMessage
*msg
, mDNSu8
**end
, mDNSu16
*numAdditionals
, uDNS_AuthInfo
*info
)
1364 mDNSu8
*countPtr
, *rdata
;
1367 mDNSu8 digest
[MD5_LEN
];
1373 // Init MD5 context, digest inner key pad and message
1375 MD5_Update(&c
, info
->key
.ipad
, HMAC_LEN
);
1376 MD5_Update(&c
, (mDNSu8
*)msg
, (unsigned long)(*end
- (mDNSu8
*)msg
));
1378 // Construct TSIG RR, digesting variables as apporpriate
1379 mDNSPlatformMemZero(&tsig
, sizeof(AuthRecord
));
1380 mDNS_SetupResourceRecord(&tsig
, mDNSNULL
, 0, kDNSType_TSIG
, 0, kDNSRecordTypeKnownUnique
, mDNSNULL
, mDNSNULL
);
1383 AssignDomainName(tsig
.resrec
.name
, &info
->keyname
);
1384 MD5_Update(&c
, info
->keyname
.c
, DomainNameLength(&info
->keyname
));
1387 tsig
.resrec
.rrclass
= kDNSQClass_ANY
;
1388 buf
= mDNSOpaque16fromIntVal(kDNSQClass_ANY
);
1389 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
));
1392 tsig
.resrec
.rroriginalttl
= 0;
1393 MD5_Update(&c
, (mDNSu8
*)&tsig
.resrec
.rroriginalttl
, sizeof(tsig
.resrec
.rroriginalttl
));
1396 AssignDomainName(&tsig
.resrec
.rdata
->u
.name
, &HMAC_MD5_AlgName
);
1397 len
= DomainNameLength(&HMAC_MD5_AlgName
);
1398 rdata
= tsig
.resrec
.rdata
->u
.data
+ len
;
1399 MD5_Update(&c
, HMAC_MD5_AlgName
.c
, len
);
1402 // get UTC (universal time), convert to 48-bit unsigned in network byte order
1403 utc32
= (mDNSu32
)mDNSPlatformUTC();
1404 if (utc32
== (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); return mDNSNULL
; }
1407 utc48
[2] = (mDNSu8
)((utc32
>> 24) & 0xff);
1408 utc48
[3] = (mDNSu8
)((utc32
>> 16) & 0xff);
1409 utc48
[4] = (mDNSu8
)((utc32
>> 8) & 0xff);
1410 utc48
[5] = (mDNSu8
)( utc32
& 0xff);
1412 mDNSPlatformMemCopy(utc48
, rdata
, 6);
1414 MD5_Update(&c
, utc48
, 6);
1416 // 300 sec is fudge recommended in RFC 2485
1417 rdata
[0] = (mDNSu8
)((300 >> 8) & 0xff);
1418 rdata
[1] = (mDNSu8
)( 300 & 0xff);
1419 MD5_Update(&c
, rdata
, sizeof(mDNSOpaque16
));
1420 rdata
+= sizeof(mDNSOpaque16
);
1422 // digest error and other data len (both zero) - we'll add them to the rdata later
1423 buf
.NotAnInteger
= 0;
1424 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // error
1425 MD5_Update(&c
, buf
.b
, sizeof(mDNSOpaque16
)); // other data len
1427 // finish the message & tsig var hash
1428 MD5_Final(digest
, &c
);
1430 // perform outer MD5 (outer key pad, inner digest)
1432 MD5_Update(&c
, info
->key
.opad
, HMAC_LEN
);
1433 MD5_Update(&c
, digest
, MD5_LEN
);
1434 MD5_Final(digest
, &c
);
1436 // set remaining rdata fields
1437 rdata
[0] = (mDNSu8
)((MD5_LEN
>> 8) & 0xff);
1438 rdata
[1] = (mDNSu8
)( MD5_LEN
& 0xff);
1439 rdata
+= sizeof(mDNSOpaque16
);
1440 mDNSPlatformMemCopy(digest
, rdata
, MD5_LEN
); // MAC
1442 rdata
[0] = msg
->h
.id
.b
[0]; // original ID
1443 rdata
[1] = msg
->h
.id
.b
[1];
1444 rdata
[2] = 0; // no error
1446 rdata
[4] = 0; // other data len
1450 tsig
.resrec
.rdlength
= (mDNSu16
)(rdata
- tsig
.resrec
.rdata
->u
.data
);
1451 *end
= PutResourceRecordTTLJumbo(msg
, ptr
, numAdditionals
, &tsig
.resrec
, 0);
1452 if (!*end
) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); return mDNSNULL
; }
1454 // update num additionals
1455 countPtr
= (mDNSu8
*)&msg
->h
.numAdditionals
; // increment (network-byte ordered) header value
1456 *countPtr
++ = (mDNSu8
)(*numAdditionals
>> 8);
1457 *countPtr
++ = (mDNSu8
)(*numAdditionals
& 0xFF);