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