xref: /openbmc/qemu/crypto/clmul.c (revision 9a65a570fab1bf2e907d593631a6b588a821d365)
107f348d7SRichard Henderson /*
207f348d7SRichard Henderson  * Carry-less multiply operations.
307f348d7SRichard Henderson  * SPDX-License-Identifier: GPL-2.0-or-later
407f348d7SRichard Henderson  *
507f348d7SRichard Henderson  * Copyright (C) 2023 Linaro, Ltd.
607f348d7SRichard Henderson  */
707f348d7SRichard Henderson 
807f348d7SRichard Henderson #include "qemu/osdep.h"
907f348d7SRichard Henderson #include "crypto/clmul.h"
1007f348d7SRichard Henderson 
1107f348d7SRichard Henderson uint64_t clmul_8x8_low(uint64_t n, uint64_t m)
1207f348d7SRichard Henderson {
1307f348d7SRichard Henderson     uint64_t r = 0;
1407f348d7SRichard Henderson 
1507f348d7SRichard Henderson     for (int i = 0; i < 8; ++i) {
1607f348d7SRichard Henderson         uint64_t mask = (n & 0x0101010101010101ull) * 0xff;
1707f348d7SRichard Henderson         r ^= m & mask;
1807f348d7SRichard Henderson         m = (m << 1) & 0xfefefefefefefefeull;
1907f348d7SRichard Henderson         n >>= 1;
2007f348d7SRichard Henderson     }
2107f348d7SRichard Henderson     return r;
2207f348d7SRichard Henderson }
2307f348d7SRichard Henderson 
2407f348d7SRichard Henderson static uint64_t clmul_8x4_even_int(uint64_t n, uint64_t m)
2507f348d7SRichard Henderson {
2607f348d7SRichard Henderson     uint64_t r = 0;
2707f348d7SRichard Henderson 
2807f348d7SRichard Henderson     for (int i = 0; i < 8; ++i) {
2907f348d7SRichard Henderson         uint64_t mask = (n & 0x0001000100010001ull) * 0xffff;
3007f348d7SRichard Henderson         r ^= m & mask;
3107f348d7SRichard Henderson         n >>= 1;
3207f348d7SRichard Henderson         m <<= 1;
3307f348d7SRichard Henderson     }
3407f348d7SRichard Henderson     return r;
3507f348d7SRichard Henderson }
3607f348d7SRichard Henderson 
3707f348d7SRichard Henderson uint64_t clmul_8x4_even(uint64_t n, uint64_t m)
3807f348d7SRichard Henderson {
3907f348d7SRichard Henderson     n &= 0x00ff00ff00ff00ffull;
4007f348d7SRichard Henderson     m &= 0x00ff00ff00ff00ffull;
4107f348d7SRichard Henderson     return clmul_8x4_even_int(n, m);
4207f348d7SRichard Henderson }
4307f348d7SRichard Henderson 
4407f348d7SRichard Henderson uint64_t clmul_8x4_odd(uint64_t n, uint64_t m)
4507f348d7SRichard Henderson {
4607f348d7SRichard Henderson     return clmul_8x4_even(n >> 8, m >> 8);
4707f348d7SRichard Henderson }
4807f348d7SRichard Henderson 
4907f348d7SRichard Henderson static uint64_t unpack_8_to_16(uint64_t x)
5007f348d7SRichard Henderson {
5107f348d7SRichard Henderson     return  (x & 0x000000ff)
5207f348d7SRichard Henderson          | ((x & 0x0000ff00) << 8)
5307f348d7SRichard Henderson          | ((x & 0x00ff0000) << 16)
5407f348d7SRichard Henderson          | ((x & 0xff000000) << 24);
5507f348d7SRichard Henderson }
5607f348d7SRichard Henderson 
5707f348d7SRichard Henderson uint64_t clmul_8x4_packed(uint32_t n, uint32_t m)
5807f348d7SRichard Henderson {
5907f348d7SRichard Henderson     return clmul_8x4_even_int(unpack_8_to_16(n), unpack_8_to_16(m));
6007f348d7SRichard Henderson }
61cf1b2cabSRichard Henderson 
62cf1b2cabSRichard Henderson uint64_t clmul_16x2_even(uint64_t n, uint64_t m)
63cf1b2cabSRichard Henderson {
64cf1b2cabSRichard Henderson     uint64_t r = 0;
65cf1b2cabSRichard Henderson 
66cf1b2cabSRichard Henderson     n &= 0x0000ffff0000ffffull;
67cf1b2cabSRichard Henderson     m &= 0x0000ffff0000ffffull;
68cf1b2cabSRichard Henderson 
69cf1b2cabSRichard Henderson     for (int i = 0; i < 16; ++i) {
70cf1b2cabSRichard Henderson         uint64_t mask = (n & 0x0000000100000001ull) * 0xffffffffull;
71cf1b2cabSRichard Henderson         r ^= m & mask;
72cf1b2cabSRichard Henderson         n >>= 1;
73cf1b2cabSRichard Henderson         m <<= 1;
74cf1b2cabSRichard Henderson     }
75cf1b2cabSRichard Henderson     return r;
76cf1b2cabSRichard Henderson }
77cf1b2cabSRichard Henderson 
78cf1b2cabSRichard Henderson uint64_t clmul_16x2_odd(uint64_t n, uint64_t m)
79cf1b2cabSRichard Henderson {
80cf1b2cabSRichard Henderson     return clmul_16x2_even(n >> 16, m >> 16);
81cf1b2cabSRichard Henderson }
82*9a65a570SRichard Henderson 
83*9a65a570SRichard Henderson uint64_t clmul_32(uint32_t n, uint32_t m32)
84*9a65a570SRichard Henderson {
85*9a65a570SRichard Henderson     uint64_t r = 0;
86*9a65a570SRichard Henderson     uint64_t m = m32;
87*9a65a570SRichard Henderson 
88*9a65a570SRichard Henderson     for (int i = 0; i < 32; ++i) {
89*9a65a570SRichard Henderson         r ^= n & 1 ? m : 0;
90*9a65a570SRichard Henderson         n >>= 1;
91*9a65a570SRichard Henderson         m <<= 1;
92*9a65a570SRichard Henderson     }
93*9a65a570SRichard Henderson     return r;
94*9a65a570SRichard Henderson }
95