]>
Commit | Line | Data |
---|---|---|
07f348d7 RH |
1 | /* |
2 | * Carry-less multiply operations. | |
3 | * SPDX-License-Identifier: GPL-2.0-or-later | |
4 | * | |
5 | * Copyright (C) 2023 Linaro, Ltd. | |
6 | */ | |
7 | ||
8 | #include "qemu/osdep.h" | |
9 | #include "crypto/clmul.h" | |
10 | ||
11 | uint64_t clmul_8x8_low(uint64_t n, uint64_t m) | |
12 | { | |
13 | uint64_t r = 0; | |
14 | ||
15 | for (int i = 0; i < 8; ++i) { | |
16 | uint64_t mask = (n & 0x0101010101010101ull) * 0xff; | |
17 | r ^= m & mask; | |
18 | m = (m << 1) & 0xfefefefefefefefeull; | |
19 | n >>= 1; | |
20 | } | |
21 | return r; | |
22 | } | |
23 | ||
24 | static uint64_t clmul_8x4_even_int(uint64_t n, uint64_t m) | |
25 | { | |
26 | uint64_t r = 0; | |
27 | ||
28 | for (int i = 0; i < 8; ++i) { | |
29 | uint64_t mask = (n & 0x0001000100010001ull) * 0xffff; | |
30 | r ^= m & mask; | |
31 | n >>= 1; | |
32 | m <<= 1; | |
33 | } | |
34 | return r; | |
35 | } | |
36 | ||
37 | uint64_t clmul_8x4_even(uint64_t n, uint64_t m) | |
38 | { | |
39 | n &= 0x00ff00ff00ff00ffull; | |
40 | m &= 0x00ff00ff00ff00ffull; | |
41 | return clmul_8x4_even_int(n, m); | |
42 | } | |
43 | ||
44 | uint64_t clmul_8x4_odd(uint64_t n, uint64_t m) | |
45 | { | |
46 | return clmul_8x4_even(n >> 8, m >> 8); | |
47 | } | |
48 | ||
49 | static uint64_t unpack_8_to_16(uint64_t x) | |
50 | { | |
51 | return (x & 0x000000ff) | |
52 | | ((x & 0x0000ff00) << 8) | |
53 | | ((x & 0x00ff0000) << 16) | |
54 | | ((x & 0xff000000) << 24); | |
55 | } | |
56 | ||
57 | uint64_t clmul_8x4_packed(uint32_t n, uint32_t m) | |
58 | { | |
59 | return clmul_8x4_even_int(unpack_8_to_16(n), unpack_8_to_16(m)); | |
60 | } | |
cf1b2cab RH |
61 | |
62 | uint64_t clmul_16x2_even(uint64_t n, uint64_t m) | |
63 | { | |
64 | uint64_t r = 0; | |
65 | ||
66 | n &= 0x0000ffff0000ffffull; | |
67 | m &= 0x0000ffff0000ffffull; | |
68 | ||
69 | for (int i = 0; i < 16; ++i) { | |
70 | uint64_t mask = (n & 0x0000000100000001ull) * 0xffffffffull; | |
71 | r ^= m & mask; | |
72 | n >>= 1; | |
73 | m <<= 1; | |
74 | } | |
75 | return r; | |
76 | } | |
77 | ||
78 | uint64_t clmul_16x2_odd(uint64_t n, uint64_t m) | |
79 | { | |
80 | return clmul_16x2_even(n >> 16, m >> 16); | |
81 | } | |
9a65a570 RH |
82 | |
83 | uint64_t clmul_32(uint32_t n, uint32_t m32) | |
84 | { | |
85 | uint64_t r = 0; | |
86 | uint64_t m = m32; | |
87 | ||
88 | for (int i = 0; i < 32; ++i) { | |
89 | r ^= n & 1 ? m : 0; | |
90 | n >>= 1; | |
91 | m <<= 1; | |
92 | } | |
93 | return r; | |
94 | } | |
00f463b3 RH |
95 | |
96 | Int128 clmul_64_gen(uint64_t n, uint64_t m) | |
97 | { | |
98 | uint64_t rl = 0, rh = 0; | |
99 | ||
100 | /* Bit 0 can only influence the low 64-bit result. */ | |
101 | if (n & 1) { | |
102 | rl = m; | |
103 | } | |
104 | ||
105 | for (int i = 1; i < 64; ++i) { | |
106 | uint64_t mask = -((n >> i) & 1); | |
107 | rl ^= (m << i) & mask; | |
108 | rh ^= (m >> (64 - i)) & mask; | |
109 | } | |
110 | return int128_make128(rl, rh); | |
111 | } |