1fb7ef469SJerome Forissier // SPDX-License-Identifier: Apache-2.0 2b8c186b5SJens Wiklander /* 3*b314df1fSJens Wiklander * Copyright (c) 2017-2020, Linaro Limited 4*b314df1fSJens Wiklander * 5b8c186b5SJens Wiklander * NIST SP800-38D compliant GCM implementation 6b8c186b5SJens Wiklander * 7b8c186b5SJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 8b8c186b5SJens Wiklander * 9b8c186b5SJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 10b8c186b5SJens Wiklander * not use this file except in compliance with the License. 11b8c186b5SJens Wiklander * You may obtain a copy of the License at 12b8c186b5SJens Wiklander * 13b8c186b5SJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 14b8c186b5SJens Wiklander * 15b8c186b5SJens Wiklander * Unless required by applicable law or agreed to in writing, software 16b8c186b5SJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17b8c186b5SJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18b8c186b5SJens Wiklander * See the License for the specific language governing permissions and 19b8c186b5SJens Wiklander * limitations under the License. 20b8c186b5SJens Wiklander */ 21b8c186b5SJens Wiklander 22*b314df1fSJens Wiklander #include <crypto/internal_aes-gcm.h> 23b8c186b5SJens Wiklander #include <io.h> 24b8c186b5SJens Wiklander #include <kernel/panic.h> 25b8c186b5SJens Wiklander #include <string.h> 26b8c186b5SJens Wiklander #include <tee_api_types.h> 27b8c186b5SJens Wiklander #include <types_ext.h> 28b8c186b5SJens Wiklander 29b8c186b5SJens Wiklander /* 30b8c186b5SJens Wiklander * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf 31b8c186b5SJens Wiklander * 32b8c186b5SJens Wiklander * See also: 33b8c186b5SJens Wiklander * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/ 34b8c186b5SJens Wiklander gcm-revised-spec.pdf 35b8c186b5SJens Wiklander * 36b8c186b5SJens Wiklander * We use the algorithm described as Shoup's method with 4-bit tables in 37b8c186b5SJens Wiklander * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. 38b8c186b5SJens Wiklander */ 39b8c186b5SJens Wiklander 40b8c186b5SJens Wiklander /* 41b8c186b5SJens Wiklander * Precompute small multiples of H, that is set 42b8c186b5SJens Wiklander * HH[i] || HL[i] = H times i, 43b8c186b5SJens Wiklander * where i is seen as a field element as in [MGV], ie high-order bits 44b8c186b5SJens Wiklander * correspond to low powers of P. The result is stored in the same way, that 45b8c186b5SJens Wiklander * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL 46b8c186b5SJens Wiklander * corresponds to P^127. 47b8c186b5SJens Wiklander */ 48*b314df1fSJens Wiklander void internal_aes_gcm_ghash_gen_tbl(struct internal_ghash_key *ghash_key, 4954af8d67SJens Wiklander const struct internal_aes_gcm_key *ek) 50b8c186b5SJens Wiklander { 51b8c186b5SJens Wiklander int i, j; 52b8c186b5SJens Wiklander uint64_t vl, vh; 53b8c186b5SJens Wiklander unsigned char h[16]; 54b8c186b5SJens Wiklander 55b8c186b5SJens Wiklander memset(h, 0, 16); 5654af8d67SJens Wiklander internal_aes_gcm_encrypt_block(ek, h, h); 57b8c186b5SJens Wiklander 58b8c186b5SJens Wiklander vh = get_be64(h); 59b8c186b5SJens Wiklander vl = get_be64(h + 8); 60b8c186b5SJens Wiklander 61b8c186b5SJens Wiklander /* 8 = 1000 corresponds to 1 in GF(2^128) */ 62*b314df1fSJens Wiklander ghash_key->HL[8] = vl; 63*b314df1fSJens Wiklander ghash_key->HH[8] = vh; 64b8c186b5SJens Wiklander 65b8c186b5SJens Wiklander /* 0 corresponds to 0 in GF(2^128) */ 66*b314df1fSJens Wiklander ghash_key->HH[0] = 0; 67*b314df1fSJens Wiklander ghash_key->HL[0] = 0; 68b8c186b5SJens Wiklander 69b8c186b5SJens Wiklander for (i = 4; i > 0; i >>= 1) { 70b8c186b5SJens Wiklander uint32_t T = (vl & 1) * 0xe1000000U; 71b8c186b5SJens Wiklander 72b8c186b5SJens Wiklander vl = (vh << 63) | (vl >> 1); 73b8c186b5SJens Wiklander vh = (vh >> 1) ^ ((uint64_t)T << 32); 74b8c186b5SJens Wiklander 75*b314df1fSJens Wiklander ghash_key->HL[i] = vl; 76*b314df1fSJens Wiklander ghash_key->HH[i] = vh; 77b8c186b5SJens Wiklander } 78b8c186b5SJens Wiklander 79b8c186b5SJens Wiklander for (i = 2; i <= 8; i *= 2) { 80*b314df1fSJens Wiklander uint64_t *HiL = ghash_key->HL + i; 81*b314df1fSJens Wiklander uint64_t *HiH = ghash_key->HH + i; 82b8c186b5SJens Wiklander 83b8c186b5SJens Wiklander vh = *HiH; 84b8c186b5SJens Wiklander vl = *HiL; 85b8c186b5SJens Wiklander for (j = 1; j < i; j++) { 86*b314df1fSJens Wiklander HiH[j] = vh ^ ghash_key->HH[j]; 87*b314df1fSJens Wiklander HiL[j] = vl ^ ghash_key->HL[j]; 88b8c186b5SJens Wiklander } 89b8c186b5SJens Wiklander } 90b8c186b5SJens Wiklander } 91b8c186b5SJens Wiklander 92b8c186b5SJens Wiklander /* 93b8c186b5SJens Wiklander * Shoup's method for multiplication use this table with 94b8c186b5SJens Wiklander * last4[x] = x times P^128 95b8c186b5SJens Wiklander * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] 96b8c186b5SJens Wiklander */ 97b8c186b5SJens Wiklander static const uint64_t last4[16] = { 98b8c186b5SJens Wiklander 0x0000, 0x1c20, 0x3840, 0x2460, 99b8c186b5SJens Wiklander 0x7080, 0x6ca0, 0x48c0, 0x54e0, 100b8c186b5SJens Wiklander 0xe100, 0xfd20, 0xd940, 0xc560, 101b8c186b5SJens Wiklander 0x9180, 0x8da0, 0xa9c0, 0xb5e0 102b8c186b5SJens Wiklander }; 103b8c186b5SJens Wiklander 104b8c186b5SJens Wiklander /* 105b8c186b5SJens Wiklander * Sets output to x times H using the precomputed tables. 106b8c186b5SJens Wiklander * x and output are seen as elements of GF(2^128) as in [MGV]. 107b8c186b5SJens Wiklander */ 108*b314df1fSJens Wiklander void internal_aes_gcm_ghash_mult_tbl(struct internal_ghash_key *ghash_key, 109*b314df1fSJens Wiklander const unsigned char x[16], 110*b314df1fSJens Wiklander unsigned char output[16]) 111b8c186b5SJens Wiklander { 112b8c186b5SJens Wiklander int i = 0; 113*b314df1fSJens Wiklander unsigned char lo = 0, hi = 0, rem = 0; 114*b314df1fSJens Wiklander uint64_t zh = 0, zl = 0; 115b8c186b5SJens Wiklander 116b8c186b5SJens Wiklander lo = x[15] & 0xf; 117b8c186b5SJens Wiklander 118*b314df1fSJens Wiklander zh = ghash_key->HH[lo]; 119*b314df1fSJens Wiklander zl = ghash_key->HL[lo]; 120b8c186b5SJens Wiklander 121b8c186b5SJens Wiklander for (i = 15; i >= 0; i--) { 122b8c186b5SJens Wiklander lo = x[i] & 0xf; 123b8c186b5SJens Wiklander hi = x[i] >> 4; 124b8c186b5SJens Wiklander 125b8c186b5SJens Wiklander if (i != 15) { 126b8c186b5SJens Wiklander rem = (unsigned char)zl & 0xf; 127b8c186b5SJens Wiklander zl = (zh << 60) | (zl >> 4); 128b8c186b5SJens Wiklander zh = (zh >> 4); 129b8c186b5SJens Wiklander zh ^= (uint64_t)last4[rem] << 48; 130*b314df1fSJens Wiklander zh ^= ghash_key->HH[lo]; 131*b314df1fSJens Wiklander zl ^= ghash_key->HL[lo]; 132b8c186b5SJens Wiklander } 133b8c186b5SJens Wiklander 134b8c186b5SJens Wiklander rem = (unsigned char)zl & 0xf; 135b8c186b5SJens Wiklander zl = (zh << 60) | (zl >> 4); 136b8c186b5SJens Wiklander zh = (zh >> 4); 137b8c186b5SJens Wiklander zh ^= (uint64_t)last4[rem] << 48; 138*b314df1fSJens Wiklander zh ^= ghash_key->HH[hi]; 139*b314df1fSJens Wiklander zl ^= ghash_key->HL[hi]; 140b8c186b5SJens Wiklander } 141b8c186b5SJens Wiklander 142b8c186b5SJens Wiklander put_be64(output, zh); 143b8c186b5SJens Wiklander put_be64(output + 8, zl); 144b8c186b5SJens Wiklander } 145