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