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