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