18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Constant-time equality testing of memory regions. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Authors: 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * James Yonan <james@openvpn.net> 78c2ecf20Sopenharmony_ci * Daniel Borkmann <dborkman@redhat.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license. When using or 108c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 178c2ecf20Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as 188c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 218c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 228c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 238c2ecf20Sopenharmony_ci * General Public License for more details. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 268c2ecf20Sopenharmony_ci * along with this program; if not, write to the Free Software 278c2ecf20Sopenharmony_ci * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 288c2ecf20Sopenharmony_ci * The full GNU General Public License is included in this distribution 298c2ecf20Sopenharmony_ci * in the file called LICENSE.GPL. 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * BSD LICENSE 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 368c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 378c2ecf20Sopenharmony_ci * are met: 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * * Redistributions of source code must retain the above copyright 408c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 418c2ecf20Sopenharmony_ci * * Redistributions in binary form must reproduce the above copyright 428c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 438c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 448c2ecf20Sopenharmony_ci * distribution. 458c2ecf20Sopenharmony_ci * * Neither the name of OpenVPN Technologies nor the names of its 468c2ecf20Sopenharmony_ci * contributors may be used to endorse or promote products derived 478c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 508c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 518c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 528c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 538c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 548c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 558c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 568c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 578c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 588c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 598c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#ifndef __HAVE_ARCH_CRYPTO_MEMNEQ 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* Generic path for arbitrary size */ 678c2ecf20Sopenharmony_cistatic inline unsigned long 688c2ecf20Sopenharmony_ci__crypto_memneq_generic(const void *a, const void *b, size_t size) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci unsigned long neq = 0; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 738c2ecf20Sopenharmony_ci while (size >= sizeof(unsigned long)) { 748c2ecf20Sopenharmony_ci neq |= *(unsigned long *)a ^ *(unsigned long *)b; 758c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 768c2ecf20Sopenharmony_ci a += sizeof(unsigned long); 778c2ecf20Sopenharmony_ci b += sizeof(unsigned long); 788c2ecf20Sopenharmony_ci size -= sizeof(unsigned long); 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ 818c2ecf20Sopenharmony_ci while (size > 0) { 828c2ecf20Sopenharmony_ci neq |= *(unsigned char *)a ^ *(unsigned char *)b; 838c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 848c2ecf20Sopenharmony_ci a += 1; 858c2ecf20Sopenharmony_ci b += 1; 868c2ecf20Sopenharmony_ci size -= 1; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci return neq; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* Loop-free fast-path for frequently used 16-byte size */ 928c2ecf20Sopenharmony_cistatic inline unsigned long __crypto_memneq_16(const void *a, const void *b) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci unsigned long neq = 0; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 978c2ecf20Sopenharmony_ci if (sizeof(unsigned long) == 8) { 988c2ecf20Sopenharmony_ci neq |= *(unsigned long *)(a) ^ *(unsigned long *)(b); 998c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1008c2ecf20Sopenharmony_ci neq |= *(unsigned long *)(a+8) ^ *(unsigned long *)(b+8); 1018c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1028c2ecf20Sopenharmony_ci } else if (sizeof(unsigned int) == 4) { 1038c2ecf20Sopenharmony_ci neq |= *(unsigned int *)(a) ^ *(unsigned int *)(b); 1048c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1058c2ecf20Sopenharmony_ci neq |= *(unsigned int *)(a+4) ^ *(unsigned int *)(b+4); 1068c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1078c2ecf20Sopenharmony_ci neq |= *(unsigned int *)(a+8) ^ *(unsigned int *)(b+8); 1088c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1098c2ecf20Sopenharmony_ci neq |= *(unsigned int *)(a+12) ^ *(unsigned int *)(b+12); 1108c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1118c2ecf20Sopenharmony_ci } else 1128c2ecf20Sopenharmony_ci#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ 1138c2ecf20Sopenharmony_ci { 1148c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a) ^ *(unsigned char *)(b); 1158c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1168c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+1) ^ *(unsigned char *)(b+1); 1178c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1188c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+2) ^ *(unsigned char *)(b+2); 1198c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1208c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+3) ^ *(unsigned char *)(b+3); 1218c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1228c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+4) ^ *(unsigned char *)(b+4); 1238c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1248c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+5) ^ *(unsigned char *)(b+5); 1258c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1268c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+6) ^ *(unsigned char *)(b+6); 1278c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1288c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+7) ^ *(unsigned char *)(b+7); 1298c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1308c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+8) ^ *(unsigned char *)(b+8); 1318c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1328c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+9) ^ *(unsigned char *)(b+9); 1338c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1348c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+10) ^ *(unsigned char *)(b+10); 1358c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1368c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+11) ^ *(unsigned char *)(b+11); 1378c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1388c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+12) ^ *(unsigned char *)(b+12); 1398c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1408c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+13) ^ *(unsigned char *)(b+13); 1418c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1428c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+14) ^ *(unsigned char *)(b+14); 1438c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1448c2ecf20Sopenharmony_ci neq |= *(unsigned char *)(a+15) ^ *(unsigned char *)(b+15); 1458c2ecf20Sopenharmony_ci OPTIMIZER_HIDE_VAR(neq); 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci return neq; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci/* Compare two areas of memory without leaking timing information, 1528c2ecf20Sopenharmony_ci * and with special optimizations for common sizes. Users should 1538c2ecf20Sopenharmony_ci * not call this function directly, but should instead use 1548c2ecf20Sopenharmony_ci * crypto_memneq defined in crypto/algapi.h. 1558c2ecf20Sopenharmony_ci */ 1568c2ecf20Sopenharmony_cinoinline unsigned long __crypto_memneq(const void *a, const void *b, 1578c2ecf20Sopenharmony_ci size_t size) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci switch (size) { 1608c2ecf20Sopenharmony_ci case 16: 1618c2ecf20Sopenharmony_ci return __crypto_memneq_16(a, b); 1628c2ecf20Sopenharmony_ci default: 1638c2ecf20Sopenharmony_ci return __crypto_memneq_generic(a, b, size); 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__crypto_memneq); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci#endif /* __HAVE_ARCH_CRYPTO_MEMNEQ */ 169