xref: /optee_os/core/crypto/aes-gcm-ghash-tbl.c (revision b8c186b57350152c3e67500d540920ca40309d5b)
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