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