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