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