1a8e1175bSopenharmony_ci#include "common.h"
2a8e1175bSopenharmony_ci
3a8e1175bSopenharmony_civoid mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n)
4a8e1175bSopenharmony_ci{
5a8e1175bSopenharmony_ci    size_t i = 0;
6a8e1175bSopenharmony_ci#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
7a8e1175bSopenharmony_ci#if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
8a8e1175bSopenharmony_ci    /* This codepath probably only makes sense on architectures with 64-bit registers */
9a8e1175bSopenharmony_ci    for (; (i + 8) <= n; i += 8) {
10a8e1175bSopenharmony_ci        uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
11a8e1175bSopenharmony_ci        mbedtls_put_unaligned_uint64(r + i, x);
12a8e1175bSopenharmony_ci    }
13a8e1175bSopenharmony_ci#if defined(__IAR_SYSTEMS_ICC__)
14a8e1175bSopenharmony_ci    /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
15a8e1175bSopenharmony_ci     * where n is a constant multiple of 8.
16a8e1175bSopenharmony_ci     * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
17a8e1175bSopenharmony_ci     * constant, and is a very small perf regression if n is not a compile-time constant. */
18a8e1175bSopenharmony_ci    if (n % 8 == 0) {
19a8e1175bSopenharmony_ci        return;
20a8e1175bSopenharmony_ci    }
21a8e1175bSopenharmony_ci#endif
22a8e1175bSopenharmony_ci#else
23a8e1175bSopenharmony_ci    for (; (i + 4) <= n; i += 4) {
24a8e1175bSopenharmony_ci        uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
25a8e1175bSopenharmony_ci        mbedtls_put_unaligned_uint32(r + i, x);
26a8e1175bSopenharmony_ci    }
27a8e1175bSopenharmony_ci#if defined(__IAR_SYSTEMS_ICC__)
28a8e1175bSopenharmony_ci    if (n % 4 == 0) {
29a8e1175bSopenharmony_ci        return;
30a8e1175bSopenharmony_ci    }
31a8e1175bSopenharmony_ci#endif
32a8e1175bSopenharmony_ci#endif
33a8e1175bSopenharmony_ci#endif
34a8e1175bSopenharmony_ci    for (; i < n; i++) {
35a8e1175bSopenharmony_ci        r[i] = a[i] ^ b[i];
36a8e1175bSopenharmony_ci    }
37a8e1175bSopenharmony_ci}
38a8e1175bSopenharmony_ci
39a8e1175bSopenharmony_civoid mbedtls_xor_no_simd(unsigned char *r,
40a8e1175bSopenharmony_ci                         const unsigned char *a,
41a8e1175bSopenharmony_ci                         const unsigned char *b,
42a8e1175bSopenharmony_ci                         size_t n)
43a8e1175bSopenharmony_ci{
44a8e1175bSopenharmony_ci    size_t i = 0;
45a8e1175bSopenharmony_ci#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
46a8e1175bSopenharmony_ci#if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
47a8e1175bSopenharmony_ci    /* This codepath probably only makes sense on architectures with 64-bit registers */
48a8e1175bSopenharmony_ci    for (; (i + 8) <= n; i += 8) {
49a8e1175bSopenharmony_ci        uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
50a8e1175bSopenharmony_ci        mbedtls_put_unaligned_uint64(r + i, x);
51a8e1175bSopenharmony_ci    }
52a8e1175bSopenharmony_ci#if defined(__IAR_SYSTEMS_ICC__)
53a8e1175bSopenharmony_ci    /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
54a8e1175bSopenharmony_ci     * where n is a constant multiple of 8.
55a8e1175bSopenharmony_ci     * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
56a8e1175bSopenharmony_ci     * constant, and is a very small perf regression if n is not a compile-time constant. */
57a8e1175bSopenharmony_ci    if (n % 8 == 0) {
58a8e1175bSopenharmony_ci        return;
59a8e1175bSopenharmony_ci    }
60a8e1175bSopenharmony_ci#endif
61a8e1175bSopenharmony_ci#else
62a8e1175bSopenharmony_ci    for (; (i + 4) <= n; i += 4) {
63a8e1175bSopenharmony_ci        uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
64a8e1175bSopenharmony_ci        mbedtls_put_unaligned_uint32(r + i, x);
65a8e1175bSopenharmony_ci    }
66a8e1175bSopenharmony_ci#if defined(__IAR_SYSTEMS_ICC__)
67a8e1175bSopenharmony_ci    if (n % 4 == 0) {
68a8e1175bSopenharmony_ci        return;
69a8e1175bSopenharmony_ci    }
70a8e1175bSopenharmony_ci#endif
71a8e1175bSopenharmony_ci#endif
72a8e1175bSopenharmony_ci#endif
73a8e1175bSopenharmony_ci    for (; i < n; i++) {
74a8e1175bSopenharmony_ci        r[i] = a[i] ^ b[i];
75a8e1175bSopenharmony_ci    }
76a8e1175bSopenharmony_ci}