]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSCore/DNSDigest.c
mDNSResponder-87.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.12 2004/12/03 07:20:50 ksekar
27 <rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
28
29 Revision 1.11 2004/12/02 01:10:27 cheshire
30 Fix to compile cleanly on 64-bit x86
31
32 Revision 1.10 2004/11/01 20:36:04 ksekar
33 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
34
35 Revision 1.9 2004/10/26 09:00:12 cheshire
36 Save a few bytes by creating HMAC_MD5_AlgName as a C string instead of a 256-byte object
37
38 Revision 1.8 2004/09/17 01:08:48 cheshire
39 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
40 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
41 declared in that file are ONLY appropriate to single-address-space embedded applications.
42 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
43
44 Revision 1.7 2004/08/15 18:36:38 cheshire
45 Don't use strcpy() and strlen() on "struct domainname" objects;
46 use AssignDomainName() and DomainNameLength() instead
47 (A "struct domainname" is a collection of packed pascal strings, not a C string.)
48
49 Revision 1.6 2004/06/02 00:17:46 ksekar
50 Referenced original OpenSSL license headers in source file description.
51
52 Revision 1.5 2004/05/20 18:37:37 cheshire
53 Fix compiler warnings
54
55 Revision 1.4 2004/04/22 20:28:20 cheshire
56 Use existing facility of PutResourceRecordTTL() to update count field for us
57
58 Revision 1.3 2004/04/22 03:05:28 cheshire
59 kDNSClass_ANY should be kDNSQClass_ANY
60
61 Revision 1.2 2004/04/15 00:51:28 bradley
62 Minor tweaks for Windows and C++ builds. Added casts for signed/unsigned integers and 64-bit pointers.
63 Prefix some functions with mDNS to avoid conflicts. Disable benign warnings on Microsoft compilers.
64
65 Revision 1.1 2004/04/14 23:09:28 ksekar
66 Support for TSIG signed dynamic updates.
67
68
69
70 */
71
72
73 #ifdef __cplusplus
74 extern "C" {
75 #endif
76
77 #include "mDNSEmbeddedAPI.h"
78 #include "DNSCommon.h"
79
80 // Disable certain benign warnings with Microsoft compilers
81 #if(defined(_MSC_VER))
82 // Disable "conditional expression is constant" warning for debug macros.
83 // Otherwise, this generates warnings for the perfectly natural construct "while(1)"
84 // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
85 #pragma warning(disable:4127)
86 #endif
87
88 // ***************************************************************************
89 #if COMPILER_LIKES_PRAGMA_MARK
90 #pragma mark - MD5 Hash Functions
91 #endif
92
93
94 /* The source for the has is derived CommonCrypto files CommonDigest.h, md32_common.h, md5_locl.h, md5_locl.h, and openssl/md5.h.
95 * The following changes have been made to the original sources:
96 * replaced CC_LONG w/ mDNSu32
97 * replaced CC_MD5* with MD5*
98 * replaced CC_LONG w/ mDNSu32, removed conditional #defines from md5.h
99 * removed extern decls for MD5_Init/Update/Final from CommonDigest.h
100 * removed APPLE_COMMON_DIGEST specific #defines from md5_locl.h
101 *
102 * Note: machine archetecure specific conditionals from the original sources are turned off, but are left in the code
103 * to aid in platform-specific optimizations and debugging.
104 * Sources originally distributed under the following license headers:
105 * CommonDigest.c - APSL
106 *
107 * md32_Common.h
108 * ====================================================================
109 * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
110 *
111 * Redistribution and use in source and binary forms, with or without
112 * modification, are permitted provided that the following conditions
113 * are met:
114 *
115 * 1. Redistributions of source code must retain the above copyright
116 * notice, this list of conditions and the following disclaimer.
117 *
118 * 2. Redistributions in binary form must reproduce the above copyright
119 * notice, this list of conditions and the following disclaimer in
120 * the documentation and/or other materials provided with the
121 * distribution.
122 *
123 * 3. All advertising materials mentioning features or use of this
124 * software must display the following acknowledgment:
125 * "This product includes software developed by the OpenSSL Project
126 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
127 *
128 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
129 * endorse or promote products derived from this software without
130 * prior written permission. For written permission, please contact
131 * licensing@OpenSSL.org.
132 *
133 * 5. Products derived from this software may not be called "OpenSSL"
134 * nor may "OpenSSL" appear in their names without prior written
135 * permission of the OpenSSL Project.
136 *
137 * 6. Redistributions of any form whatsoever must retain the following
138 * acknowledgment:
139 * "This product includes software developed by the OpenSSL Project
140 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
141 *
142 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
143 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
144 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
145 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
146 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
147 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
148 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
149 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
150 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
151 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
152 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
153 * OF THE POSSIBILITY OF SUCH DAMAGE.
154 *
155 *
156 * md5_dgst.c, md5_locl.h
157 * ====================================================================
158 *
159 * This product includes cryptographic software written by Eric Young
160 * (eay@cryptsoft.com). This product includes software written by Tim
161 * Hudson (tjh@cryptsoft.com).
162 *
163 * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
164 * All rights reserved.
165 *
166 * This package is an SSL implementation written
167 * by Eric Young (eay@cryptsoft.com).
168 * The implementation was written so as to conform with Netscapes SSL.
169 *
170 * This library is free for commercial and non-commercial use as long as
171 * the following conditions are aheared to. The following conditions
172 * apply to all code found in this distribution, be it the RC4, RSA,
173 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
174 * included with this distribution is covered by the same copyright terms
175 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
176 *
177 * Copyright remains Eric Young's, and as such any Copyright notices in
178 * the code are not to be removed.
179 * If this package is used in a product, Eric Young should be given attribution
180 * as the author of the parts of the library used.
181 * This can be in the form of a textual message at program startup or
182 * in documentation (online or textual) provided with the package.
183 *
184 * Redistribution and use in source and binary forms, with or without
185 * modification, are permitted provided that the following conditions
186 * are met:
187 * 1. Redistributions of source code must retain the copyright
188 * notice, this list of conditions and the following disclaimer.
189 * 2. Redistributions in binary form must reproduce the above copyright
190 * notice, this list of conditions and the following disclaimer in the
191 * documentation and/or other materials provided with the distribution.
192 * 3. All advertising materials mentioning features or use of this software
193 * must display the following acknowledgement:
194 * "This product includes cryptographic software written by
195 * Eric Young (eay@cryptsoft.com)"
196 * The word 'cryptographic' can be left out if the rouines from the library
197 * being used are not cryptographic related :-).
198 * 4. If you include any Windows specific code (or a derivative thereof) from
199 * the apps directory (application code) you must include an acknowledgement:
200 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
201 *
202 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
203 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
204 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
205 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
206 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
207 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
208 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
209 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
210 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
211 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
212 * SUCH DAMAGE.
213 *
214 * The licence and distribution terms for any publically available version or
215 * derivative of this code cannot be changed. i.e. this code cannot simply be
216 * copied and put under another distribution licence
217 * [including the GNU Public Licence.]
218 *
219 */
220
221 //from CommonDigest.h
222
223 #define MD5_DIGEST_LENGTH 16 /* digest length in bytes */
224 #define MD5_BLOCK_BYTES 64 /* block size in bytes */
225 #define MD5_BLOCK_LONG (MD5_BLOCK_BYTES / sizeof(mDNSu32))
226
227 typedef struct MD5state_st
228 {
229 mDNSu32 A,B,C,D;
230 mDNSu32 Nl,Nh;
231 mDNSu32 data[MD5_BLOCK_LONG];
232 int num;
233 } MD5_CTX;
234
235
236 // from openssl/md5.h
237
238 #define MD5_CBLOCK 64
239 #define MD5_LBLOCK (MD5_CBLOCK/4)
240 #define MD5_DIGEST_LENGTH 16
241
242 int MD5_Init(MD5_CTX *c);
243 int MD5_Update(MD5_CTX *c, const void *data, unsigned long len);
244 int MD5_Final(unsigned char *md, MD5_CTX *c);
245 void MD5_Transform(MD5_CTX *c, const unsigned char *b);
246
247 // From md5_locl.h
248
249 #ifndef MD5_LONG_LOG2
250 #define MD5_LONG_LOG2 2 /* default to 32 bits */
251 #endif
252
253 #ifdef MD5_ASM
254 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
255 # define md5_block_host_order md5_block_asm_host_order
256 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
257 void md5_block_asm_data_order_aligned (MD5_CTX *c, const mDNSu32 *p,int num);
258 # define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned
259 # endif
260 #endif
261
262 void md5_block_host_order (MD5_CTX *c, const void *p,int num);
263 void md5_block_data_order (MD5_CTX *c, const void *p,int num);
264
265 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
266 /*
267 * *_block_host_order is expected to handle aligned data while
268 * *_block_data_order - unaligned. As algorithm and host (x86)
269 * are in this case of the same "endianness" these two are
270 * otherwise indistinguishable. But normally you don't want to
271 * call the same function because unaligned access in places
272 * where alignment is expected is usually a "Bad Thing". Indeed,
273 * on RISCs you get punished with BUS ERROR signal or *severe*
274 * performance degradation. Intel CPUs are in turn perfectly
275 * capable of loading unaligned data without such drastic side
276 * effect. Yes, they say it's slower than aligned load, but no
277 * exception is generated and therefore performance degradation
278 * is *incomparable* with RISCs. What we should weight here is
279 * costs of unaligned access against costs of aligning data.
280 * According to my measurements allowing unaligned access results
281 * in ~9% performance improvement on Pentium II operating at
282 * 266MHz. I won't be surprised if the difference will be higher
283 * on faster systems:-)
284 *
285 * <appro@fy.chalmers.se>
286 */
287 #define md5_block_data_order md5_block_host_order
288 #endif
289
290 #define DATA_ORDER_IS_LITTLE_ENDIAN
291
292 #define HASH_LONG mDNSu32
293 #define HASH_LONG_LOG2 MD5_LONG_LOG2
294 #define HASH_CTX MD5_CTX
295 #define HASH_CBLOCK MD5_CBLOCK
296 #define HASH_LBLOCK MD5_LBLOCK
297
298 #define HASH_UPDATE MD5_Update
299 #define HASH_TRANSFORM MD5_Transform
300 #define HASH_FINAL MD5_Final
301
302 #define HASH_MAKE_STRING(c,s) do { \
303 unsigned long ll; \
304 ll=(c)->A; HOST_l2c(ll,(s)); \
305 ll=(c)->B; HOST_l2c(ll,(s)); \
306 ll=(c)->C; HOST_l2c(ll,(s)); \
307 ll=(c)->D; HOST_l2c(ll,(s)); \
308 } while (0)
309 #define HASH_BLOCK_HOST_ORDER md5_block_host_order
310 #if !defined(L_ENDIAN) || defined(md5_block_data_order)
311 #define HASH_BLOCK_DATA_ORDER md5_block_data_order
312 /*
313 * Little-endians (Intel and Alpha) feel better without this.
314 * It looks like memcpy does better job than generic
315 * md5_block_data_order on copying-n-aligning input data.
316 * But frankly speaking I didn't expect such result on Alpha.
317 * On the other hand I've got this with egcs-1.0.2 and if
318 * program is compiled with another (better?) compiler it
319 * might turn out other way around.
320 *
321 * <appro@fy.chalmers.se>
322 */
323 #endif
324
325
326 // from md32_common.h
327
328 /*
329 * This is a generic 32 bit "collector" for message digest algorithms.
330 * Whenever needed it collects input character stream into chunks of
331 * 32 bit values and invokes a block function that performs actual hash
332 * calculations.
333 *
334 * Porting guide.
335 *
336 * Obligatory macros:
337 *
338 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
339 * this macro defines byte order of input stream.
340 * HASH_CBLOCK
341 * size of a unit chunk HASH_BLOCK operates on.
342 * HASH_LONG
343 * has to be at lest 32 bit wide, if it's wider, then
344 * HASH_LONG_LOG2 *has to* be defined along
345 * HASH_CTX
346 * context structure that at least contains following
347 * members:
348 * typedef struct {
349 * ...
350 * HASH_LONG Nl,Nh;
351 * HASH_LONG data[HASH_LBLOCK];
352 * int num;
353 * ...
354 * } HASH_CTX;
355 * HASH_UPDATE
356 * name of "Update" function, implemented here.
357 * HASH_TRANSFORM
358 * name of "Transform" function, implemented here.
359 * HASH_FINAL
360 * name of "Final" function, implemented here.
361 * HASH_BLOCK_HOST_ORDER
362 * name of "block" function treating *aligned* input message
363 * in host byte order, implemented externally.
364 * HASH_BLOCK_DATA_ORDER
365 * name of "block" function treating *unaligned* input message
366 * in original (data) byte order, implemented externally (it
367 * actually is optional if data and host are of the same
368 * "endianess").
369 * HASH_MAKE_STRING
370 * macro convering context variables to an ASCII hash string.
371 *
372 * Optional macros:
373 *
374 * B_ENDIAN or L_ENDIAN
375 * defines host byte-order.
376 * HASH_LONG_LOG2
377 * defaults to 2 if not states otherwise.
378 * HASH_LBLOCK
379 * assumed to be HASH_CBLOCK/4 if not stated otherwise.
380 * HASH_BLOCK_DATA_ORDER_ALIGNED
381 * alternative "block" function capable of treating
382 * aligned input message in original (data) order,
383 * implemented externally.
384 *
385 * MD5 example:
386 *
387 * #define DATA_ORDER_IS_LITTLE_ENDIAN
388 *
389 * #define HASH_LONG mDNSu32
390 * #define HASH_LONG_LOG2 mDNSu32_LOG2
391 * #define HASH_CTX MD5_CTX
392 * #define HASH_CBLOCK MD5_CBLOCK
393 * #define HASH_LBLOCK MD5_LBLOCK
394 * #define HASH_UPDATE MD5_Update
395 * #define HASH_TRANSFORM MD5_Transform
396 * #define HASH_FINAL MD5_Final
397 * #define HASH_BLOCK_HOST_ORDER md5_block_host_order
398 * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
399 *
400 * <appro@fy.chalmers.se>
401 */
402
403 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
404 #error "DATA_ORDER must be defined!"
405 #endif
406
407 #ifndef HASH_CBLOCK
408 #error "HASH_CBLOCK must be defined!"
409 #endif
410 #ifndef HASH_LONG
411 #error "HASH_LONG must be defined!"
412 #endif
413 #ifndef HASH_CTX
414 #error "HASH_CTX must be defined!"
415 #endif
416
417 #ifndef HASH_UPDATE
418 #error "HASH_UPDATE must be defined!"
419 #endif
420 #ifndef HASH_TRANSFORM
421 #error "HASH_TRANSFORM must be defined!"
422 #endif
423 #ifndef HASH_FINAL
424 #error "HASH_FINAL must be defined!"
425 #endif
426
427 #ifndef HASH_BLOCK_HOST_ORDER
428 #error "HASH_BLOCK_HOST_ORDER must be defined!"
429 #endif
430
431 #if 0
432 /*
433 * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
434 * isn't defined.
435 */
436 #ifndef HASH_BLOCK_DATA_ORDER
437 #error "HASH_BLOCK_DATA_ORDER must be defined!"
438 #endif
439 #endif
440
441 #ifndef HASH_LBLOCK
442 #define HASH_LBLOCK (HASH_CBLOCK/4)
443 #endif
444
445 #ifndef HASH_LONG_LOG2
446 #define HASH_LONG_LOG2 2
447 #endif
448
449 /*
450 * Engage compiler specific rotate intrinsic function if available.
451 */
452 #undef ROTATE
453 #ifndef PEDANTIC
454 # if 0 /* defined(_MSC_VER) */
455 # define ROTATE(a,n) _lrotl(a,n)
456 # elif defined(__MWERKS__)
457 # if defined(__POWERPC__)
458 # define ROTATE(a,n) (unsigned MD32_REG_T)__rlwinm((int)a,n,0,31)
459 # elif defined(__MC68K__)
460 /* Motorola specific tweak. <appro@fy.chalmers.se> */
461 # define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) )
462 # else
463 # define ROTATE(a,n) __rol(a,n)
464 # endif
465 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
466 /*
467 * Some GNU C inline assembler templates. Note that these are
468 * rotates by *constant* number of bits! But that's exactly
469 * what we need here...
470 *
471 * <appro@fy.chalmers.se>
472 */
473 # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
474 # define ROTATE(a,n) ({ register unsigned int ret; \
475 asm ( \
476 "roll %1,%0" \
477 : "=r"(ret) \
478 : "I"(n), "0"(a) \
479 : "cc"); \
480 ret; \
481 })
482 # elif defined(__powerpc) || defined(__ppc)
483 # define ROTATE(a,n) ({ register unsigned int ret; \
484 asm ( \
485 "rlwinm %0,%1,%2,0,31" \
486 : "=r"(ret) \
487 : "r"(a), "I"(n)); \
488 ret; \
489 })
490 # endif
491 # endif
492
493 /*
494 * Engage compiler specific "fetch in reverse byte order"
495 * intrinsic function if available.
496 */
497 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
498 /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
499 # if (defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)) && !defined(I386_ONLY)
500 # define BE_FETCH32(a) ({ register unsigned int l=(a);\
501 asm ( \
502 "bswapl %0" \
503 : "=r"(l) : "0"(l)); \
504 l; \
505 })
506 # elif defined(__powerpc)
507 # define LE_FETCH32(a) ({ register unsigned int l; \
508 asm ( \
509 "lwbrx %0,0,%1" \
510 : "=r"(l) \
511 : "r"(a)); \
512 l; \
513 })
514
515 # elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC)
516 # define LE_FETCH32(a) ({ register unsigned int l; \
517 asm ( \
518 "lda [%1]#ASI_PRIMARY_LITTLE,%0"\
519 : "=r"(l) \
520 : "r"(a)); \
521 l; \
522 })
523 # endif
524 # endif
525 #endif /* PEDANTIC */
526
527 #if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */
528 /* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
529 #ifdef ROTATE
530 /* 5 instructions with rotate instruction, else 9 */
531 #define REVERSE_FETCH32(a,l) ( \
532 l=*(const HASH_LONG *)(a), \
533 ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \
534 )
535 #else
536 /* 6 instructions with rotate instruction, else 8 */
537 #define REVERSE_FETCH32(a,l) ( \
538 l=*(const HASH_LONG *)(a), \
539 l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \
540 ROTATE(l,16) \
541 )
542 /*
543 * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
544 * It's rewritten as above for two reasons:
545 * - RISCs aren't good at long constants and have to explicitely
546 * compose 'em with several (well, usually 2) instructions in a
547 * register before performing the actual operation and (as you
548 * already realized:-) having same constant should inspire the
549 * compiler to permanently allocate the only register for it;
550 * - most modern CPUs have two ALUs, but usually only one has
551 * circuitry for shifts:-( this minor tweak inspires compiler
552 * to schedule shift instructions in a better way...
553 *
554 * <appro@fy.chalmers.se>
555 */
556 #endif
557 #endif
558
559 #ifndef ROTATE
560 #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
561 #endif
562
563 /*
564 * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
565 * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
566 * and host are of the same "endianess". It's possible to mask
567 * this with blank #define HASH_BLOCK_DATA_ORDER though...
568 *
569 * <appro@fy.chalmers.se>
570 */
571 #if defined(B_ENDIAN)
572 # if defined(DATA_ORDER_IS_BIG_ENDIAN)
573 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
574 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
575 # endif
576 # elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
577 # ifndef HOST_FETCH32
578 # ifdef LE_FETCH32
579 # define HOST_FETCH32(p,l) LE_FETCH32(p)
580 # elif defined(REVERSE_FETCH32)
581 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
582 # endif
583 # endif
584 # endif
585 #elif defined(L_ENDIAN)
586 # if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
587 # if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
588 # define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER
589 # endif
590 # elif defined(DATA_ORDER_IS_BIG_ENDIAN)
591 # ifndef HOST_FETCH32
592 # ifdef BE_FETCH32
593 # define HOST_FETCH32(p,l) BE_FETCH32(p)
594 # elif defined(REVERSE_FETCH32)
595 # define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l)
596 # endif
597 # endif
598 # endif
599 #endif
600
601 #if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
602 #ifndef HASH_BLOCK_DATA_ORDER
603 #error "HASH_BLOCK_DATA_ORDER must be defined!"
604 #endif
605 #endif
606
607 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
608
609 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
610 l|=(((unsigned long)(*((c)++)))<<16), \
611 l|=(((unsigned long)(*((c)++)))<< 8), \
612 l|=(((unsigned long)(*((c)++))) ), \
613 l)
614 #define HOST_p_c2l(c,l,n) { \
615 switch (n) { \
616 case 0: l =((unsigned long)(*((c)++)))<<24; \
617 case 1: l|=((unsigned long)(*((c)++)))<<16; \
618 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
619 case 3: l|=((unsigned long)(*((c)++))); \
620 } }
621 #define HOST_p_c2l_p(c,l,sc,len) { \
622 switch (sc) { \
623 case 0: l =((unsigned long)(*((c)++)))<<24; \
624 if (--len == 0) break; \
625 case 1: l|=((unsigned long)(*((c)++)))<<16; \
626 if (--len == 0) break; \
627 case 2: l|=((unsigned long)(*((c)++)))<< 8; \
628 } }
629 /* NOTE the pointer is not incremented at the end of this */
630 #define HOST_c2l_p(c,l,n) { \
631 l=0; (c)+=n; \
632 switch (n) { \
633 case 3: l =((unsigned long)(*(--(c))))<< 8; \
634 case 2: l|=((unsigned long)(*(--(c))))<<16; \
635 case 1: l|=((unsigned long)(*(--(c))))<<24; \
636 } }
637 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
638 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
639 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
640 *((c)++)=(unsigned char)(((l) )&0xff), \
641 l)
642
643 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
644
645 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
646 l|=(((unsigned long)(*((c)++)))<< 8), \
647 l|=(((unsigned long)(*((c)++)))<<16), \
648 l|=(((unsigned long)(*((c)++)))<<24), \
649 l)
650 #define HOST_p_c2l(c,l,n) { \
651 switch (n) { \
652 case 0: l =((unsigned long)(*((c)++))); \
653 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
654 case 2: l|=((unsigned long)(*((c)++)))<<16; \
655 case 3: l|=((unsigned long)(*((c)++)))<<24; \
656 } }
657 #define HOST_p_c2l_p(c,l,sc,len) { \
658 switch (sc) { \
659 case 0: l =((unsigned long)(*((c)++))); \
660 if (--len == 0) break; \
661 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
662 if (--len == 0) break; \
663 case 2: l|=((unsigned long)(*((c)++)))<<16; \
664 } }
665 /* NOTE the pointer is not incremented at the end of this */
666 #define HOST_c2l_p(c,l,n) { \
667 l=0; (c)+=n; \
668 switch (n) { \
669 case 3: l =((unsigned long)(*(--(c))))<<16; \
670 case 2: l|=((unsigned long)(*(--(c))))<< 8; \
671 case 1: l|=((unsigned long)(*(--(c)))); \
672 } }
673 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
674 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
675 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
676 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
677 l)
678
679 #endif
680
681 /*
682 * Time for some action:-)
683 */
684
685 int HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len)
686 {
687 const unsigned char *data=(const unsigned char *)data_;
688 register HASH_LONG * p;
689 register unsigned long l;
690 int sw,sc,ew,ec;
691
692 if (len==0) return 1;
693
694 l=(c->Nl+(len<<3))&0xffffffffL;
695 /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
696 * Wei Dai <weidai@eskimo.com> for pointing it out. */
697 if (l < c->Nl) /* overflow */
698 c->Nh++;
699 c->Nh+=(len>>29);
700 c->Nl=l;
701
702 if (c->num != 0)
703 {
704 p=c->data;
705 sw=c->num>>2;
706 sc=c->num&0x03;
707
708 if ((c->num+len) >= HASH_CBLOCK)
709 {
710 l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
711 for (; sw<HASH_LBLOCK; sw++)
712 {
713 HOST_c2l(data,l); p[sw]=l;
714 }
715 HASH_BLOCK_HOST_ORDER (c,p,1);
716 len-=(HASH_CBLOCK-c->num);
717 c->num=0;
718 /* drop through and do the rest */
719 }
720 else
721 {
722 c->num+=len;
723 if ((sc+len) < 4) /* ugly, add char's to a word */
724 {
725 l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
726 }
727 else
728 {
729 ew=(c->num>>2);
730 ec=(c->num&0x03);
731 if (sc)
732 l=p[sw];
733 HOST_p_c2l(data,l,sc);
734 p[sw++]=l;
735 for (; sw < ew; sw++)
736 {
737 HOST_c2l(data,l); p[sw]=l;
738 }
739 if (ec)
740 {
741 HOST_c2l_p(data,l,ec); p[sw]=l;
742 }
743 }
744 return 1;
745 }
746 }
747
748 sw=(int)(len/HASH_CBLOCK);
749 if (sw > 0)
750 {
751 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
752 /*
753 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
754 * only if sizeof(HASH_LONG)==4.
755 */
756 if ((((unsigned long)data)%4) == 0)
757 {
758 /* data is properly aligned so that we can cast it: */
759 HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw);
760 sw*=HASH_CBLOCK;
761 data+=sw;
762 len-=sw;
763 }
764 else
765 #if !defined(HASH_BLOCK_DATA_ORDER)
766 while (sw--)
767 {
768 memcpy (p=c->data,data,HASH_CBLOCK);
769 HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
770 data+=HASH_CBLOCK;
771 len-=HASH_CBLOCK;
772 }
773 #endif
774 #endif
775 #if defined(HASH_BLOCK_DATA_ORDER)
776 {
777 HASH_BLOCK_DATA_ORDER(c,data,sw);
778 sw*=HASH_CBLOCK;
779 data+=sw;
780 len-=sw;
781 }
782 #endif
783 }
784
785 if (len!=0)
786 {
787 p = c->data;
788 c->num = (int)len;
789 ew=(int)(len>>2); /* words to copy */
790 ec=(int)(len&0x03);
791 for (; ew; ew--,p++)
792 {
793 HOST_c2l(data,l); *p=l;
794 }
795 HOST_c2l_p(data,l,ec);
796 *p=l;
797 }
798 return 1;
799 }
800
801
802 void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
803 {
804 #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
805 if ((((unsigned long)data)%4) == 0)
806 /* data is properly aligned so that we can cast it: */
807 HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1);
808 else
809 #if !defined(HASH_BLOCK_DATA_ORDER)
810 {
811 memcpy (c->data,data,HASH_CBLOCK);
812 HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
813 }
814 #endif
815 #endif
816 #if defined(HASH_BLOCK_DATA_ORDER)
817 HASH_BLOCK_DATA_ORDER (c,data,1);
818 #endif
819 }
820
821
822 int HASH_FINAL (unsigned char *md, HASH_CTX *c)
823 {
824 register HASH_LONG *p;
825 register unsigned long l;
826 register int i,j;
827 static const unsigned char end[4]={0x80,0x00,0x00,0x00};
828 const unsigned char *cp=end;
829
830 /* c->num should definitly have room for at least one more byte. */
831 p=c->data;
832 i=c->num>>2;
833 j=c->num&0x03;
834
835 #if 0
836 /* purify often complains about the following line as an
837 * Uninitialized Memory Read. While this can be true, the
838 * following p_c2l macro will reset l when that case is true.
839 * This is because j&0x03 contains the number of 'valid' bytes
840 * already in p[i]. If and only if j&0x03 == 0, the UMR will
841 * occur but this is also the only time p_c2l will do
842 * l= *(cp++) instead of l|= *(cp++)
843 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
844 * 'potential bug' */
845 #ifdef PURIFY
846 if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */
847 #endif
848 l=p[i];
849 #else
850 l = (j==0) ? 0 : p[i];
851 #endif
852 HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */
853
854 if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */
855 {
856 if (i<HASH_LBLOCK) p[i]=0;
857 HASH_BLOCK_HOST_ORDER (c,p,1);
858 i=0;
859 }
860 for (; i<(HASH_LBLOCK-2); i++)
861 p[i]=0;
862
863 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
864 p[HASH_LBLOCK-2]=c->Nh;
865 p[HASH_LBLOCK-1]=c->Nl;
866 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
867 p[HASH_LBLOCK-2]=c->Nl;
868 p[HASH_LBLOCK-1]=c->Nh;
869 #endif
870 HASH_BLOCK_HOST_ORDER (c,p,1);
871
872 #ifndef HASH_MAKE_STRING
873 #error "HASH_MAKE_STRING must be defined!"
874 #else
875 HASH_MAKE_STRING(c,md);
876 #endif
877
878 c->num=0;
879 /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
880 * but I'm not worried :-)
881 OPENSSL_cleanse((void *)c,sizeof(HASH_CTX));
882 */
883 return 1;
884 }
885
886 #ifndef MD32_REG_T
887 #define MD32_REG_T long
888 /*
889 * This comment was originaly written for MD5, which is why it
890 * discusses A-D. But it basically applies to all 32-bit digests,
891 * which is why it was moved to common header file.
892 *
893 * In case you wonder why A-D are declared as long and not
894 * as mDNSu32. Doing so results in slight performance
895 * boost on LP64 architectures. The catch is we don't
896 * really care if 32 MSBs of a 64-bit register get polluted
897 * with eventual overflows as we *save* only 32 LSBs in
898 * *either* case. Now declaring 'em long excuses the compiler
899 * from keeping 32 MSBs zeroed resulting in 13% performance
900 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
901 * Well, to be honest it should say that this *prevents*
902 * performance degradation.
903 * <appro@fy.chalmers.se>
904 * Apparently there're LP64 compilers that generate better
905 * code if A-D are declared int. Most notably GCC-x86_64
906 * generates better code.
907 * <appro@fy.chalmers.se>
908 */
909 #endif
910
911
912 // from md5_locl.h (continued)
913
914 /*
915 #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
916 #define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
917 */
918
919 /* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
920 * simplified to the code below. Wei attributes these optimizations
921 * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
922 */
923 #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
924 #define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c))
925 #define H(b,c,d) ((b) ^ (c) ^ (d))
926 #define I(b,c,d) (((~(d)) | (b)) ^ (c))
927
928 #define R0(a,b,c,d,k,s,t) { \
929 a+=((k)+(t)+F((b),(c),(d))); \
930 a=ROTATE(a,s); \
931 a+=b; };\
932
933 #define R1(a,b,c,d,k,s,t) { \
934 a+=((k)+(t)+G((b),(c),(d))); \
935 a=ROTATE(a,s); \
936 a+=b; };
937
938 #define R2(a,b,c,d,k,s,t) { \
939 a+=((k)+(t)+H((b),(c),(d))); \
940 a=ROTATE(a,s); \
941 a+=b; };
942
943 #define R3(a,b,c,d,k,s,t) { \
944 a+=((k)+(t)+I((b),(c),(d))); \
945 a=ROTATE(a,s); \
946 a+=b; };
947
948 // from md5_dgst.c
949
950
951 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
952 */
953
954 #define INIT_DATA_A (unsigned long)0x67452301L
955 #define INIT_DATA_B (unsigned long)0xefcdab89L
956 #define INIT_DATA_C (unsigned long)0x98badcfeL
957 #define INIT_DATA_D (unsigned long)0x10325476L
958
959 int MD5_Init(MD5_CTX *c)
960 {
961 c->A=INIT_DATA_A;
962 c->B=INIT_DATA_B;
963 c->C=INIT_DATA_C;
964 c->D=INIT_DATA_D;
965 c->Nl=0;
966 c->Nh=0;
967 c->num=0;
968 return 1;
969 }
970
971 #ifndef md5_block_host_order
972 void md5_block_host_order (MD5_CTX *c, const void *data, int num)
973 {
974 const mDNSu32 *X=(const mDNSu32 *)data;
975 register unsigned MD32_REG_T A,B,C,D;
976
977 A=c->A;
978 B=c->B;
979 C=c->C;
980 D=c->D;
981
982 for (;num--;X+=HASH_LBLOCK)
983 {
984 /* Round 0 */
985 R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
986 R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
987 R0(C,D,A,B,X[ 2],17,0x242070dbL);
988 R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
989 R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
990 R0(D,A,B,C,X[ 5],12,0x4787c62aL);
991 R0(C,D,A,B,X[ 6],17,0xa8304613L);
992 R0(B,C,D,A,X[ 7],22,0xfd469501L);
993 R0(A,B,C,D,X[ 8], 7,0x698098d8L);
994 R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
995 R0(C,D,A,B,X[10],17,0xffff5bb1L);
996 R0(B,C,D,A,X[11],22,0x895cd7beL);
997 R0(A,B,C,D,X[12], 7,0x6b901122L);
998 R0(D,A,B,C,X[13],12,0xfd987193L);
999 R0(C,D,A,B,X[14],17,0xa679438eL);
1000 R0(B,C,D,A,X[15],22,0x49b40821L);
1001 /* Round 1 */
1002 R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
1003 R1(D,A,B,C,X[ 6], 9,0xc040b340L);
1004 R1(C,D,A,B,X[11],14,0x265e5a51L);
1005 R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
1006 R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
1007 R1(D,A,B,C,X[10], 9,0x02441453L);
1008 R1(C,D,A,B,X[15],14,0xd8a1e681L);
1009 R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
1010 R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
1011 R1(D,A,B,C,X[14], 9,0xc33707d6L);
1012 R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
1013 R1(B,C,D,A,X[ 8],20,0x455a14edL);
1014 R1(A,B,C,D,X[13], 5,0xa9e3e905L);
1015 R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
1016 R1(C,D,A,B,X[ 7],14,0x676f02d9L);
1017 R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
1018 /* Round 2 */
1019 R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
1020 R2(D,A,B,C,X[ 8],11,0x8771f681L);
1021 R2(C,D,A,B,X[11],16,0x6d9d6122L);
1022 R2(B,C,D,A,X[14],23,0xfde5380cL);
1023 R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
1024 R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
1025 R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
1026 R2(B,C,D,A,X[10],23,0xbebfbc70L);
1027 R2(A,B,C,D,X[13], 4,0x289b7ec6L);
1028 R2(D,A,B,C,X[ 0],11,0xeaa127faL);
1029 R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
1030 R2(B,C,D,A,X[ 6],23,0x04881d05L);
1031 R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
1032 R2(D,A,B,C,X[12],11,0xe6db99e5L);
1033 R2(C,D,A,B,X[15],16,0x1fa27cf8L);
1034 R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
1035 /* Round 3 */
1036 R3(A,B,C,D,X[ 0], 6,0xf4292244L);
1037 R3(D,A,B,C,X[ 7],10,0x432aff97L);
1038 R3(C,D,A,B,X[14],15,0xab9423a7L);
1039 R3(B,C,D,A,X[ 5],21,0xfc93a039L);
1040 R3(A,B,C,D,X[12], 6,0x655b59c3L);
1041 R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
1042 R3(C,D,A,B,X[10],15,0xffeff47dL);
1043 R3(B,C,D,A,X[ 1],21,0x85845dd1L);
1044 R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
1045 R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
1046 R3(C,D,A,B,X[ 6],15,0xa3014314L);
1047 R3(B,C,D,A,X[13],21,0x4e0811a1L);
1048 R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
1049 R3(D,A,B,C,X[11],10,0xbd3af235L);
1050 R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
1051 R3(B,C,D,A,X[ 9],21,0xeb86d391L);
1052
1053 A = c->A += A;
1054 B = c->B += B;
1055 C = c->C += C;
1056 D = c->D += D;
1057 }
1058 }
1059 #endif
1060
1061 #ifndef md5_block_data_order
1062 #ifdef X
1063 #undef X
1064 #endif
1065 void md5_block_data_order (MD5_CTX *c, const void *data_, int num)
1066 {
1067 const unsigned char *data=data_;
1068 register unsigned MD32_REG_T A,B,C,D,l;
1069 #ifndef MD32_XARRAY
1070 /* See comment in crypto/sha/sha_locl.h for details. */
1071 unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
1072 XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
1073 # define X(i) XX##i
1074 #else
1075 mDNSu32 XX[MD5_LBLOCK];
1076 # define X(i) XX[i]
1077 #endif
1078
1079 A=c->A;
1080 B=c->B;
1081 C=c->C;
1082 D=c->D;
1083
1084 for (;num--;)
1085 {
1086 HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l;
1087 /* Round 0 */
1088 R0(A,B,C,D,X( 0), 7,0xd76aa478L); HOST_c2l(data,l); X( 2)=l;
1089 R0(D,A,B,C,X( 1),12,0xe8c7b756L); HOST_c2l(data,l); X( 3)=l;
1090 R0(C,D,A,B,X( 2),17,0x242070dbL); HOST_c2l(data,l); X( 4)=l;
1091 R0(B,C,D,A,X( 3),22,0xc1bdceeeL); HOST_c2l(data,l); X( 5)=l;
1092 R0(A,B,C,D,X( 4), 7,0xf57c0fafL); HOST_c2l(data,l); X( 6)=l;
1093 R0(D,A,B,C,X( 5),12,0x4787c62aL); HOST_c2l(data,l); X( 7)=l;
1094 R0(C,D,A,B,X( 6),17,0xa8304613L); HOST_c2l(data,l); X( 8)=l;
1095 R0(B,C,D,A,X( 7),22,0xfd469501L); HOST_c2l(data,l); X( 9)=l;
1096 R0(A,B,C,D,X( 8), 7,0x698098d8L); HOST_c2l(data,l); X(10)=l;
1097 R0(D,A,B,C,X( 9),12,0x8b44f7afL); HOST_c2l(data,l); X(11)=l;
1098 R0(C,D,A,B,X(10),17,0xffff5bb1L); HOST_c2l(data,l); X(12)=l;
1099 R0(B,C,D,A,X(11),22,0x895cd7beL); HOST_c2l(data,l); X(13)=l;
1100 R0(A,B,C,D,X(12), 7,0x6b901122L); HOST_c2l(data,l); X(14)=l;
1101 R0(D,A,B,C,X(13),12,0xfd987193L); HOST_c2l(data,l); X(15)=l;
1102 R0(C,D,A,B,X(14),17,0xa679438eL);
1103 R0(B,C,D,A,X(15),22,0x49b40821L);
1104 /* Round 1 */
1105 R1(A,B,C,D,X( 1), 5,0xf61e2562L);
1106 R1(D,A,B,C,X( 6), 9,0xc040b340L);
1107 R1(C,D,A,B,X(11),14,0x265e5a51L);
1108 R1(B,C,D,A,X( 0),20,0xe9b6c7aaL);
1109 R1(A,B,C,D,X( 5), 5,0xd62f105dL);
1110 R1(D,A,B,C,X(10), 9,0x02441453L);
1111 R1(C,D,A,B,X(15),14,0xd8a1e681L);
1112 R1(B,C,D,A,X( 4),20,0xe7d3fbc8L);
1113 R1(A,B,C,D,X( 9), 5,0x21e1cde6L);
1114 R1(D,A,B,C,X(14), 9,0xc33707d6L);
1115 R1(C,D,A,B,X( 3),14,0xf4d50d87L);
1116 R1(B,C,D,A,X( 8),20,0x455a14edL);
1117 R1(A,B,C,D,X(13), 5,0xa9e3e905L);
1118 R1(D,A,B,C,X( 2), 9,0xfcefa3f8L);
1119 R1(C,D,A,B,X( 7),14,0x676f02d9L);
1120 R1(B,C,D,A,X(12),20,0x8d2a4c8aL);
1121 /* Round 2 */
1122 R2(A,B,C,D,X( 5), 4,0xfffa3942L);
1123 R2(D,A,B,C,X( 8),11,0x8771f681L);
1124 R2(C,D,A,B,X(11),16,0x6d9d6122L);
1125 R2(B,C,D,A,X(14),23,0xfde5380cL);
1126 R2(A,B,C,D,X( 1), 4,0xa4beea44L);
1127 R2(D,A,B,C,X( 4),11,0x4bdecfa9L);
1128 R2(C,D,A,B,X( 7),16,0xf6bb4b60L);
1129 R2(B,C,D,A,X(10),23,0xbebfbc70L);
1130 R2(A,B,C,D,X(13), 4,0x289b7ec6L);
1131 R2(D,A,B,C,X( 0),11,0xeaa127faL);
1132 R2(C,D,A,B,X( 3),16,0xd4ef3085L);
1133 R2(B,C,D,A,X( 6),23,0x04881d05L);
1134 R2(A,B,C,D,X( 9), 4,0xd9d4d039L);
1135 R2(D,A,B,C,X(12),11,0xe6db99e5L);
1136 R2(C,D,A,B,X(15),16,0x1fa27cf8L);
1137 R2(B,C,D,A,X( 2),23,0xc4ac5665L);
1138 /* Round 3 */
1139 R3(A,B,C,D,X( 0), 6,0xf4292244L);
1140 R3(D,A,B,C,X( 7),10,0x432aff97L);
1141 R3(C,D,A,B,X(14),15,0xab9423a7L);
1142 R3(B,C,D,A,X( 5),21,0xfc93a039L);
1143 R3(A,B,C,D,X(12), 6,0x655b59c3L);
1144 R3(D,A,B,C,X( 3),10,0x8f0ccc92L);
1145 R3(C,D,A,B,X(10),15,0xffeff47dL);
1146 R3(B,C,D,A,X( 1),21,0x85845dd1L);
1147 R3(A,B,C,D,X( 8), 6,0x6fa87e4fL);
1148 R3(D,A,B,C,X(15),10,0xfe2ce6e0L);
1149 R3(C,D,A,B,X( 6),15,0xa3014314L);
1150 R3(B,C,D,A,X(13),21,0x4e0811a1L);
1151 R3(A,B,C,D,X( 4), 6,0xf7537e82L);
1152 R3(D,A,B,C,X(11),10,0xbd3af235L);
1153 R3(C,D,A,B,X( 2),15,0x2ad7d2bbL);
1154 R3(B,C,D,A,X( 9),21,0xeb86d391L);
1155
1156 A = c->A += A;
1157 B = c->B += B;
1158 C = c->C += C;
1159 D = c->D += D;
1160 }
1161 }
1162 #endif
1163
1164
1165
1166 // ***************************************************************************
1167 #if COMPILER_LIKES_PRAGMA_MARK
1168 #pragma mark - base64 -> binary conversion
1169 #endif
1170
1171 static const char Base64[] =
1172 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1173 static const char Pad64 = '=';
1174
1175
1176 #define mDNSisspace(x) (x == '\t' || x == '\n' || x == '\v' || x == '\f' || x == '\r' || x == ' ')
1177
1178 static const char *mDNSstrchr(const char *s, int c)
1179 {
1180 while (1)
1181 {
1182 if (c == *s) return s;
1183 if (!*s) return mDNSNULL;
1184 s++;
1185 }
1186 }
1187
1188 // skips all whitespace anywhere.
1189 // converts characters, four at a time, starting at (or after)
1190 // src from base - 64 numbers into three 8 bit bytes in the target area.
1191 // it returns the number of data bytes stored at the target, or -1 on error.
1192 // adapted from BIND sources
1193
1194 mDNSexport mDNSs32 DNSDigest_Base64ToBin(const char *src, mDNSu8 *target, mDNSu32 targsize)
1195 {
1196 int tarindex, state, ch;
1197 const char *pos;
1198
1199 state = 0;
1200 tarindex = 0;
1201
1202 while ((ch = *src++) != '\0') {
1203 if (mDNSisspace(ch)) /* Skip whitespace anywhere. */
1204 continue;
1205
1206 if (ch == Pad64)
1207 break;
1208
1209 pos = mDNSstrchr(Base64, ch);
1210 if (pos == 0) /* A non-base64 character. */
1211 return (-1);
1212
1213 switch (state) {
1214 case 0:
1215 if (target) {
1216 if ((mDNSu32)tarindex >= targsize)
1217 return (-1);
1218 target[tarindex] = (mDNSu8)((pos - Base64) << 2);
1219 }
1220 state = 1;
1221 break;
1222 case 1:
1223 if (target) {
1224 if ((mDNSu32)tarindex + 1 >= targsize)
1225 return (-1);
1226 target[tarindex] |= (pos - Base64) >> 4;
1227 target[tarindex+1] = (mDNSu8)(((pos - Base64) & 0x0f) << 4);
1228 }
1229 tarindex++;
1230 state = 2;
1231 break;
1232 case 2:
1233 if (target) {
1234 if ((mDNSu32)tarindex + 1 >= targsize)
1235 return (-1);
1236 target[tarindex] |= (pos - Base64) >> 2;
1237 target[tarindex+1] = (mDNSu8)(((pos - Base64) & 0x03) << 6);
1238 }
1239 tarindex++;
1240 state = 3;
1241 break;
1242 case 3:
1243 if (target) {
1244 if ((mDNSu32)tarindex >= targsize)
1245 return (-1);
1246 target[tarindex] |= (pos - Base64);
1247 }
1248 tarindex++;
1249 state = 0;
1250 break;
1251 default:
1252 return -1;
1253 }
1254 }
1255
1256 /*
1257 * We are done decoding Base-64 chars. Let's see if we ended
1258 * on a byte boundary, and/or with erroneous trailing characters.
1259 */
1260
1261 if (ch == Pad64) { /* We got a pad char. */
1262 ch = *src++; /* Skip it, get next. */
1263 switch (state) {
1264 case 0: /* Invalid = in first position */
1265 case 1: /* Invalid = in second position */
1266 return (-1);
1267
1268 case 2: /* Valid, means one byte of info */
1269 /* Skip any number of spaces. */
1270 for ((void)mDNSNULL; ch != '\0'; ch = *src++)
1271 if (!mDNSisspace(ch))
1272 break;
1273 /* Make sure there is another trailing = sign. */
1274 if (ch != Pad64)
1275 return (-1);
1276 ch = *src++; /* Skip the = */
1277 /* Fall through to "single trailing =" case. */
1278 /* FALLTHROUGH */
1279
1280 case 3: /* Valid, means two bytes of info */
1281 /*
1282 * We know this char is an =. Is there anything but
1283 * whitespace after it?
1284 */
1285 for ((void)mDNSNULL; ch != '\0'; ch = *src++)
1286 if (!mDNSisspace(ch))
1287 return (-1);
1288
1289 /*
1290 * Now make sure for cases 2 and 3 that the "extra"
1291 * bits that slopped past the last full byte were
1292 * zeros. If we don't check them, they become a
1293 * subliminal channel.
1294 */
1295 if (target && target[tarindex] != 0)
1296 return (-1);
1297 }
1298 } else {
1299 /*
1300 * We ended by seeing the end of the string. Make sure we
1301 * have no partial bytes lying around.
1302 */
1303 if (state != 0)
1304 return (-1);
1305 }
1306
1307 return (tarindex);
1308 }
1309
1310
1311 // ***************************************************************************
1312 #if COMPILER_LIKES_PRAGMA_MARK
1313 #pragma mark - API exported to mDNS Core
1314 #endif
1315
1316 // Constants
1317 #define HMAC_IPAD 0x36
1318 #define HMAC_OPAD 0x5c
1319 #define MD5_LEN 16
1320
1321 #define HMAC_MD5_AlgName (*(const domainname*) "\010" "hmac-md5" "\007" "sig-alg" "\003" "reg" "\003" "int")
1322
1323 // Adapted from Appendix, RFC 2104
1324 mDNSexport void DNSDigest_ConstructHMACKey(uDNS_AuthInfo *info, const mDNSu8 *key, mDNSu32 len)
1325 {
1326 MD5_CTX k;
1327 mDNSu8 buf[MD5_LEN];
1328 int i;
1329
1330 // If key is longer than HMAC_LEN reset it to MD5(key)
1331 if (len > HMAC_LEN)
1332 {
1333 MD5_Init(&k);
1334 MD5_Update(&k, key, len);
1335 MD5_Final(buf, &k);
1336 key = buf;
1337 len = MD5_LEN;
1338 }
1339
1340 // store key in pads
1341 mDNSPlatformMemZero(info->key.ipad, HMAC_LEN);
1342 mDNSPlatformMemZero(info->key.opad, HMAC_LEN);
1343 mDNSPlatformMemCopy(key, info->key.ipad, len);
1344 mDNSPlatformMemCopy(key, info->key.opad, len);
1345
1346 // XOR key with ipad and opad values
1347 for (i = 0; i < HMAC_LEN; i++)
1348 {
1349 info->key.ipad[i] ^= HMAC_IPAD;
1350 info->key.opad[i] ^= HMAC_OPAD;
1351 }
1352
1353 }
1354
1355 mDNSexport mDNSu8 *DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, mDNSu16 *numAdditionals, uDNS_AuthInfo *info)
1356 {
1357 AuthRecord tsig;
1358 mDNSu8 *countPtr, *rdata;
1359 mDNSu32 utc32;
1360 mDNSu8 utc48[6];
1361 mDNSu8 digest[MD5_LEN];
1362 mDNSu8 *ptr = *end;
1363 mDNSu32 len;
1364 mDNSOpaque16 buf;
1365 MD5_CTX c;
1366
1367 // Init MD5 context, digest inner key pad and message
1368 MD5_Init(&c);
1369 MD5_Update(&c, info->key.ipad, HMAC_LEN);
1370 MD5_Update(&c, (mDNSu8 *)msg, (unsigned long)(*end - (mDNSu8 *)msg));
1371
1372 // Construct TSIG RR, digesting variables as apporpriate
1373 mDNSPlatformMemZero(&tsig, sizeof(AuthRecord));
1374 mDNS_SetupResourceRecord(&tsig, mDNSNULL, 0, kDNSType_TSIG, 0, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
1375
1376 // key name
1377 AssignDomainName(tsig.resrec.name, info->keyname);
1378 MD5_Update(&c, info->keyname.c, DomainNameLength(&info->keyname));
1379
1380 // class
1381 tsig.resrec.rrclass = kDNSQClass_ANY;
1382 buf = mDNSOpaque16fromIntVal(kDNSQClass_ANY);
1383 MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
1384
1385 // ttl
1386 tsig.resrec.rroriginalttl = 0;
1387 MD5_Update(&c, (mDNSu8 *)&tsig.resrec.rroriginalttl, sizeof(tsig.resrec.rroriginalttl));
1388
1389 // alg name
1390 AssignDomainName(tsig.resrec.rdata->u.name, HMAC_MD5_AlgName);
1391 len = DomainNameLength(&HMAC_MD5_AlgName);
1392 rdata = tsig.resrec.rdata->u.data + len;
1393 MD5_Update(&c, HMAC_MD5_AlgName.c, len);
1394
1395 // time
1396 // get UTC (universal time), convert to 48-bit unsigned in network byte order
1397 utc32 = (mDNSu32)mDNSPlatformUTC();
1398 if (utc32 == (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); return mDNSNULL; }
1399 utc48[0] = 0;
1400 utc48[1] = 0;
1401 utc48[2] = (mDNSu8)((utc32 >> 24) & 0xff);
1402 utc48[3] = (mDNSu8)((utc32 >> 16) & 0xff);
1403 utc48[4] = (mDNSu8)((utc32 >> 8) & 0xff);
1404 utc48[5] = (mDNSu8)( utc32 & 0xff);
1405
1406 mDNSPlatformMemCopy(utc48, rdata, 6);
1407 rdata += 6;
1408 MD5_Update(&c, utc48, 6);
1409
1410 // fudge
1411 buf = mDNSOpaque16fromIntVal(300); // 300 sec is fudge recommended in RFC 2485
1412 rdata[0] = buf.b[0];
1413 rdata[1] = buf.b[1];
1414 rdata += sizeof(mDNSOpaque16);
1415 MD5_Update(&c, buf.b, sizeof(mDNSOpaque16));
1416
1417 // digest error and other data len (both zero) - we'll add them to the rdata later
1418 buf.NotAnInteger = 0;
1419 MD5_Update(&c, buf.b, sizeof(mDNSOpaque16)); // error
1420 MD5_Update(&c, buf.b, sizeof(mDNSOpaque16)); // other data len
1421
1422 // finish the message & tsig var hash
1423 MD5_Final(digest, &c);
1424
1425 // perform outer MD5 (outer key pad, inner digest)
1426 MD5_Init(&c);
1427 MD5_Update(&c, info->key.opad, HMAC_LEN);
1428 MD5_Update(&c, digest, MD5_LEN);
1429 MD5_Final(digest, &c);
1430
1431 // set remaining rdata fields
1432 rdata[0] = (mDNSu8)((MD5_LEN >> 8) & 0xff);
1433 rdata[1] = (mDNSu8)( MD5_LEN & 0xff);
1434 rdata += sizeof(mDNSOpaque16);
1435 mDNSPlatformMemCopy(digest, rdata, MD5_LEN); // MAC
1436 rdata += MD5_LEN;
1437 rdata[0] = msg->h.id.b[0]; // original ID
1438 rdata[1] = msg->h.id.b[1];
1439 rdata[2] = 0; // no error
1440 rdata[3] = 0;
1441 rdata[4] = 0; // other data len
1442 rdata[5] = 0;
1443 rdata += 6;
1444
1445 tsig.resrec.rdlength = (mDNSu16)(rdata - tsig.resrec.rdata->u.data);
1446 *end = PutResourceRecordTTLJumbo(msg, ptr, numAdditionals, &tsig.resrec, 0);
1447 if (!*end) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); return mDNSNULL; }
1448
1449 // update num additionals
1450 countPtr = (mDNSu8 *)&msg->h.numAdditionals; // increment (network-byte ordered) header value
1451 *countPtr++ = (mDNSu8)(*numAdditionals >> 8);
1452 *countPtr++ = (mDNSu8)(*numAdditionals & 0xFF);
1453
1454 return *end;
1455 }
1456
1457 #ifdef __cplusplus
1458 }
1459 #endif