xref: /optee_os/core/crypto/aes-gcm-ghash-tbl.c (revision 4f6d71606482a7cc346546de5b6be277985650f6)
1fb7ef469SJerome Forissier // SPDX-License-Identifier: Apache-2.0
2b8c186b5SJens Wiklander /*
3b314df1fSJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
4b314df1fSJens 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*4f6d7160SJens Wiklander #include <crypto/crypto.h>
23b314df1fSJens Wiklander #include <crypto/internal_aes-gcm.h>
24b8c186b5SJens Wiklander #include <io.h>
25b8c186b5SJens Wiklander #include <kernel/panic.h>
26b8c186b5SJens Wiklander #include <string.h>
27b8c186b5SJens Wiklander #include <tee_api_types.h>
28b8c186b5SJens Wiklander #include <types_ext.h>
29b8c186b5SJens Wiklander 
30b8c186b5SJens Wiklander /*
31b8c186b5SJens Wiklander  * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
32b8c186b5SJens Wiklander  *
33b8c186b5SJens Wiklander  * See also:
34b8c186b5SJens Wiklander  * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/
35b8c186b5SJens Wiklander gcm-revised-spec.pdf
36b8c186b5SJens Wiklander  *
37b8c186b5SJens Wiklander  * We use the algorithm described as Shoup's method with 4-bit tables in
38b8c186b5SJens Wiklander  * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
39b8c186b5SJens Wiklander  */
40b8c186b5SJens Wiklander 
41b8c186b5SJens Wiklander /*
42b8c186b5SJens Wiklander  * Precompute small multiples of H, that is set
43b8c186b5SJens Wiklander  *      HH[i] || HL[i] = H times i,
44b8c186b5SJens Wiklander  * where i is seen as a field element as in [MGV], ie high-order bits
45b8c186b5SJens Wiklander  * correspond to low powers of P. The result is stored in the same way, that
46b8c186b5SJens Wiklander  * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
47b8c186b5SJens Wiklander  * corresponds to P^127.
48b8c186b5SJens Wiklander  */
49b314df1fSJens Wiklander void internal_aes_gcm_ghash_gen_tbl(struct internal_ghash_key *ghash_key,
5054af8d67SJens Wiklander 				    const struct internal_aes_gcm_key *ek)
51b8c186b5SJens Wiklander {
52b8c186b5SJens Wiklander 	int i, j;
53b8c186b5SJens Wiklander 	uint64_t vl, vh;
54b8c186b5SJens Wiklander 	unsigned char h[16];
55b8c186b5SJens Wiklander 
56b8c186b5SJens Wiklander 	memset(h, 0, 16);
57*4f6d7160SJens Wiklander 	crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, h, h);
58b8c186b5SJens Wiklander 
59b8c186b5SJens Wiklander 	vh = get_be64(h);
60b8c186b5SJens Wiklander 	vl = get_be64(h + 8);
61b8c186b5SJens Wiklander 
62b8c186b5SJens Wiklander 	/* 8 = 1000 corresponds to 1 in GF(2^128) */
63b314df1fSJens Wiklander 	ghash_key->HL[8] = vl;
64b314df1fSJens Wiklander 	ghash_key->HH[8] = vh;
65b8c186b5SJens Wiklander 
66b8c186b5SJens Wiklander 	/* 0 corresponds to 0 in GF(2^128) */
67b314df1fSJens Wiklander 	ghash_key->HH[0] = 0;
68b314df1fSJens Wiklander 	ghash_key->HL[0] = 0;
69b8c186b5SJens Wiklander 
70b8c186b5SJens Wiklander 	for (i = 4; i > 0; i >>= 1) {
71b8c186b5SJens Wiklander 		uint32_t T = (vl & 1) * 0xe1000000U;
72b8c186b5SJens Wiklander 
73b8c186b5SJens Wiklander 		vl  = (vh << 63) | (vl >> 1);
74b8c186b5SJens Wiklander 		vh  = (vh >> 1) ^ ((uint64_t)T << 32);
75b8c186b5SJens Wiklander 
76b314df1fSJens Wiklander 		ghash_key->HL[i] = vl;
77b314df1fSJens Wiklander 		ghash_key->HH[i] = vh;
78b8c186b5SJens Wiklander 	}
79b8c186b5SJens Wiklander 
80b8c186b5SJens Wiklander 	for (i = 2; i <= 8; i *= 2) {
81b314df1fSJens Wiklander 		uint64_t *HiL = ghash_key->HL + i;
82b314df1fSJens Wiklander 		uint64_t *HiH = ghash_key->HH + i;
83b8c186b5SJens Wiklander 
84b8c186b5SJens Wiklander 		vh = *HiH;
85b8c186b5SJens Wiklander 		vl = *HiL;
86b8c186b5SJens Wiklander 		for (j = 1; j < i; j++) {
87b314df1fSJens Wiklander 			HiH[j] = vh ^ ghash_key->HH[j];
88b314df1fSJens Wiklander 			HiL[j] = vl ^ ghash_key->HL[j];
89b8c186b5SJens Wiklander 		}
90b8c186b5SJens Wiklander 	}
91b8c186b5SJens Wiklander }
92b8c186b5SJens Wiklander 
93b8c186b5SJens Wiklander /*
94b8c186b5SJens Wiklander  * Shoup's method for multiplication use this table with
95b8c186b5SJens Wiklander  *      last4[x] = x times P^128
96b8c186b5SJens Wiklander  * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
97b8c186b5SJens Wiklander  */
98b8c186b5SJens Wiklander static const uint64_t last4[16] = {
99b8c186b5SJens Wiklander 	0x0000, 0x1c20, 0x3840, 0x2460,
100b8c186b5SJens Wiklander 	0x7080, 0x6ca0, 0x48c0, 0x54e0,
101b8c186b5SJens Wiklander 	0xe100, 0xfd20, 0xd940, 0xc560,
102b8c186b5SJens Wiklander 	0x9180, 0x8da0, 0xa9c0, 0xb5e0
103b8c186b5SJens Wiklander };
104b8c186b5SJens Wiklander 
105b8c186b5SJens Wiklander /*
106b8c186b5SJens Wiklander  * Sets output to x times H using the precomputed tables.
107b8c186b5SJens Wiklander  * x and output are seen as elements of GF(2^128) as in [MGV].
108b8c186b5SJens Wiklander  */
109b314df1fSJens Wiklander void internal_aes_gcm_ghash_mult_tbl(struct internal_ghash_key *ghash_key,
110b314df1fSJens Wiklander 				     const unsigned char x[16],
111b314df1fSJens Wiklander 				     unsigned char output[16])
112b8c186b5SJens Wiklander {
113b8c186b5SJens Wiklander 	int i = 0;
114b314df1fSJens Wiklander 	unsigned char lo = 0, hi = 0, rem = 0;
115b314df1fSJens Wiklander 	uint64_t zh = 0, zl = 0;
116b8c186b5SJens Wiklander 
117b8c186b5SJens Wiklander 	lo = x[15] & 0xf;
118b8c186b5SJens Wiklander 
119b314df1fSJens Wiklander 	zh = ghash_key->HH[lo];
120b314df1fSJens Wiklander 	zl = ghash_key->HL[lo];
121b8c186b5SJens Wiklander 
122b8c186b5SJens Wiklander 	for (i = 15; i >= 0; i--) {
123b8c186b5SJens Wiklander 		lo = x[i] & 0xf;
124b8c186b5SJens Wiklander 		hi = x[i] >> 4;
125b8c186b5SJens Wiklander 
126b8c186b5SJens Wiklander 		if (i != 15) {
127b8c186b5SJens Wiklander 			rem = (unsigned char)zl & 0xf;
128b8c186b5SJens Wiklander 			zl = (zh << 60) | (zl >> 4);
129b8c186b5SJens Wiklander 			zh = (zh >> 4);
130b8c186b5SJens Wiklander 			zh ^= (uint64_t)last4[rem] << 48;
131b314df1fSJens Wiklander 			zh ^= ghash_key->HH[lo];
132b314df1fSJens Wiklander 			zl ^= ghash_key->HL[lo];
133b8c186b5SJens Wiklander 		}
134b8c186b5SJens Wiklander 
135b8c186b5SJens Wiklander 		rem = (unsigned char)zl & 0xf;
136b8c186b5SJens Wiklander 		zl = (zh << 60) | (zl >> 4);
137b8c186b5SJens Wiklander 		zh = (zh >> 4);
138b8c186b5SJens Wiklander 		zh ^= (uint64_t)last4[rem] << 48;
139b314df1fSJens Wiklander 		zh ^= ghash_key->HH[hi];
140b314df1fSJens Wiklander 		zl ^= ghash_key->HL[hi];
141b8c186b5SJens Wiklander 	}
142b8c186b5SJens Wiklander 
143b8c186b5SJens Wiklander 	put_be64(output, zh);
144b8c186b5SJens Wiklander 	put_be64(output + 8, zl);
145b8c186b5SJens Wiklander }
146