• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
__crypto_memneq_generic(const void * a,const void * b,size_t size)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 */
__crypto_memneq_16(const void * a,const void * b)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   */
__crypto_memneq(const void * a,const void * b,size_t size)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 */
169