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