3 Copyright (C) 2010, 2014 Niels Möller
5 This file is part of GNU Nettle.
7 GNU Nettle is free software: you can redistribute it and/or
8 modify it under the terms of either:
10 * the GNU Lesser General Public License as published by the Free
11 Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
16 * the GNU General Public License as published by the Free
17 Software Foundation; either version 2 of the License, or (at your
18 option) any later version.
20 or both in parallel, as here.
22 GNU Nettle is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 General Public License for more details.
27 You should have received copies of the GNU General Public License and
28 the GNU Lesser General Public License along with this program. If
29 not, see http://www.gnu.org/licenses/.
32 /* Implementation inspired by memcmp in glibc, contributed to the FSF
44 #include "memxor-internal.h"
46 #define WORD_T_THRESH 16
48 /* XOR word-aligned areas. n is the number of words, not bytes. */
50 memxor3_common_alignment (word_t *dst,
51 const word_t *a, const word_t *b, size_t n)
53 /* FIXME: Require n > 0? */
62 dst[n+1] = a[n+1] ^ b[n+1];
68 memxor3_different_alignment_b (word_t *dst,
69 const word_t *a, const unsigned char *b,
70 unsigned offset, size_t n)
79 shl = CHAR_BIT * offset;
80 shr = CHAR_BIT * (sizeof(word_t) - offset);
82 b_word = (const word_t *) ((uintptr_t) b & -sizeof(word_t));
84 /* Read top offset bytes, in native byte order. */
85 READ_PARTIAL (s0, (unsigned char *) &b_word[n], offset);
86 #ifdef WORDS_BIGENDIAN
96 dst[n] = a[n] ^ MERGE (s1, shl, s0, shr);
103 dst[n+1] = a[n+1] ^ MERGE(s0, shl, s1, shr);
105 dst[n] = a[n] ^ MERGE(s1, shl, s0, shr);
108 /* Read low wordsize - offset bytes */
109 READ_PARTIAL (s0, b, sizeof(word_t) - offset);
110 #ifndef WORDS_BIGENDIAN
112 #endif /* !WORDS_BIGENDIAN */
114 dst[0] = a[0] ^ MERGE(s0, shl, s1, shr);
118 memxor3_different_alignment_ab (word_t *dst,
119 const unsigned char *a, const unsigned char *b,
120 unsigned offset, size_t n)
123 const word_t *a_word;
124 const word_t *b_word;
130 shl = CHAR_BIT * offset;
131 shr = CHAR_BIT * (sizeof(word_t) - offset);
133 a_word = (const word_t *) ((uintptr_t) a & -sizeof(word_t));
134 b_word = (const word_t *) ((uintptr_t) b & -sizeof(word_t));
136 /* Read top offset bytes, in native byte order. */
137 READ_PARTIAL (s0, (unsigned char *) &a_word[n], offset);
138 READ_PARTIAL (t, (unsigned char *) &b_word[n], offset);
140 #ifdef WORDS_BIGENDIAN
149 s1 = a_word[n] ^ b_word[n];
150 dst[n] = MERGE (s1, shl, s0, shr);
156 s0 = a_word[n+1] ^ b_word[n+1];
157 dst[n+1] = MERGE(s0, shl, s1, shr);
158 s1 = a_word[n] ^ b_word[n];
159 dst[n] = MERGE(s1, shl, s0, shr);
162 /* Read low wordsize - offset bytes */
163 READ_PARTIAL (s0, a, sizeof(word_t) - offset);
164 READ_PARTIAL (t, b, sizeof(word_t) - offset);
166 #ifndef WORDS_BIGENDIAN
168 #endif /* !WORDS_BIGENDIAN */
170 dst[0] = MERGE(s0, shl, s1, shr);
174 memxor3_different_alignment_all (word_t *dst,
175 const unsigned char *a, const unsigned char *b,
176 unsigned a_offset, unsigned b_offset,
180 const word_t *a_word;
181 const word_t *b_word;
183 word_t a0, a1, b0, b1;
185 al = CHAR_BIT * a_offset;
186 ar = CHAR_BIT * (sizeof(word_t) - a_offset);
187 bl = CHAR_BIT * b_offset;
188 br = CHAR_BIT * (sizeof(word_t) - b_offset);
190 a_word = (const word_t *) ((uintptr_t) a & -sizeof(word_t));
191 b_word = (const word_t *) ((uintptr_t) b & -sizeof(word_t));
193 /* Read top offset bytes, in native byte order. */
194 READ_PARTIAL (a0, (unsigned char *) &a_word[n], a_offset);
195 READ_PARTIAL (b0, (unsigned char *) &b_word[n], b_offset);
196 #ifdef WORDS_BIGENDIAN
211 dst[n] = MERGE (a1, al, a0, ar) ^ MERGE (b1, bl, b0, br);
216 a0 = a_word[n+1]; b0 = b_word[n+1];
217 dst[n+1] = MERGE(a0, al, a1, ar) ^ MERGE(b0, bl, b1, br);
218 a1 = a_word[n]; b1 = b_word[n];
219 dst[n] = MERGE(a1, al, a0, ar) ^ MERGE(b1, bl, b0, br);
222 /* Read low wordsize - offset bytes */
223 READ_PARTIAL (a0, a, sizeof(word_t) - a_offset);
224 READ_PARTIAL (b0, b, sizeof(word_t) - b_offset);
225 #ifndef WORDS_BIGENDIAN
228 #endif /* !WORDS_BIGENDIAN */
230 dst[0] = MERGE(a0, al, a1, ar) ^ MERGE(b0, bl, b1, br);
233 /* Current implementation processes data in descending order, to
234 support overlapping operation with one of the sources overlapping
235 the start of the destination area. This feature is used only
236 internally by cbc decrypt, and it is not advertised or documented
239 memxor3(void *dst_in, const void *a_in, const void *b_in, size_t n)
241 unsigned char *dst = dst_in;
242 const unsigned char *a = a_in;
243 const unsigned char *b = b_in;
245 if (n >= WORD_T_THRESH)
252 for (i = ALIGN_OFFSET(dst + n); i > 0; i--)
255 dst[n] = a[n] ^ b[n];
258 a_offset = ALIGN_OFFSET(a + n);
259 b_offset = ALIGN_OFFSET(b + n);
261 nwords = n / sizeof (word_t);
262 n %= sizeof (word_t);
264 if (a_offset == b_offset)
267 memxor3_common_alignment((word_t *) (dst + n),
268 (const word_t *) (a + n),
269 (const word_t *) (b + n), nwords);
271 memxor3_different_alignment_ab((word_t *) (dst + n),
272 a + n, b + n, a_offset,
276 memxor3_different_alignment_b((word_t *) (dst + n),
277 (const word_t *) (a + n), b + n,
280 memxor3_different_alignment_b((word_t *) (dst + n),
281 (const word_t *) (b + n), a + n,
284 memxor3_different_alignment_all((word_t *) (dst + n), a + n, b + n,
285 a_offset, b_offset, nwords);
289 dst[n] = a[n] ^ b[n];