Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / nettle / memxor.c
blobf2feff04fa31fd7a8d54ac27114bcb66485c429d
1 /* memxor.c
3 */
5 /* nettle, low-level cryptographics library
7 * Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc.
8 * Copyright (C) 2010 Niels Möller
9 *
10 * The nettle library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or (at your
13 * option) any later version.
15 * The nettle library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with the nettle library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 * MA 02111-1301, USA.
26 /* Implementation inspired by memcmp in glibc, contributed to the FSF
27 by Torbjorn Granlund.
30 #if HAVE_CONFIG_H
31 # include "config.h"
32 #endif
34 #include <limits.h>
36 #include "memxor.h"
38 typedef unsigned long int word_t;
40 #if SIZEOF_LONG & (SIZEOF_LONG - 1)
41 #error Word size must be a power of two
42 #endif
44 #define ALIGN_OFFSET(p) ((uintptr_t) (p) % sizeof(word_t))
46 #ifndef WORDS_BIGENDIAN
47 #define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
48 #else
49 #define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2)))
50 #endif
52 #define WORD_T_THRESH 16
54 /* XOR word-aligned areas. n is the number of words, not bytes. */
55 static void
56 memxor_common_alignment (word_t *dst, const word_t *src, size_t n)
58 /* FIXME: Require n > 0? */
59 /* FIXME: Unroll four times, like memcmp? Probably not worth the
60 effort. */
62 if (n & 1)
64 *dst++ ^= *src++;
65 n--;
67 for (; n >= 2; dst += 2, src += 2, n -= 2)
69 dst[0] ^= src[0];
70 dst[1] ^= src[1];
74 /* XOR *un-aligned* src-area onto aligned dst area. n is number of
75 words, not bytes. Assumes we can read complete words at the start
76 and end of the src operand. */
77 static void
78 memxor_different_alignment (word_t *dst, const uint8_t *src, size_t n)
80 size_t i;
81 int shl, shr;
82 const word_t *src_word;
83 unsigned offset = ALIGN_OFFSET (src);
84 word_t s0, s1;
86 shl = CHAR_BIT * offset;
87 shr = CHAR_BIT * (sizeof(word_t) - offset);
89 src_word = (const word_t *) ((uintptr_t) src & -SIZEOF_LONG);
91 /* FIXME: Unroll four times, like memcmp? */
92 i = n & 1;
93 s0 = src_word[i];
94 if (i)
96 s1 = src_word[0];
97 dst[0] ^= MERGE (s1, shl, s0, shr);
100 for (; i < n; i += 2)
102 s1 = src_word[i+1];
103 dst[i] ^= MERGE(s0, shl, s1, shr);
104 s0 = src_word[i+2];
105 dst[i+1] ^= MERGE(s1, shl, s0, shr);
109 /* Performance, Intel SU1400 (x86_64): 0.25 cycles/byte aligned, 0.45
110 cycles/byte unaligned. */
112 /* XOR LEN bytes starting at SRCADDR onto DESTADDR. Result undefined
113 if the source overlaps with the destination. Return DESTADDR. */
114 uint8_t *
115 memxor(uint8_t *dst, const uint8_t *src, size_t n)
117 uint8_t *orig_dst = dst;
119 if (n >= WORD_T_THRESH)
121 /* There are at least some bytes to compare. No need to test
122 for N == 0 in this alignment loop. */
123 while (ALIGN_OFFSET (dst))
125 *dst++ ^= *src++;
126 n--;
128 if (ALIGN_OFFSET (src))
129 memxor_different_alignment ((word_t *) dst, src, n / sizeof(word_t));
130 else
131 memxor_common_alignment ((word_t *) dst, (const word_t *) src, n / sizeof(word_t));
133 dst += n & -SIZEOF_LONG;
134 src += n & -SIZEOF_LONG;
135 n = n & (SIZEOF_LONG - 1);
137 for (; n > 0; n--)
138 *dst++ ^= *src++;
140 return orig_dst;
144 /* XOR word-aligned areas. n is the number of words, not bytes. */
145 static void
146 memxor3_common_alignment (word_t *dst,
147 const word_t *a, const word_t *b, size_t n)
149 /* FIXME: Require n > 0? */
150 while (n-- > 0)
151 dst[n] = a[n] ^ b[n];
154 static void
155 memxor3_different_alignment_b (word_t *dst,
156 const word_t *a, const uint8_t *b, unsigned offset, size_t n)
158 int shl, shr;
159 const word_t *b_word;
161 word_t s0, s1;
163 shl = CHAR_BIT * offset;
164 shr = CHAR_BIT * (sizeof(word_t) - offset);
166 b_word = (const word_t *) ((uintptr_t) b & -SIZEOF_LONG);
168 if (n & 1)
170 n--;
171 s1 = b_word[n];
172 s0 = b_word[n+1];
173 dst[n] = a[n] ^ MERGE (s1, shl, s0, shr);
175 else
176 s1 = b_word[n];
178 while (n > 0)
180 n -= 2;
181 s0 = b_word[n+1];
182 dst[n+1] = a[n+1] ^ MERGE(s0, shl, s1, shr);
183 s1 = b_word[n];
184 dst[n] = a[n] ^ MERGE(s1, shl, s0, shr);
188 static void
189 memxor3_different_alignment_ab (word_t *dst,
190 const uint8_t *a, const uint8_t *b,
191 unsigned offset, size_t n)
193 int shl, shr;
194 const word_t *a_word;
195 const word_t *b_word;
197 word_t s0, s1;
199 shl = CHAR_BIT * offset;
200 shr = CHAR_BIT * (sizeof(word_t) - offset);
202 a_word = (const word_t *) ((uintptr_t) a & -SIZEOF_LONG);
203 b_word = (const word_t *) ((uintptr_t) b & -SIZEOF_LONG);
205 if (n & 1)
207 n--;
208 s1 = a_word[n] ^ b_word[n];
209 s0 = a_word[n+1] ^ b_word[n+1];
210 dst[n] = MERGE (s1, shl, s0, shr);
212 else
213 s1 = a_word[n] ^ b_word[n];
215 while (n > 0)
217 n -= 2;
218 s0 = a_word[n+1] ^ b_word[n+1];
219 dst[n+1] = MERGE(s0, shl, s1, shr);
220 s1 = a_word[n] ^ b_word[n];
221 dst[n] = MERGE(s1, shl, s0, shr);
225 static void
226 memxor3_different_alignment_all (word_t *dst,
227 const uint8_t *a, const uint8_t *b,
228 unsigned a_offset, unsigned b_offset,
229 size_t n)
231 int al, ar, bl, br;
232 const word_t *a_word;
233 const word_t *b_word;
235 word_t a0, a1, b0, b1;
237 al = CHAR_BIT * a_offset;
238 ar = CHAR_BIT * (sizeof(word_t) - a_offset);
239 bl = CHAR_BIT * b_offset;
240 br = CHAR_BIT * (sizeof(word_t) - b_offset);
242 a_word = (const word_t *) ((uintptr_t) a & -SIZEOF_LONG);
243 b_word = (const word_t *) ((uintptr_t) b & -SIZEOF_LONG);
245 if (n & 1)
247 n--;
248 a1 = a_word[n]; a0 = a_word[n+1];
249 b1 = b_word[n]; b0 = b_word[n+1];
251 dst[n] = MERGE (a1, al, a0, ar) ^ MERGE (b1, bl, b0, br);
253 else
255 a1 = a_word[n];
256 b1 = b_word[n];
259 while (n > 0)
261 n -= 2;
262 a0 = a_word[n+1]; b0 = b_word[n+1];
263 dst[n+1] = MERGE(a0, al, a1, ar) ^ MERGE(b0, bl, b1, br);
264 a1 = a_word[n]; b1 = b_word[n];
265 dst[n] = MERGE(a1, al, a0, ar) ^ MERGE(b1, bl, b0, br);
269 /* Current implementation processes data in descending order, to
270 support overlapping operation with one of the sources overlapping
271 the start of the destination area. This feature is used only
272 internally by cbc decrypt, and it is not advertised or documented
273 to nettle users. */
274 uint8_t *
275 memxor3(uint8_t *dst, const uint8_t *a, const uint8_t *b, size_t n)
277 if (n >= WORD_T_THRESH)
279 unsigned i;
280 unsigned a_offset;
281 unsigned b_offset;
282 size_t nwords;
284 for (i = ALIGN_OFFSET(dst + n); i > 0; i--)
286 n--;
287 dst[n] = a[n] ^ b[n];
290 a_offset = ALIGN_OFFSET(a + n);
291 b_offset = ALIGN_OFFSET(b + n);
293 nwords = n / sizeof (word_t);
294 n %= sizeof (word_t);
296 if (a_offset == b_offset)
298 if (!a_offset)
299 memxor3_common_alignment((word_t *) (dst + n),
300 (const word_t *) (a + n),
301 (const word_t *) (b + n), nwords);
302 else
303 memxor3_different_alignment_ab((word_t *) (dst + n),
304 a + n, b + n, a_offset,
305 nwords);
307 else if (!a_offset)
308 memxor3_different_alignment_b((word_t *) (dst + n),
309 (const word_t *) (a + n), b + n,
310 b_offset, nwords);
311 else if (!b_offset)
312 memxor3_different_alignment_b((word_t *) (dst + n),
313 (const word_t *) (b + n), a + n,
314 a_offset, nwords);
315 else
316 memxor3_different_alignment_all((word_t *) (dst + n), a + n, b + n,
317 a_offset, b_offset, nwords);
320 while (n-- > 0)
321 dst[n] = a[n] ^ b[n];
323 return dst;