1 /* bufhelp.h - Some buffer manipulation helpers
2 * Copyright (C) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
4 * This file is part of Libgcrypt.
6 * Libgcrypt is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * Libgcrypt is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #ifndef GCRYPT_BUFHELP_H
20 #define GCRYPT_BUFHELP_H
26 #undef BUFHELP_FAST_UNALIGNED_ACCESS
27 #if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
28 defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
29 (defined(__i386__) || defined(__x86_64__) || \
30 (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \
32 /* These architectures are able of unaligned memory accesses and can
35 # define BUFHELP_FAST_UNALIGNED_ACCESS 1
39 #ifdef BUFHELP_FAST_UNALIGNED_ACCESS
40 /* Define type with one-byte alignment on architectures with fast unaligned
43 typedef struct bufhelp_int_s
46 } __attribute__((packed, aligned(1))) bufhelp_int_t;
48 /* Define type with default alignment for other architectures (unaligned
49 accessed handled in per byte loops).
51 typedef struct bufhelp_int_s
58 /* Optimized function for small buffer copying */
60 buf_cpy(void *_dst, const void *_src, size_t len)
62 #if __GNUC__ >= 4 && (defined(__x86_64__) || defined(__i386__))
63 /* For AMD64 and i386, memcpy is faster. */
64 memcpy(_dst, _src, len);
67 const byte *src = _src;
69 const bufhelp_int_t *lsrc;
70 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
71 const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
73 /* Skip fast processing if buffers are unaligned. */
74 if (((uintptr_t)dst | (uintptr_t)src) & longmask)
78 ldst = (bufhelp_int_t *)(void *)dst;
79 lsrc = (const bufhelp_int_t *)(const void *)src;
81 for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
82 (ldst++)->a = (lsrc++)->a;
85 src = (const byte *)lsrc;
87 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
93 #endif /*__GNUC__ >= 4 && (__x86_64__ || __i386__)*/
97 /* Optimized function for buffer xoring */
99 buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len)
102 const byte *src1 = _src1;
103 const byte *src2 = _src2;
105 const bufhelp_int_t *lsrc1, *lsrc2;
106 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
107 const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
109 /* Skip fast processing if buffers are unaligned. */
110 if (((uintptr_t)dst | (uintptr_t)src1 | (uintptr_t)src2) & longmask)
114 ldst = (bufhelp_int_t *)(void *)dst;
115 lsrc1 = (const bufhelp_int_t *)(const void *)src1;
116 lsrc2 = (const bufhelp_int_t *)(const void *)src2;
118 for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
119 (ldst++)->a = (lsrc1++)->a ^ (lsrc2++)->a;
122 src1 = (const byte *)lsrc1;
123 src2 = (const byte *)lsrc2;
125 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
130 *dst++ = *src1++ ^ *src2++;
134 /* Optimized function for in-place buffer xoring. */
136 buf_xor_1(void *_dst, const void *_src, size_t len)
139 const byte *src = _src;
141 const bufhelp_int_t *lsrc;
142 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
143 const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
145 /* Skip fast processing if buffers are unaligned. */
146 if (((uintptr_t)dst | (uintptr_t)src) & longmask)
150 ldst = (bufhelp_int_t *)(void *)dst;
151 lsrc = (const bufhelp_int_t *)(const void *)src;
153 for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
154 (ldst++)->a ^= (lsrc++)->a;
157 src = (const byte *)lsrc;
159 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
168 /* Optimized function for buffer xoring with two destination buffers. Used
169 mainly by CFB mode encryption. */
171 buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len)
175 const byte *src = _src;
176 bufhelp_int_t *ldst1, *ldst2;
177 const bufhelp_int_t *lsrc;
178 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
179 const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
181 /* Skip fast processing if buffers are unaligned. */
182 if (((uintptr_t)src | (uintptr_t)dst1 | (uintptr_t)dst2) & longmask)
186 ldst1 = (bufhelp_int_t *)(void *)dst1;
187 ldst2 = (bufhelp_int_t *)(void *)dst2;
188 lsrc = (const bufhelp_int_t *)(const void *)src;
190 for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
191 (ldst1++)->a = ((ldst2++)->a ^= (lsrc++)->a);
193 dst1 = (byte *)ldst1;
194 dst2 = (byte *)ldst2;
195 src = (const byte *)lsrc;
197 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
202 *dst1++ = (*dst2++ ^= *src++);
206 /* Optimized function for combined buffer xoring and copying. Used by mainly
207 CBC mode decryption. */
209 buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy,
210 const void *_src_cpy, size_t len)
212 byte *dst_xor = _dst_xor;
213 byte *srcdst_cpy = _srcdst_cpy;
214 const byte *src_xor = _src_xor;
215 const byte *src_cpy = _src_cpy;
217 bufhelp_int_t *ldst_xor, *lsrcdst_cpy;
218 const bufhelp_int_t *lsrc_cpy, *lsrc_xor;
220 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
221 const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
223 /* Skip fast processing if buffers are unaligned. */
224 if (((uintptr_t)src_cpy | (uintptr_t)src_xor | (uintptr_t)dst_xor |
225 (uintptr_t)srcdst_cpy) & longmask)
229 ldst_xor = (bufhelp_int_t *)(void *)dst_xor;
230 lsrc_xor = (const bufhelp_int_t *)(void *)src_xor;
231 lsrcdst_cpy = (bufhelp_int_t *)(void *)srcdst_cpy;
232 lsrc_cpy = (const bufhelp_int_t *)(const void *)src_cpy;
234 for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
236 ltemp = (lsrc_cpy++)->a;
237 (ldst_xor++)->a = (lsrcdst_cpy)->a ^ (lsrc_xor++)->a;
238 (lsrcdst_cpy++)->a = ltemp;
241 dst_xor = (byte *)ldst_xor;
242 src_xor = (const byte *)lsrc_xor;
243 srcdst_cpy = (byte *)lsrcdst_cpy;
244 src_cpy = (const byte *)lsrc_cpy;
246 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
253 *dst_xor++ = *srcdst_cpy ^ *src_xor++;
254 *srcdst_cpy++ = temp;
259 /* Optimized function for combined buffer xoring and copying. Used by mainly
260 CFB mode decryption. */
262 buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len)
264 buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len);
268 /* Constant-time compare of two buffers. Returns 1 if buffers are equal,
269 and 0 if buffers differ. */
271 buf_eq_const(const void *_a, const void *_b, size_t len)
277 /* Constant-time compare. */
278 for (i = 0, diff = 0; i < len; i++)
279 diff -= !!(a[i] - b[i]);
285 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
287 /* Functions for loading and storing unaligned u32 values of different
289 static inline u32 buf_get_be32(const void *_buf)
291 const byte *in = _buf;
292 return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \
293 ((u32)in[2] << 8) | (u32)in[3];
296 static inline u32 buf_get_le32(const void *_buf)
298 const byte *in = _buf;
299 return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \
300 ((u32)in[1] << 8) | (u32)in[0];
303 static inline void buf_put_be32(void *_buf, u32 val)
312 static inline void buf_put_le32(void *_buf, u32 val)
322 /* Functions for loading and storing unaligned u64 values of different
324 static inline u64 buf_get_be64(const void *_buf)
326 const byte *in = _buf;
327 return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \
328 ((u64)in[2] << 40) | ((u64)in[3] << 32) | \
329 ((u64)in[4] << 24) | ((u64)in[5] << 16) | \
330 ((u64)in[6] << 8) | (u64)in[7];
333 static inline u64 buf_get_le64(const void *_buf)
335 const byte *in = _buf;
336 return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \
337 ((u64)in[5] << 40) | ((u64)in[4] << 32) | \
338 ((u64)in[3] << 24) | ((u64)in[2] << 16) | \
339 ((u64)in[1] << 8) | (u64)in[0];
342 static inline void buf_put_be64(void *_buf, u64 val)
355 static inline void buf_put_le64(void *_buf, u64 val)
368 #else /*BUFHELP_FAST_UNALIGNED_ACCESS*/
370 typedef struct bufhelp_u32_s
373 } __attribute__((packed, aligned(1))) bufhelp_u32_t;
375 /* Functions for loading and storing unaligned u32 values of different
377 static inline u32 buf_get_be32(const void *_buf)
379 return be_bswap32(((const bufhelp_u32_t *)_buf)->a);
382 static inline u32 buf_get_le32(const void *_buf)
384 return le_bswap32(((const bufhelp_u32_t *)_buf)->a);
387 static inline void buf_put_be32(void *_buf, u32 val)
389 bufhelp_u32_t *out = _buf;
390 out->a = be_bswap32(val);
393 static inline void buf_put_le32(void *_buf, u32 val)
395 bufhelp_u32_t *out = _buf;
396 out->a = le_bswap32(val);
400 typedef struct bufhelp_u64_s
403 } __attribute__((packed, aligned(1))) bufhelp_u64_t;
405 /* Functions for loading and storing unaligned u64 values of different
407 static inline u64 buf_get_be64(const void *_buf)
409 return be_bswap64(((const bufhelp_u64_t *)_buf)->a);
412 static inline u64 buf_get_le64(const void *_buf)
414 return le_bswap64(((const bufhelp_u64_t *)_buf)->a);
417 static inline void buf_put_be64(void *_buf, u64 val)
419 bufhelp_u64_t *out = _buf;
420 out->a = be_bswap64(val);
423 static inline void buf_put_le64(void *_buf, u64 val)
425 bufhelp_u64_t *out = _buf;
426 out->a = le_bswap64(val);
430 #endif /*BUFHELP_FAST_UNALIGNED_ACCESS*/
432 #endif /*GCRYPT_BUFHELP_H*/