xref: /linux/include/crypto/utils.h (revision 84b9b44b)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Cryptographic utilities
4  *
5  * Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
6  */
7 #ifndef _CRYPTO_UTILS_H
8 #define _CRYPTO_UTILS_H
9 
10 #include <asm/unaligned.h>
11 #include <linux/compiler_attributes.h>
12 #include <linux/types.h>
13 
14 void __crypto_xor(u8 *dst, const u8 *src1, const u8 *src2, unsigned int size);
15 
16 static inline void crypto_xor(u8 *dst, const u8 *src, unsigned int size)
17 {
18 	if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
19 	    __builtin_constant_p(size) &&
20 	    (size % sizeof(unsigned long)) == 0) {
21 		unsigned long *d = (unsigned long *)dst;
22 		unsigned long *s = (unsigned long *)src;
23 		unsigned long l;
24 
25 		while (size > 0) {
26 			l = get_unaligned(d) ^ get_unaligned(s++);
27 			put_unaligned(l, d++);
28 			size -= sizeof(unsigned long);
29 		}
30 	} else {
31 		__crypto_xor(dst, dst, src, size);
32 	}
33 }
34 
35 static inline void crypto_xor_cpy(u8 *dst, const u8 *src1, const u8 *src2,
36 				  unsigned int size)
37 {
38 	if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
39 	    __builtin_constant_p(size) &&
40 	    (size % sizeof(unsigned long)) == 0) {
41 		unsigned long *d = (unsigned long *)dst;
42 		unsigned long *s1 = (unsigned long *)src1;
43 		unsigned long *s2 = (unsigned long *)src2;
44 		unsigned long l;
45 
46 		while (size > 0) {
47 			l = get_unaligned(s1++) ^ get_unaligned(s2++);
48 			put_unaligned(l, d++);
49 			size -= sizeof(unsigned long);
50 		}
51 	} else {
52 		__crypto_xor(dst, src1, src2, size);
53 	}
54 }
55 
56 noinline unsigned long __crypto_memneq(const void *a, const void *b, size_t size);
57 
58 /**
59  * crypto_memneq - Compare two areas of memory without leaking
60  *		   timing information.
61  *
62  * @a: One area of memory
63  * @b: Another area of memory
64  * @size: The size of the area.
65  *
66  * Returns 0 when data is equal, 1 otherwise.
67  */
68 static inline int crypto_memneq(const void *a, const void *b, size_t size)
69 {
70 	return __crypto_memneq(a, b, size) != 0UL ? 1 : 0;
71 }
72 
73 #endif	/* _CRYPTO_UTILS_H */
74