xref: /openbmc/linux/lib/crypto/memneq.c (revision 4a772c40)
1*7033b937SEric Biggers /*
2*7033b937SEric Biggers  * Constant-time equality testing of memory regions.
3*7033b937SEric Biggers  *
4*7033b937SEric Biggers  * Authors:
5*7033b937SEric Biggers  *
6*7033b937SEric Biggers  *   James Yonan <james@openvpn.net>
7*7033b937SEric Biggers  *   Daniel Borkmann <dborkman@redhat.com>
8*7033b937SEric Biggers  *
9*7033b937SEric Biggers  * This file is provided under a dual BSD/GPLv2 license.  When using or
10*7033b937SEric Biggers  * redistributing this file, you may do so under either license.
11*7033b937SEric Biggers  *
12*7033b937SEric Biggers  * GPL LICENSE SUMMARY
13*7033b937SEric Biggers  *
14*7033b937SEric Biggers  * Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved.
15*7033b937SEric Biggers  *
16*7033b937SEric Biggers  * This program is free software; you can redistribute it and/or modify
17*7033b937SEric Biggers  * it under the terms of version 2 of the GNU General Public License as
18*7033b937SEric Biggers  * published by the Free Software Foundation.
19*7033b937SEric Biggers  *
20*7033b937SEric Biggers  * This program is distributed in the hope that it will be useful, but
21*7033b937SEric Biggers  * WITHOUT ANY WARRANTY; without even the implied warranty of
22*7033b937SEric Biggers  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23*7033b937SEric Biggers  * General Public License for more details.
24*7033b937SEric Biggers  *
25*7033b937SEric Biggers  * You should have received a copy of the GNU General Public License
26*7033b937SEric Biggers  * along with this program; if not, write to the Free Software
27*7033b937SEric Biggers  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
28*7033b937SEric Biggers  * The full GNU General Public License is included in this distribution
29*7033b937SEric Biggers  * in the file called LICENSE.GPL.
30*7033b937SEric Biggers  *
31*7033b937SEric Biggers  * BSD LICENSE
32*7033b937SEric Biggers  *
33*7033b937SEric Biggers  * Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved.
34*7033b937SEric Biggers  *
35*7033b937SEric Biggers  * Redistribution and use in source and binary forms, with or without
36*7033b937SEric Biggers  * modification, are permitted provided that the following conditions
37*7033b937SEric Biggers  * are met:
38*7033b937SEric Biggers  *
39*7033b937SEric Biggers  *   * Redistributions of source code must retain the above copyright
40*7033b937SEric Biggers  *     notice, this list of conditions and the following disclaimer.
41*7033b937SEric Biggers  *   * Redistributions in binary form must reproduce the above copyright
42*7033b937SEric Biggers  *     notice, this list of conditions and the following disclaimer in
43*7033b937SEric Biggers  *     the documentation and/or other materials provided with the
44*7033b937SEric Biggers  *     distribution.
45*7033b937SEric Biggers  *   * Neither the name of OpenVPN Technologies nor the names of its
46*7033b937SEric Biggers  *     contributors may be used to endorse or promote products derived
47*7033b937SEric Biggers  *     from this software without specific prior written permission.
48*7033b937SEric Biggers  *
49*7033b937SEric Biggers  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50*7033b937SEric Biggers  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51*7033b937SEric Biggers  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
52*7033b937SEric Biggers  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
53*7033b937SEric Biggers  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54*7033b937SEric Biggers  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55*7033b937SEric Biggers  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56*7033b937SEric Biggers  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57*7033b937SEric Biggers  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58*7033b937SEric Biggers  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
59*7033b937SEric Biggers  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60*7033b937SEric Biggers  */
61*7033b937SEric Biggers 
62*7033b937SEric Biggers #include <asm/unaligned.h>
63*7033b937SEric Biggers #include <crypto/algapi.h>
64*7033b937SEric Biggers #include <linux/module.h>
65*7033b937SEric Biggers 
66*7033b937SEric Biggers /* Generic path for arbitrary size */
67*7033b937SEric Biggers static inline unsigned long
__crypto_memneq_generic(const void * a,const void * b,size_t size)68*7033b937SEric Biggers __crypto_memneq_generic(const void *a, const void *b, size_t size)
69*7033b937SEric Biggers {
70*7033b937SEric Biggers 	unsigned long neq = 0;
71*7033b937SEric Biggers 
72*7033b937SEric Biggers #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
73*7033b937SEric Biggers 	while (size >= sizeof(unsigned long)) {
74*7033b937SEric Biggers 		neq |= get_unaligned((unsigned long *)a) ^
75*7033b937SEric Biggers 		       get_unaligned((unsigned long *)b);
76*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
77*7033b937SEric Biggers 		a += sizeof(unsigned long);
78*7033b937SEric Biggers 		b += sizeof(unsigned long);
79*7033b937SEric Biggers 		size -= sizeof(unsigned long);
80*7033b937SEric Biggers 	}
81*7033b937SEric Biggers #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
82*7033b937SEric Biggers 	while (size > 0) {
83*7033b937SEric Biggers 		neq |= *(unsigned char *)a ^ *(unsigned char *)b;
84*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
85*7033b937SEric Biggers 		a += 1;
86*7033b937SEric Biggers 		b += 1;
87*7033b937SEric Biggers 		size -= 1;
88*7033b937SEric Biggers 	}
89*7033b937SEric Biggers 	return neq;
90*7033b937SEric Biggers }
91*7033b937SEric Biggers 
92*7033b937SEric Biggers /* Loop-free fast-path for frequently used 16-byte size */
__crypto_memneq_16(const void * a,const void * b)93*7033b937SEric Biggers static inline unsigned long __crypto_memneq_16(const void *a, const void *b)
94*7033b937SEric Biggers {
95*7033b937SEric Biggers 	unsigned long neq = 0;
96*7033b937SEric Biggers 
97*7033b937SEric Biggers #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
98*7033b937SEric Biggers 	if (sizeof(unsigned long) == 8) {
99*7033b937SEric Biggers 		neq |= get_unaligned((unsigned long *)a) ^
100*7033b937SEric Biggers 		       get_unaligned((unsigned long *)b);
101*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
102*7033b937SEric Biggers 		neq |= get_unaligned((unsigned long *)(a + 8)) ^
103*7033b937SEric Biggers 		       get_unaligned((unsigned long *)(b + 8));
104*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
105*7033b937SEric Biggers 	} else if (sizeof(unsigned int) == 4) {
106*7033b937SEric Biggers 		neq |= get_unaligned((unsigned int *)a) ^
107*7033b937SEric Biggers 		       get_unaligned((unsigned int *)b);
108*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
109*7033b937SEric Biggers 		neq |= get_unaligned((unsigned int *)(a + 4)) ^
110*7033b937SEric Biggers 		       get_unaligned((unsigned int *)(b + 4));
111*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
112*7033b937SEric Biggers 		neq |= get_unaligned((unsigned int *)(a + 8)) ^
113*7033b937SEric Biggers 		       get_unaligned((unsigned int *)(b + 8));
114*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
115*7033b937SEric Biggers 		neq |= get_unaligned((unsigned int *)(a + 12)) ^
116*7033b937SEric Biggers 		       get_unaligned((unsigned int *)(b + 12));
117*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
118*7033b937SEric Biggers 	} else
119*7033b937SEric Biggers #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
120*7033b937SEric Biggers 	{
121*7033b937SEric Biggers 		neq |= *(unsigned char *)(a)    ^ *(unsigned char *)(b);
122*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
123*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+1)  ^ *(unsigned char *)(b+1);
124*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
125*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+2)  ^ *(unsigned char *)(b+2);
126*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
127*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+3)  ^ *(unsigned char *)(b+3);
128*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
129*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+4)  ^ *(unsigned char *)(b+4);
130*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
131*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+5)  ^ *(unsigned char *)(b+5);
132*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
133*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+6)  ^ *(unsigned char *)(b+6);
134*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
135*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+7)  ^ *(unsigned char *)(b+7);
136*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
137*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+8)  ^ *(unsigned char *)(b+8);
138*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
139*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+9)  ^ *(unsigned char *)(b+9);
140*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
141*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+10) ^ *(unsigned char *)(b+10);
142*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
143*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+11) ^ *(unsigned char *)(b+11);
144*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
145*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+12) ^ *(unsigned char *)(b+12);
146*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
147*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+13) ^ *(unsigned char *)(b+13);
148*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
149*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+14) ^ *(unsigned char *)(b+14);
150*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
151*7033b937SEric Biggers 		neq |= *(unsigned char *)(a+15) ^ *(unsigned char *)(b+15);
152*7033b937SEric Biggers 		OPTIMIZER_HIDE_VAR(neq);
153*7033b937SEric Biggers 	}
154*7033b937SEric Biggers 
155*7033b937SEric Biggers 	return neq;
156*7033b937SEric Biggers }
157*7033b937SEric Biggers 
158*7033b937SEric Biggers /* Compare two areas of memory without leaking timing information,
159*7033b937SEric Biggers  * and with special optimizations for common sizes.  Users should
160*7033b937SEric Biggers  * not call this function directly, but should instead use
161*7033b937SEric Biggers  * crypto_memneq defined in crypto/algapi.h.
162*7033b937SEric Biggers  */
__crypto_memneq(const void * a,const void * b,size_t size)163*7033b937SEric Biggers noinline unsigned long __crypto_memneq(const void *a, const void *b,
164*7033b937SEric Biggers 				       size_t size)
165*7033b937SEric Biggers {
166*7033b937SEric Biggers 	switch (size) {
167*7033b937SEric Biggers 	case 16:
168*7033b937SEric Biggers 		return __crypto_memneq_16(a, b);
169*7033b937SEric Biggers 	default:
170*7033b937SEric Biggers 		return __crypto_memneq_generic(a, b, size);
171*7033b937SEric Biggers 	}
172*7033b937SEric Biggers }
173*7033b937SEric Biggers EXPORT_SYMBOL(__crypto_memneq);
174