root/crypto/memneq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __crypto_memneq_generic
  2. __crypto_memneq_16
  3. __crypto_memneq

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

/* [<][>][^][v][top][bottom][index][help] */