1*0a6a1f1dSLionel Sambuc /* $NetBSD: consttime_memequal.c,v 1.6 2015/03/18 20:11:35 riastradh Exp $ */ 2*0a6a1f1dSLionel Sambuc 3*0a6a1f1dSLionel Sambuc /* 4*0a6a1f1dSLionel Sambuc * Written by Matthias Drochner <drochner@NetBSD.org>. 5*0a6a1f1dSLionel Sambuc * Public domain. 6*0a6a1f1dSLionel Sambuc */ 784d9c625SLionel Sambuc 884d9c625SLionel Sambuc #if !defined(_KERNEL) && !defined(_STANDALONE) 984d9c625SLionel Sambuc #include "namespace.h" 1084d9c625SLionel Sambuc #include <string.h> 1184d9c625SLionel Sambuc #ifdef __weak_alias __weak_alias(consttime_memequal,_consttime_memequal)1284d9c625SLionel Sambuc__weak_alias(consttime_memequal,_consttime_memequal) 1384d9c625SLionel Sambuc #endif 1484d9c625SLionel Sambuc #else 1584d9c625SLionel Sambuc #include <lib/libkern/libkern.h> 1684d9c625SLionel Sambuc #endif 1784d9c625SLionel Sambuc 1884d9c625SLionel Sambuc int 1984d9c625SLionel Sambuc consttime_memequal(const void *b1, const void *b2, size_t len) 2084d9c625SLionel Sambuc { 21*0a6a1f1dSLionel Sambuc const unsigned char *c1 = b1, *c2 = b2; 22*0a6a1f1dSLionel Sambuc unsigned int res = 0; 2384d9c625SLionel Sambuc 2484d9c625SLionel Sambuc while (len--) 2584d9c625SLionel Sambuc res |= *c1++ ^ *c2++; 2684d9c625SLionel Sambuc 2784d9c625SLionel Sambuc /* 28*0a6a1f1dSLionel Sambuc * Map 0 to 1 and [1, 256) to 0 using only constant-time 29*0a6a1f1dSLionel Sambuc * arithmetic. 3084d9c625SLionel Sambuc * 31*0a6a1f1dSLionel Sambuc * This is not simply `!res' because although many CPUs support 32*0a6a1f1dSLionel Sambuc * branchless conditional moves and many compilers will take 33*0a6a1f1dSLionel Sambuc * advantage of them, certain compilers generate branches on 34*0a6a1f1dSLionel Sambuc * certain CPUs for `!res'. 3584d9c625SLionel Sambuc */ 36*0a6a1f1dSLionel Sambuc return (1 & ((res - 1) >> 8)); 3784d9c625SLionel Sambuc } 38