xref: /minix3/common/lib/libc/string/consttime_memequal.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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