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