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