]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSCore/DNSDigest.c
mDNSResponder-107.tar.gz
[apple/mdnsresponder.git] / mDNSCore / DNSDigest.c
1 /*
2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22
23 Change History (most recent first):
24
25 $Log: DNSDigest.c,v $
26 Revision 1.13 2004/12/16 20:12:59 cheshire
27 <rdar://problem/3324626> Cache memory management improvements
28
29 Revision 1.12 2004/12/03 07:20:50 ksekar
30 <rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
31
32 Revision 1.11 2004/12/02 01:10:27 cheshire
33 Fix to compile cleanly on 64-bit x86
34
35 Revision 1.10 2004/11/01 20:36:04 ksekar
36 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
37
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
40
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.
46
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.)
51
52 Revision 1.6 2004/06/02 00:17:46 ksekar
53 Referenced original OpenSSL license headers in source file description.
54
55 Revision 1.5 2004/05/20 18:37:37 cheshire
56 Fix compiler warnings
57
58 Revision 1.4 2004/04/22 20:28:20 cheshire
59 Use existing facility of PutResourceRecordTTL() to update count field for us
60
61 Revision 1.3 2004/04/22 03:05:28 cheshire
62 kDNSClass_ANY should be kDNSQClass_ANY
63
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.
67
68 Revision 1.1 2004/04/14 23:09:28 ksekar
69 Support for TSIG signed dynamic updates.
70
71
72
73 */
74
75
76 #ifdef __cplusplus
77 extern "C" {
78 #endif
79
80 #include "mDNSEmbeddedAPI.h"
81 #include "DNSCommon.h"
82
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)
89 #endif
90
91 // ***************************************************************************
92 #if COMPILER_LIKES_PRAGMA_MARK
93 #pragma mark - MD5 Hash Functions
94 #endif
95
96
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
104 *
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
109 *
110 * md32_Common.h
111 * ====================================================================
112 * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
113 *
114 * Redistribution and use in source and binary forms, with or without
115 * modification, are permitted provided that the following conditions
116 * are met:
117 *
118 * 1. Redistributions of source code must retain the above copyright
119 * notice, this list of conditions and the following disclaimer.
120 *
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
124 * distribution.
125 *
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/)"
130 *
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.
135 *
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.
139 *
140 * 6. Redistributions of any form whatsoever must retain the following
141 * acknowledgment:
142 * "This product includes software developed by the OpenSSL Project
143 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
144 *
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.
157 *
158 *
159 * md5_dgst.c, md5_locl.h
160 * ====================================================================
161 *
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).
165 *
166 * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
167 * All rights reserved.
168 *
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.
172 *
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).
179 *
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.
186 *
187 * Redistribution and use in source and binary forms, with or without
188 * modification, are permitted provided that the following conditions
189 * are met:
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)"
204 *
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
215 * SUCH DAMAGE.
216 *
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.]
221 *
222 */
223
224 //from CommonDigest.h
225
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))
229
230 typedef struct MD5state_st
231 {
232 mDNSu32 A,B,C,D;
233 mDNSu32 Nl,Nh;
234 mDNSu32 data[MD5_BLOCK_LONG];
235 int num;
236 } MD5_CTX;
237
238
239 // from openssl/md5.h
240
241 #define MD5_CBLOCK 64
242 #define MD5_LBLOCK (MD5_CBLOCK/4)
243 #define MD5_DIGEST_LENGTH 16
244
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);
249
250 // From md5_locl.h
251
252 #ifndef MD5_LONG_LOG2
253 #define MD5_LONG_LOG2 2 /* default to 32 bits */
254 #endif
255
256 #ifdef MD5_ASM
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
262 # endif
263 #endif
264
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);
267
268 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
269 /*
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:-)
287 *
288 * <appro@fy.chalmers.se>
289 */
290 #define md5_block_data_order md5_block_host_order
291 #endif
292
293 #define DATA_ORDER_IS_LITTLE_ENDIAN
294
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
300
301 #define HASH_UPDATE MD5_Update
302 #define HASH_TRANSFORM MD5_Transform
303 #define HASH_FINAL MD5_Final
304
305 #define HASH_MAKE_STRING(c,s) do { \
306 unsigned long ll; \
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)); \
311 } while (0)
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
315 /*
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.
323 *
324 * <appro@fy.chalmers.se>
325 */
326 #endif
327
328
329 // from md32_common.h
330
331 /*
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
335 * calculations.
336 *
337 * Porting guide.
338 *
339 * Obligatory macros:
340 *
341 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
342 * this macro defines byte order of input stream.
343 * HASH_CBLOCK
344 * size of a unit chunk HASH_BLOCK operates on.
345 * HASH_LONG
346 * has to be at lest 32 bit wide, if it's wider, then
347 * HASH_LONG_LOG2 *has to* be defined along
348 * HASH_CTX
349 * context structure that at least contains following
350 * members:
351 * typedef struct {
352 * ...
353 * HASH_LONG Nl,Nh;
354 * HASH_LONG data[HASH_LBLOCK];
355 * int num;
356 * ...
357 * } HASH_CTX;
358 * HASH_UPDATE
359 * name of "Update" function, implemented here.
360 * HASH_TRANSFORM
361 * name of "Transform" function, implemented here.
362 * HASH_FINAL
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
371 * "endianess").
372 * HASH_MAKE_STRING
373 * macro convering context variables to an ASCII hash string.
374 *
375 * Optional macros:
376 *
377 * B_ENDIAN or L_ENDIAN
378 * defines host byte-order.
379 * HASH_LONG_LOG2
380 * defaults to 2 if not states otherwise.
381 * HASH_LBLOCK
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.
387 *
388 * MD5 example:
389 *
390 * #define DATA_ORDER_IS_LITTLE_ENDIAN
391 *
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
402 *
403 * <appro@fy.chalmers.se>
404 */
405
406 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
407 #error "DATA_ORDER must be defined!"
408 #endif
409
410 #ifndef HASH_CBLOCK
411 #error "HASH_CBLOCK must be defined!"
412 #endif
413 #ifndef HASH_LONG
414 #error "HASH_LONG must be defined!"
415 #endif
416 #ifndef HASH_CTX
417 #error "HASH_CTX must be defined!"
418 #endif
419
420 #ifndef HASH_UPDATE
421 #error "HASH_UPDATE must be defined!"
422 #endif
423 #ifndef HASH_TRANSFORM
424 #error "HASH_TRANSFORM must be defined!"
425 #endif
426 #ifndef HASH_FINAL
427 #error "HASH_FINAL must be defined!"
428 #endif
429
430 #ifndef HASH_BLOCK_HOST_ORDER
431 #error "HASH_BLOCK_HOST_ORDER must be defined!"
432 #endif
433
434 #if 0
435 /*
436 * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
437 * isn't defined.
438 */
439 #ifndef HASH_BLOCK_DATA_ORDER
440 #error "HASH_BLOCK_DATA_ORDER must be defined!"
441 #endif
442 #endif
443
444 #ifndef HASH_LBLOCK
445 #define HASH_LBLOCK (HASH_CBLOCK/4)
446 #endif
447
448 #ifndef HASH_LONG_LOG2
449 #define HASH_LONG_LOG2 2
450 #endif
451
452 /*
453 * Engage compiler specific rotate intrinsic function if available.
454 */
455 #undef ROTATE
456 #ifndef PEDANTIC
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) )
465 # else
466 # define ROTATE(a,n) __rol(a,n)
467 # endif
468 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
469 /*
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...
473 *
474 * <appro@fy.chalmers.se>
475 */
476 # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
477 # define ROTATE(a,n) ({ register unsigned int ret; \
478 asm ( \
479 "roll %1,%0" \
480 : "=r"(ret) \
481 : "I"(n), "0"(a) \
482 : "cc"); \
483 ret; \
484 })
485 # elif defined(__powerpc) || defined(__ppc)
486 # define ROTATE(a,n) ({ register unsigned int ret; \
487 asm ( \
488 "rlwinm %0,%1,%2,0,31" \
489 : "=r"(ret) \
490 : "r"(a), "I"(n)); \
491 ret; \
492 })
493 # endif
494 # endif
495
496 /*
497 * Engage compiler specific "fetch in reverse byte order"
498 * intrinsic function if available.
499 */
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);\
504 asm ( \
505 "bswapl %0" \
506 : "=r"(l) : "0"(l)); \
507 l; \
508 })
509 # elif defined(__powerpc)
510 # define LE_FETCH32(a) ({ register unsigned int l; \
511 asm ( \
512 "lwbrx %0,0,%1" \
513 : "=r"(l) \
514 : "r"(a)); \
515 l; \
516 })
517
518 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
519 # define LE_FETCH32(a) ({ register unsigned int l; \
520 asm ( \
521 "lda [%1]#ASI_PRIMARY_LITTLE,%0"\
522 : "=r"(l) \
523 : "r"(a)); \
524 l; \
525 })
526 # endif
527 # endif
528 #endif /* PEDANTIC */
529
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> */
532 #ifdef ROTATE
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))) \
537 )
538 #else
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)), \
543 ROTATE(l,16) \
544 )
545 /*
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...
556 *
557 * <appro@fy.chalmers.se>
558 */
559 #endif
560 #endif
561
562 #ifndef ROTATE
563 #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
564 #endif
565
566 /*
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...
571 *
572 * <appro@fy.chalmers.se>
573 */
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
578 # endif
579 # elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
580 # ifndef HOST_FETCH32
581 # ifdef LE_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)
585 # endif
586 # endif
587 # endif
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
592 # endif
593 # elif defined(DATA_ORDER_IS_BIG_ENDIAN)
594 # ifndef HOST_FETCH32
595 # ifdef BE_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)
599 # endif
600 # endif
601 # endif
602 #endif
603
604 #if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
605 #ifndef HASH_BLOCK_DATA_ORDER
606 #error "HASH_BLOCK_DATA_ORDER must be defined!"
607 #endif
608 #endif
609
610 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
611
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)++))) ), \
616 l)
617 #define HOST_p_c2l(c,l,n) { \
618 switch (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)++))); \
623 } }
624 #define HOST_p_c2l_p(c,l,sc,len) { \
625 switch (sc) { \
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; \
631 } }
632 /* NOTE the pointer is not incremented at the end of this */
633 #define HOST_c2l_p(c,l,n) { \
634 l=0; (c)+=n; \
635 switch (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; \
639 } }
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), \
644 l)
645
646 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
647
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), \
652 l)
653 #define HOST_p_c2l(c,l,n) { \
654 switch (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; \
659 } }
660 #define HOST_p_c2l_p(c,l,sc,len) { \
661 switch (sc) { \
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; \
667 } }
668 /* NOTE the pointer is not incremented at the end of this */
669 #define HOST_c2l_p(c,l,n) { \
670 l=0; (c)+=n; \
671 switch (n) { \
672 case 3: l =((unsigned long)(*(--(c))))<<16; \
673 case 2: l|=((unsigned long)(*(--(c))))<< 8; \
674 case 1: l|=((unsigned long)(*(--(c)))); \
675 } }
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), \
680 l)
681
682 #endif
683
684 /*
685 * Time for some action:-)
686 */
687
688 int HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len)
689 {
690 const unsigned char *data=(const unsigned char *)data_;
691 register HASH_LONG * p;
692 register unsigned long l;
693 int sw,sc,ew,ec;
694
695 if (len==0) return 1;
696
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 */
701 c->Nh++;
702 c->Nh+=(len>>29);
703 c->Nl=l;
704
705 if (c->num != 0)
706 {
707 p=c->data;
708 sw=c->num>>2;
709 sc=c->num&0x03;
710
711 if ((c->num+len) >= HASH_CBLOCK)
712 {
713 l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
714 for (; sw<HASH_LBLOCK; sw++)
715 {
716 HOST_c2l(data,l); p[sw]=l;
717 }
718 HASH_BLOCK_HOST_ORDER (c,p,1);
719 len-=(HASH_CBLOCK-c->num);
720 c->num=0;
721 /* drop through and do the rest */
722 }
723 else
724 {
725 c->num+=len;
726 if ((sc+len) < 4) /* ugly, add char's to a word */
727 {
728 l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
729 }
730 else
731 {
732 ew=(c->num>>2);
733 ec=(c->num&0x03);
734 if (sc)
735 l=p[sw];
736 HOST_p_c2l(data,l,sc);
737 p[sw++]=l;
738 for (; sw < ew; sw++)
739 {
740 HOST_c2l(data,l); p[sw]=l;
741 }
742 if (ec)
743 {
744 HOST_c2l_p(data,l,ec); p[sw]=l;
745 }
746 }
747 return 1;
748 }
749 }
750
751 sw=(int)(len/HASH_CBLOCK);
752 if (sw > 0)
753 {
754 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
755 /*
756 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
757 * only if sizeof(HASH_LONG)==4.
758 */
759 if ((((unsigned long)data)%4) == 0)
760 {
761 /* data is properly aligned so that we can cast it: */
762 HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw);
763 sw*=HASH_CBLOCK;
764 data+=sw;
765 len-=sw;
766 }
767 else
768 #if !defined(HASH_BLOCK_DATA_ORDER)
769 while (sw--)
770 {
771 memcpy (p=c->data,data,HASH_CBLOCK);
772 HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
773 data+=HASH_CBLOCK;
774 len-=HASH_CBLOCK;
775 }
776 #endif
777 #endif
778 #if defined(HASH_BLOCK_DATA_ORDER)
779 {
780 HASH_BLOCK_DATA_ORDER(c,data,sw);
781 sw*=HASH_CBLOCK;
782 data+=sw;
783 len-=sw;
784 }
785 #endif
786 }
787
788 if (len!=0)
789 {
790 p = c->data;
791 c->num = (int)len;
792 ew=(int)(len>>2); /* words to copy */
793 ec=(int)(len&0x03);
794 for (; ew; ew--,p++)
795 {
796 HOST_c2l(data,l); *p=l;
797 }
798 HOST_c2l_p(data,l,ec);
799 *p=l;
800 }
801 return 1;
802 }
803
804
805 void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
806 {
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);
811 else
812 #if !defined(HASH_BLOCK_DATA_ORDER)
813 {
814 memcpy (c->data,data,HASH_CBLOCK);
815 HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
816 }
817 #endif
818 #endif
819 #if defined(HASH_BLOCK_DATA_ORDER)
820 HASH_BLOCK_DATA_ORDER (c,data,1);
821 #endif
822 }
823
824
825 int HASH_FINAL (unsigned char *md, HASH_CTX *c)
826 {
827 register HASH_LONG *p;
828 register unsigned long l;
829 register int i,j;
830 static const unsigned char end[4]={0x80,0x00,0x00,0x00};
831 const unsigned char *cp=end;
832
833 /* c->num should definitly have room for at least one more byte. */
834 p=c->data;
835 i=c->num>>2;
836 j=c->num&0x03;
837
838 #if 0
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
847 * 'potential bug' */
848 #ifdef PURIFY
849 if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */
850 #endif
851 l=p[i];
852 #else
853 l = (j==0) ? 0 : p[i];
854 #endif
855 HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */
856
857 if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */
858 {
859 if (i<HASH_LBLOCK) p[i]=0;
860 HASH_BLOCK_HOST_ORDER (c,p,1);
861 i=0;
862 }
863 for (; i<(HASH_LBLOCK-2); i++)
864 p[i]=0;
865
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;
872 #endif
873 HASH_BLOCK_HOST_ORDER (c,p,1);
874
875 #ifndef HASH_MAKE_STRING
876 #error "HASH_MAKE_STRING must be defined!"
877 #else
878 HASH_MAKE_STRING(c,md);
879 #endif
880
881 c->num=0;
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));
885 */
886 return 1;
887 }
888
889 #ifndef MD32_REG_T
890 #define MD32_REG_T long
891 /*
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.
895 *
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>
911 */
912 #endif
913
914
915 // from md5_locl.h (continued)
916
917 /*
918 #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
919 #define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
920 */
921
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.
925 */
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))
930
931 #define R0(a,b,c,d,k,s,t) { \
932 a+=((k)+(t)+F((b),(c),(d))); \
933 a=ROTATE(a,s); \
934 a+=b; };\
935
936 #define R1(a,b,c,d,k,s,t) { \
937 a+=((k)+(t)+G((b),(c),(d))); \
938 a=ROTATE(a,s); \
939 a+=b; };
940
941 #define R2(a,b,c,d,k,s,t) { \
942 a+=((k)+(t)+H((b),(c),(d))); \
943 a=ROTATE(a,s); \
944 a+=b; };
945
946 #define R3(a,b,c,d,k,s,t) { \
947 a+=((k)+(t)+I((b),(c),(d))); \
948 a=ROTATE(a,s); \
949 a+=b; };
950
951 // from md5_dgst.c
952
953
954 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
955 */
956
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
961
962 int MD5_Init(MD5_CTX *c)
963 {
964 c->A=INIT_DATA_A;
965 c->B=INIT_DATA_B;
966 c->C=INIT_DATA_C;
967 c->D=INIT_DATA_D;
968 c->Nl=0;
969 c->Nh=0;
970 c->num=0;
971 return 1;
972 }
973
974 #ifndef md5_block_host_order
975 void md5_block_host_order (MD5_CTX *c, const void *data, int num)
976 {
977 const mDNSu32 *X=(const mDNSu32 *)data;
978 register unsigned MD32_REG_T A,B,C,D;
979
980 A=c->A;
981 B=c->B;
982 C=c->C;
983 D=c->D;
984
985 for (;num--;X+=HASH_LBLOCK)
986 {
987 /* Round 0 */
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);
1004 /* Round 1 */
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);
1021 /* Round 2 */
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);
1038 /* Round 3 */
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);
1055
1056 A = c->A += A;
1057 B = c->B += B;
1058 C = c->C += C;
1059 D = c->D += D;
1060 }
1061 }
1062 #endif
1063
1064 #ifndef md5_block_data_order
1065 #ifdef X
1066 #undef X
1067 #endif
1068 void md5_block_data_order (MD5_CTX *c, const void *data_, int num)
1069 {
1070 const unsigned char *data=data_;
1071 register unsigned MD32_REG_T A,B,C,D,l;
1072 #ifndef MD32_XARRAY
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;
1076 # define X(i) XX##i
1077 #else
1078 mDNSu32 XX[MD5_LBLOCK];
1079 # define X(i) XX[i]
1080 #endif
1081
1082 A=c->A;
1083 B=c->B;
1084 C=c->C;
1085 D=c->D;
1086
1087 for (;num--;)
1088 {
1089 HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l;
1090 /* Round 0 */
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);
1107 /* Round 1 */
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);
1124 /* Round 2 */
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);
1141 /* Round 3 */
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);
1158
1159 A = c->A += A;
1160 B = c->B += B;
1161 C = c->C += C;
1162 D = c->D += D;
1163 }
1164 }
1165 #endif
1166
1167
1168
1169 // ***************************************************************************
1170 #if COMPILER_LIKES_PRAGMA_MARK
1171 #pragma mark - base64 -> binary conversion
1172 #endif
1173
1174 static const char Base64[] =
1175 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1176 static const char Pad64 = '=';
1177
1178
1179 #define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
1180
1181 static const char *mDNSstrchr(const char *s, int c)
1182 {
1183 while (1)
1184 {
1185 if (c == *s) return s;
1186 if (!*s) return mDNSNULL;
1187 s++;
1188 }
1189 }
1190
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
1196
1197 mDNSexport mDNSs32 DNSDigest_Base64ToBin(const char *src, mDNSu8 *target, mDNSu32 targsize)
1198 {
1199 int tarindex, state, ch;
1200 const char *pos;
1201
1202 state = 0;
1203 tarindex = 0;
1204
1205 while ((ch = *src++) != '\0') {
1206 if (mDNSisspace(ch)) /* Skip whitespace anywhere. */
1207 continue;
1208
1209 if (ch == Pad64)
1210 break;
1211
1212 pos = mDNSstrchr(Base64, ch);
1213 if (pos == 0) /* A non-base64 character. */
1214 return (-1);
1215
1216 switch (state) {
1217 case 0:
1218 if (target) {
1219 if ((mDNSu32)tarindex >= targsize)
1220 return (-1);
1221 target[tarindex] = (mDNSu8)((pos - Base64) << 2);
1222 }
1223 state = 1;
1224 break;
1225 case 1:
1226 if (target) {
1227 if ((mDNSu32)tarindex + 1 >= targsize)
1228 return (-1);
1229 target[tarindex] |= (pos - Base64) >> 4;
1230 target[tarindex+1] = (mDNSu8)(((pos - Base64) & 0x0f) << 4);
1231 }
1232 tarindex++;
1233 state = 2;
1234 break;
1235 case 2:
1236 if (target) {
1237 if ((mDNSu32)tarindex + 1 >= targsize)
1238 return (-1);
1239 target[tarindex] |= (pos - Base64) >> 2;
1240 target[tarindex+1] = (mDNSu8)(((pos - Base64) & 0x03) << 6);
1241 }
1242 tarindex++;
1243 state = 3;
1244 break;
1245 case 3:
1246 if (target) {
1247 if ((mDNSu32)tarindex >= targsize)
1248 return (-1);
1249 target[tarindex] |= (pos - Base64);
1250 }
1251 tarindex++;
1252 state = 0;
1253 break;
1254 default:
1255 return -1;
1256 }
1257 }
1258
1259 /*
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.
1262 */
1263
1264 if (ch == Pad64) { /* We got a pad char. */
1265 ch = *src++; /* Skip it, get next. */
1266 switch (state) {
1267 case 0: /* Invalid = in first position */
1268 case 1: /* Invalid = in second position */
1269 return (-1);
1270
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))
1275 break;
1276 /* Make sure there is another trailing = sign. */
1277 if (ch != Pad64)
1278 return (-1);
1279 ch = *src++; /* Skip the = */
1280 /* Fall through to "single trailing =" case. */
1281 /* FALLTHROUGH */
1282
1283 case 3: /* Valid, means two bytes of info */
1284 /*
1285 * We know this char is an =. Is there anything but
1286 * whitespace after it?
1287 */
1288 for ((void)mDNSNULL; ch != '\0'; ch = *src++)
1289 if (!mDNSisspace(ch))
1290 return (-1);
1291
1292 /*
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.
1297 */
1298 if (target && target[tarindex] != 0)
1299 return (-1);
1300 }
1301 } else {
1302 /*
1303 * We ended by seeing the end of the string. Make sure we
1304 * have no partial bytes lying around.
1305 */
1306 if (state != 0)
1307 return (-1);
1308 }
1309
1310 return (tarindex);
1311 }
1312
1313
1314 // ***************************************************************************
1315 #if COMPILER_LIKES_PRAGMA_MARK
1316 #pragma mark - API exported to mDNS Core
1317 #endif
1318
1319 // Constants
1320 #define HMAC_IPAD 0x36
1321 #define HMAC_OPAD 0x5c
1322 #define MD5_LEN 16
1323
1324 #define HMAC_MD5_AlgName (*(const domainname*) "\010" "hmac-md5" "\007" "sig-alg" "\003" "reg" "\003" "int")
1325
1326 // Adapted from Appendix, RFC 2104
1327 mDNSexport void DNSDigest_ConstructHMACKey(uDNS_AuthInfo *info, const mDNSu8 *key, mDNSu32 len)
1328 {
1329 MD5_CTX k;
1330 mDNSu8 buf[MD5_LEN];
1331 int i;
1332
1333 // If key is longer than HMAC_LEN reset it to MD5(key)
1334 if (len > HMAC_LEN)
1335 {
1336 MD5_Init(&k);
1337 MD5_Update(&k, key, len);
1338 MD5_Final(buf, &k);
1339 key = buf;
1340 len = MD5_LEN;
1341 }
1342
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);
1348
1349 // XOR key with ipad and opad values
1350 for (i = 0; i < HMAC_LEN; i++)
1351 {
1352 info->key.ipad[i] ^= HMAC_IPAD;
1353 info->key.opad[i] ^= HMAC_OPAD;
1354 }
1355
1356 }
1357
1358 mDNSexport mDNSu8 *DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, mDNSu16 *numAdditionals, uDNS_AuthInfo *info)
1359 {
1360 AuthRecord tsig;
1361 mDNSu8 *countPtr, *rdata;
1362 mDNSu32 utc32;
1363 mDNSu8 utc48[6];
1364 mDNSu8 digest[MD5_LEN];
1365 mDNSu8 *ptr = *end;
1366 mDNSu32 len;
1367 mDNSOpaque16 buf;
1368 MD5_CTX c;
1369
1370 // Init MD5 context, digest inner key pad and message
1371 MD5_Init(&c);
1372 MD5_Update(&c, info->key.ipad, HMAC_LEN);
1373 MD5_Update(&c, (mDNSu8 *)msg, (unsigned long)(*end - (mDNSu8 *)msg));
1374
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);
1378
1379 // key name
1380 AssignDomainName(tsig.resrec.name, &info->keyname);
1381 MD5_Update(&c, info->keyname.c, DomainNameLength(&info->keyname));
1382
1383 // class
1384 tsig.resrec.rrclass = kDNSQClass_ANY;
1385 buf = mDNSOpaque16fromIntVal(kDNSQClass_ANY);
1386 MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
1387
1388 // ttl
1389 tsig.resrec.rroriginalttl = 0;
1390 MD5_Update(&c, (mDNSu8 *)&tsig.resrec.rroriginalttl, sizeof(tsig.resrec.rroriginalttl));
1391
1392 // alg name
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);
1397
1398 // time
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; }
1402 utc48[0] = 0;
1403 utc48[1] = 0;
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);
1408
1409 mDNSPlatformMemCopy(utc48, rdata, 6);
1410 rdata += 6;
1411 MD5_Update(&c, utc48, 6);
1412
1413 // fudge
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));
1419
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
1424
1425 // finish the message & tsig var hash
1426 MD5_Final(digest, &c);
1427
1428 // perform outer MD5 (outer key pad, inner digest)
1429 MD5_Init(&c);
1430 MD5_Update(&c, info->key.opad, HMAC_LEN);
1431 MD5_Update(&c, digest, MD5_LEN);
1432 MD5_Final(digest, &c);
1433
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
1439 rdata += MD5_LEN;
1440 rdata[0] = msg->h.id.b[0]; // original ID
1441 rdata[1] = msg->h.id.b[1];
1442 rdata[2] = 0; // no error
1443 rdata[3] = 0;
1444 rdata[4] = 0; // other data len
1445 rdata[5] = 0;
1446 rdata += 6;
1447
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; }
1451
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);
1456
1457 return *end;
1458 }
1459
1460 #ifdef __cplusplus
1461 }
1462 #endif