1*eabc0478Schristos /* $NetBSD: tsmemcmp.c,v 1.2 2024/08/18 20:47:14 christos Exp $ */ 2897be3a4Schristos 3897be3a4Schristos /* 4897be3a4Schristos * Copyright (C) 2004-2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 5897be3a4Schristos * Copyright (C) 1999-2001, 2003 Internet Software Consortium. 6897be3a4Schristos * 7897be3a4Schristos * Permission to use, copy, modify, and/or distribute this software for any 8897be3a4Schristos * purpose with or without fee is hereby granted, provided that the above 9897be3a4Schristos * copyright notice and this permission notice appear in all copies. 10897be3a4Schristos * 11897be3a4Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12897be3a4Schristos * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13897be3a4Schristos * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14897be3a4Schristos * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15897be3a4Schristos * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16897be3a4Schristos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17897be3a4Schristos * PERFORMANCE OF THIS SOFTWARE. 18897be3a4Schristos */ 19897be3a4Schristos 20897be3a4Schristos /* Id */ 21897be3a4Schristos 22897be3a4Schristos /*! \file */ 23897be3a4Schristos 24897be3a4Schristos #include <config.h> 25897be3a4Schristos #include <limits.h> 26897be3a4Schristos #include <isc/string.h> 27897be3a4Schristos 28897be3a4Schristos /* Making a portable memcmp that has no internal branches and loops always 29897be3a4Schristos * once for every byte without early-out shortcut has a few challenges. 30897be3a4Schristos * 31897be3a4Schristos * Inspired by 'timingsafe_memcmp()' from the BSD system and 32897be3a4Schristos * https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/string/timingsafe_memcmp.c 33897be3a4Schristos * 34897be3a4Schristos * Sadly, that one is not portable C: It makes assumptions on the representation 35897be3a4Schristos * of negative integers and assumes sign-preserving right-shift of negative 36897be3a4Schristos * signed values. This is a rewrite from scratch that should not suffer from 37897be3a4Schristos * such issues. 38897be3a4Schristos * 39897be3a4Schristos * 2015-12-12, J. Perlinger (perlinger-at-ntp-dot-org) 40897be3a4Schristos */ 41897be3a4Schristos int 42897be3a4Schristos isc_tsmemcmp(const void *p1, const void *p2, size_t nb) { 43897be3a4Schristos const unsigned char *ucp1 = p1; 44897be3a4Schristos const unsigned char *ucp2 = p2; 45897be3a4Schristos unsigned int isLT = 0u; 46897be3a4Schristos unsigned int isGT = 0u; 47897be3a4Schristos volatile unsigned int mask = (1u << CHAR_BIT); 48897be3a4Schristos 49897be3a4Schristos for (/*NOP*/; 0 != nb; --nb, ++ucp1, ++ucp2) { 50897be3a4Schristos isLT |= mask & 51897be3a4Schristos ((unsigned int)*ucp1 - (unsigned int)*ucp2); 52897be3a4Schristos isGT |= mask & 53897be3a4Schristos ((unsigned int)*ucp2 - (unsigned int)*ucp1); 54897be3a4Schristos mask &= ~(isLT | isGT); 55897be3a4Schristos } 56897be3a4Schristos return (int)(isGT >> CHAR_BIT) - (int)(isLT >> CHAR_BIT); 57897be3a4Schristos } 58