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 1665