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 #ifndef __HAVE_ARCH_CRYPTO_MEMNEQ 67*7033b937SEric Biggers 68*7033b937SEric Biggers /* Generic path for arbitrary size */ 69*7033b937SEric Biggers static inline unsigned long 70*7033b937SEric Biggers __crypto_memneq_generic(const void *a, const void *b, size_t size) 71*7033b937SEric Biggers { 72*7033b937SEric Biggers unsigned long neq = 0; 73*7033b937SEric Biggers 74*7033b937SEric Biggers #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 75*7033b937SEric Biggers while (size >= sizeof(unsigned long)) { 76*7033b937SEric Biggers neq |= get_unaligned((unsigned long *)a) ^ 77*7033b937SEric Biggers get_unaligned((unsigned long *)b); 78*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 79*7033b937SEric Biggers a += sizeof(unsigned long); 80*7033b937SEric Biggers b += sizeof(unsigned long); 81*7033b937SEric Biggers size -= sizeof(unsigned long); 82*7033b937SEric Biggers } 83*7033b937SEric Biggers #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ 84*7033b937SEric Biggers while (size > 0) { 85*7033b937SEric Biggers neq |= *(unsigned char *)a ^ *(unsigned char *)b; 86*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 87*7033b937SEric Biggers a += 1; 88*7033b937SEric Biggers b += 1; 89*7033b937SEric Biggers size -= 1; 90*7033b937SEric Biggers } 91*7033b937SEric Biggers return neq; 92*7033b937SEric Biggers } 93*7033b937SEric Biggers 94*7033b937SEric Biggers /* Loop-free fast-path for frequently used 16-byte size */ 95*7033b937SEric Biggers static inline unsigned long __crypto_memneq_16(const void *a, const void *b) 96*7033b937SEric Biggers { 97*7033b937SEric Biggers unsigned long neq = 0; 98*7033b937SEric Biggers 99*7033b937SEric Biggers #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 100*7033b937SEric Biggers if (sizeof(unsigned long) == 8) { 101*7033b937SEric Biggers neq |= get_unaligned((unsigned long *)a) ^ 102*7033b937SEric Biggers get_unaligned((unsigned long *)b); 103*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 104*7033b937SEric Biggers neq |= get_unaligned((unsigned long *)(a + 8)) ^ 105*7033b937SEric Biggers get_unaligned((unsigned long *)(b + 8)); 106*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 107*7033b937SEric Biggers } else if (sizeof(unsigned int) == 4) { 108*7033b937SEric Biggers neq |= get_unaligned((unsigned int *)a) ^ 109*7033b937SEric Biggers get_unaligned((unsigned int *)b); 110*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 111*7033b937SEric Biggers neq |= get_unaligned((unsigned int *)(a + 4)) ^ 112*7033b937SEric Biggers get_unaligned((unsigned int *)(b + 4)); 113*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 114*7033b937SEric Biggers neq |= get_unaligned((unsigned int *)(a + 8)) ^ 115*7033b937SEric Biggers get_unaligned((unsigned int *)(b + 8)); 116*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 117*7033b937SEric Biggers neq |= get_unaligned((unsigned int *)(a + 12)) ^ 118*7033b937SEric Biggers get_unaligned((unsigned int *)(b + 12)); 119*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 120*7033b937SEric Biggers } else 121*7033b937SEric Biggers #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ 122*7033b937SEric Biggers { 123*7033b937SEric Biggers neq |= *(unsigned char *)(a) ^ *(unsigned char *)(b); 124*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 125*7033b937SEric Biggers neq |= *(unsigned char *)(a+1) ^ *(unsigned char *)(b+1); 126*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 127*7033b937SEric Biggers neq |= *(unsigned char *)(a+2) ^ *(unsigned char *)(b+2); 128*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 129*7033b937SEric Biggers neq |= *(unsigned char *)(a+3) ^ *(unsigned char *)(b+3); 130*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 131*7033b937SEric Biggers neq |= *(unsigned char *)(a+4) ^ *(unsigned char *)(b+4); 132*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 133*7033b937SEric Biggers neq |= *(unsigned char *)(a+5) ^ *(unsigned char *)(b+5); 134*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 135*7033b937SEric Biggers neq |= *(unsigned char *)(a+6) ^ *(unsigned char *)(b+6); 136*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 137*7033b937SEric Biggers neq |= *(unsigned char *)(a+7) ^ *(unsigned char *)(b+7); 138*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 139*7033b937SEric Biggers neq |= *(unsigned char *)(a+8) ^ *(unsigned char *)(b+8); 140*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 141*7033b937SEric Biggers neq |= *(unsigned char *)(a+9) ^ *(unsigned char *)(b+9); 142*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 143*7033b937SEric Biggers neq |= *(unsigned char *)(a+10) ^ *(unsigned char *)(b+10); 144*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 145*7033b937SEric Biggers neq |= *(unsigned char *)(a+11) ^ *(unsigned char *)(b+11); 146*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 147*7033b937SEric Biggers neq |= *(unsigned char *)(a+12) ^ *(unsigned char *)(b+12); 148*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 149*7033b937SEric Biggers neq |= *(unsigned char *)(a+13) ^ *(unsigned char *)(b+13); 150*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 151*7033b937SEric Biggers neq |= *(unsigned char *)(a+14) ^ *(unsigned char *)(b+14); 152*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 153*7033b937SEric Biggers neq |= *(unsigned char *)(a+15) ^ *(unsigned char *)(b+15); 154*7033b937SEric Biggers OPTIMIZER_HIDE_VAR(neq); 155*7033b937SEric Biggers } 156*7033b937SEric Biggers 157*7033b937SEric Biggers return neq; 158*7033b937SEric Biggers } 159*7033b937SEric Biggers 160*7033b937SEric Biggers /* Compare two areas of memory without leaking timing information, 161*7033b937SEric Biggers * and with special optimizations for common sizes. Users should 162*7033b937SEric Biggers * not call this function directly, but should instead use 163*7033b937SEric Biggers * crypto_memneq defined in crypto/algapi.h. 164*7033b937SEric Biggers */ 165*7033b937SEric Biggers noinline unsigned long __crypto_memneq(const void *a, const void *b, 166*7033b937SEric Biggers size_t size) 167*7033b937SEric Biggers { 168*7033b937SEric Biggers switch (size) { 169*7033b937SEric Biggers case 16: 170*7033b937SEric Biggers return __crypto_memneq_16(a, b); 171*7033b937SEric Biggers default: 172*7033b937SEric Biggers return __crypto_memneq_generic(a, b, size); 173*7033b937SEric Biggers } 174*7033b937SEric Biggers } 175*7033b937SEric Biggers EXPORT_SYMBOL(__crypto_memneq); 176*7033b937SEric Biggers 177*7033b937SEric Biggers #endif /* __HAVE_ARCH_CRYPTO_MEMNEQ */ 178*7033b937SEric Biggers 179*7033b937SEric Biggers MODULE_LICENSE("GPL"); 180