1 /* bufhelp.h - Some buffer manipulation helpers
2 * Copyright © 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
26 # include <stdint.h> /* uintptr_t */
27 #elif defined(HAVE_INTTYPES_H)
28 # include <inttypes.h>
30 /* In this case, uintptr_t is provided by config.h. */
36 #if defined(__i386__) || defined(__x86_64__) || \
37 defined(__powerpc__) || defined(__powerpc64__) || \
38 (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \
40 /* These architectures are able of unaligned memory accesses and can
43 # define BUFHELP_FAST_UNALIGNED_ACCESS 1
47 /* Optimized function for small buffer copying */
49 buf_cpy(void *_dst, const void *_src, size_t len)
51 #if __GNUC__ >= 4 && (defined(__x86_64__) || defined(__i386__))
52 /* For AMD64 and i386, memcpy is faster. */
53 memcpy(_dst, _src, len);
56 const byte *src = _src;
58 const uintptr_t *lsrc;
59 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
60 const unsigned int longmask = sizeof(uintptr_t) - 1;
62 /* Skip fast processing if buffers are unaligned. */
63 if (((uintptr_t)dst | (uintptr_t)src) & longmask)
67 ldst = (uintptr_t *)(void *)dst;
68 lsrc = (const uintptr_t *)(const void *)src;
70 for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t))
74 src = (const byte *)lsrc;
76 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
82 #endif /*__GNUC__ >= 4 && (__x86_64__ || __i386__)*/
86 /* Optimized function for buffer xoring */
88 buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len)
91 const byte *src1 = _src1;
92 const byte *src2 = _src2;
94 const uintptr_t *lsrc1, *lsrc2;
95 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
96 const unsigned int longmask = sizeof(uintptr_t) - 1;
98 /* Skip fast processing if buffers are unaligned. */
99 if (((uintptr_t)dst | (uintptr_t)src1 | (uintptr_t)src2) & longmask)
103 ldst = (uintptr_t *)(void *)dst;
104 lsrc1 = (const uintptr_t *)(const void *)src1;
105 lsrc2 = (const uintptr_t *)(const void *)src2;
107 for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t))
108 *ldst++ = *lsrc1++ ^ *lsrc2++;
111 src1 = (const byte *)lsrc1;
112 src2 = (const byte *)lsrc2;
114 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
119 *dst++ = *src1++ ^ *src2++;
123 /* Optimized function for buffer xoring with two destination buffers. Used
124 mainly by CFB mode encryption. */
126 buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len)
130 const byte *src = _src;
131 uintptr_t *ldst1, *ldst2;
132 const uintptr_t *lsrc;
133 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
134 const unsigned int longmask = sizeof(uintptr_t) - 1;
136 /* Skip fast processing if buffers are unaligned. */
137 if (((uintptr_t)src | (uintptr_t)dst1 | (uintptr_t)dst2) & longmask)
141 ldst1 = (uintptr_t *)(void *)dst1;
142 ldst2 = (uintptr_t *)(void *)dst2;
143 lsrc = (const uintptr_t *)(const void *)src;
145 for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t))
146 *ldst1++ = (*ldst2++ ^= *lsrc++);
148 dst1 = (byte *)ldst1;
149 dst2 = (byte *)ldst2;
150 src = (const byte *)lsrc;
152 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
157 *dst1++ = (*dst2++ ^= *src++);
161 /* Optimized function for combined buffer xoring and copying. Used by mainly
162 CBC mode decryption. */
164 buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy,
165 const void *_src_cpy, size_t len)
167 byte *dst_xor = _dst_xor;
168 byte *srcdst_cpy = _srcdst_cpy;
169 const byte *src_xor = _src_xor;
170 const byte *src_cpy = _src_cpy;
172 uintptr_t *ldst_xor, *lsrcdst_cpy;
173 const uintptr_t *lsrc_cpy, *lsrc_xor;
175 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
176 const unsigned int longmask = sizeof(uintptr_t) - 1;
178 /* Skip fast processing if buffers are unaligned. */
179 if (((uintptr_t)src_cpy | (uintptr_t)src_xor | (uintptr_t)dst_xor |
180 (uintptr_t)srcdst_cpy) & longmask)
184 ldst_xor = (uintptr_t *)(void *)dst_xor;
185 lsrc_xor = (const uintptr_t *)(void *)src_xor;
186 lsrcdst_cpy = (uintptr_t *)(void *)srcdst_cpy;
187 lsrc_cpy = (const uintptr_t *)(const void *)src_cpy;
189 for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t))
192 *ldst_xor++ = *lsrcdst_cpy ^ *lsrc_xor++;
193 *lsrcdst_cpy++ = ltemp;
196 dst_xor = (byte *)ldst_xor;
197 src_xor = (const byte *)lsrc_xor;
198 srcdst_cpy = (byte *)lsrcdst_cpy;
199 src_cpy = (const byte *)lsrc_cpy;
201 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
208 *dst_xor++ = *srcdst_cpy ^ *src_xor++;
209 *srcdst_cpy++ = temp;
214 /* Optimized function for combined buffer xoring and copying. Used by mainly
215 CFB mode decryption. */
217 buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len)
219 buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len);
223 /* Constant-time compare of two buffers. Returns 1 if buffers are equal,
224 and 0 if buffers differ. */
226 buf_eq_const(const void *_a, const void *_b, size_t len)
232 /* Constant-time compare. */
233 for (i = 0, diff = 0; i < len; i++)
234 diff -= !!(a[i] - b[i]);
240 #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
242 /* Functions for loading and storing unaligned u32 values of different
244 static inline u32 buf_get_be32(const void *_buf)
246 const byte *in = _buf;
247 return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \
248 ((u32)in[2] << 8) | (u32)in[3];
251 static inline u32 buf_get_le32(const void *_buf)
253 const byte *in = _buf;
254 return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \
255 ((u32)in[1] << 8) | (u32)in[0];
258 static inline void buf_put_be32(void *_buf, u32 val)
267 static inline void buf_put_le32(void *_buf, u32 val)
276 #ifdef HAVE_U64_TYPEDEF
277 /* Functions for loading and storing unaligned u64 values of different
279 static inline u64 buf_get_be64(const void *_buf)
281 const byte *in = _buf;
282 return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \
283 ((u64)in[2] << 40) | ((u64)in[3] << 32) | \
284 ((u64)in[4] << 24) | ((u64)in[5] << 16) | \
285 ((u64)in[6] << 8) | (u64)in[7];
288 static inline u64 buf_get_le64(const void *_buf)
290 const byte *in = _buf;
291 return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \
292 ((u64)in[5] << 40) | ((u64)in[4] << 32) | \
293 ((u64)in[3] << 24) | ((u64)in[2] << 16) | \
294 ((u64)in[1] << 8) | (u64)in[0];
297 static inline void buf_put_be64(void *_buf, u64 val)
310 static inline void buf_put_le64(void *_buf, u64 val)
322 #endif /*HAVE_U64_TYPEDEF*/
324 #else /*BUFHELP_FAST_UNALIGNED_ACCESS*/
326 /* Functions for loading and storing unaligned u32 values of different
328 static inline u32 buf_get_be32(const void *_buf)
330 return be_bswap32(*(const u32 *)_buf);
333 static inline u32 buf_get_le32(const void *_buf)
335 return le_bswap32(*(const u32 *)_buf);
338 static inline void buf_put_be32(void *_buf, u32 val)
341 *out = be_bswap32(val);
344 static inline void buf_put_le32(void *_buf, u32 val)
347 *out = le_bswap32(val);
350 #ifdef HAVE_U64_TYPEDEF
351 /* Functions for loading and storing unaligned u64 values of different
353 static inline u64 buf_get_be64(const void *_buf)
355 return be_bswap64(*(const u64 *)_buf);
358 static inline u64 buf_get_le64(const void *_buf)
360 return le_bswap64(*(const u64 *)_buf);
363 static inline void buf_put_be64(void *_buf, u64 val)
366 *out = be_bswap64(val);
369 static inline void buf_put_le64(void *_buf, u64 val)
372 *out = le_bswap64(val);
374 #endif /*HAVE_U64_TYPEDEF*/
376 #endif /*BUFHELP_FAST_UNALIGNED_ACCESS*/
378 #endif /*G10_BITHELP_H*/