xref: /optee_os/core/crypto/aes-gcm.c (revision 8f848cdb03b809e96ccec8ecce1231f265ad7c02)
1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
21fca7e26SJens Wiklander /*
3b314df1fSJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
41fca7e26SJens Wiklander  */
51fca7e26SJens Wiklander 
661b4cd9cSJens Wiklander #include <assert.h>
74f6d7160SJens Wiklander #include <crypto/crypto.h>
8f1e9b21bSJens Wiklander #include <crypto/crypto_impl.h>
94f6d7160SJens Wiklander #include <crypto/internal_aes-gcm.h>
101fca7e26SJens Wiklander #include <io.h>
111fca7e26SJens Wiklander #include <string_ext.h>
121fca7e26SJens Wiklander #include <string.h>
131fca7e26SJens Wiklander #include <tee_api_types.h>
141fca7e26SJens Wiklander #include <types_ext.h>
151fca7e26SJens Wiklander #include <utee_defines.h>
161fca7e26SJens Wiklander #include <util.h>
171fca7e26SJens Wiklander 
181fca7e26SJens Wiklander static void xor_buf(uint8_t *dst, const uint8_t *src, size_t len)
191fca7e26SJens Wiklander {
201fca7e26SJens Wiklander 	size_t n;
211fca7e26SJens Wiklander 
221fca7e26SJens Wiklander 	for (n = 0; n < len; n++)
231fca7e26SJens Wiklander 		dst[n] ^= src[n];
241fca7e26SJens Wiklander }
251fca7e26SJens Wiklander 
261fca7e26SJens Wiklander 
2754af8d67SJens Wiklander static void ghash_update_pad_zero(struct internal_aes_gcm_state *state,
281fca7e26SJens Wiklander 				  const uint8_t *data, size_t len)
291fca7e26SJens Wiklander {
301fca7e26SJens Wiklander 	size_t n = len / TEE_AES_BLOCK_SIZE;
311fca7e26SJens Wiklander 	uint64_t block[2];
321fca7e26SJens Wiklander 
331fca7e26SJens Wiklander 	if (n) {
34b8c186b5SJens Wiklander 		if (internal_aes_gcm_ptr_is_block_aligned(data)) {
3554af8d67SJens Wiklander 			internal_aes_gcm_ghash_update(state, NULL, data, n);
361fca7e26SJens Wiklander 		} else {
371fca7e26SJens Wiklander 			size_t m;
381fca7e26SJens Wiklander 
391fca7e26SJens Wiklander 			for (m = 0; m < n; m++) {
401fca7e26SJens Wiklander 
411fca7e26SJens Wiklander 				memcpy(block, data + m * sizeof(block),
421fca7e26SJens Wiklander 				       sizeof(block));
4354af8d67SJens Wiklander 				internal_aes_gcm_ghash_update(state, NULL,
441fca7e26SJens Wiklander 							      (void *)block, 1);
451fca7e26SJens Wiklander 			}
461fca7e26SJens Wiklander 		}
471fca7e26SJens Wiklander 	}
481fca7e26SJens Wiklander 
491fca7e26SJens Wiklander 	if (len - n * TEE_AES_BLOCK_SIZE) {
501fca7e26SJens Wiklander 		memset(block, 0, sizeof(block));
511fca7e26SJens Wiklander 		memcpy(block, data + n * TEE_AES_BLOCK_SIZE,
521fca7e26SJens Wiklander 		       len - n * TEE_AES_BLOCK_SIZE);
5354af8d67SJens Wiklander 		internal_aes_gcm_ghash_update(state, block, NULL, 0);
541fca7e26SJens Wiklander 	}
551fca7e26SJens Wiklander }
561fca7e26SJens Wiklander 
5754af8d67SJens Wiklander static void ghash_update_lengths(struct internal_aes_gcm_state *state,
5854af8d67SJens Wiklander 				 uint32_t l1, uint32_t l2)
591fca7e26SJens Wiklander {
601fca7e26SJens Wiklander 	uint64_t len_fields[2] = {
611fca7e26SJens Wiklander 		TEE_U64_TO_BIG_ENDIAN(l1 * 8),
621fca7e26SJens Wiklander 		TEE_U64_TO_BIG_ENDIAN(l2 * 8)
631fca7e26SJens Wiklander 	};
641fca7e26SJens Wiklander 
651fca7e26SJens Wiklander 	COMPILE_TIME_ASSERT(sizeof(len_fields) == TEE_AES_BLOCK_SIZE);
6654af8d67SJens Wiklander 	internal_aes_gcm_ghash_update(state, (uint8_t *)len_fields, NULL, 0);
671fca7e26SJens Wiklander }
681fca7e26SJens Wiklander 
6954af8d67SJens Wiklander static TEE_Result __gcm_init(struct internal_aes_gcm_state *state,
7054af8d67SJens Wiklander 			     const struct internal_aes_gcm_key *ek,
7154af8d67SJens Wiklander 			     TEE_OperationMode mode, const void *nonce,
721fca7e26SJens Wiklander 			     size_t nonce_len, size_t tag_len)
731fca7e26SJens Wiklander {
7454af8d67SJens Wiklander 	COMPILE_TIME_ASSERT(sizeof(state->ctr) == TEE_AES_BLOCK_SIZE);
751fca7e26SJens Wiklander 
7654af8d67SJens Wiklander 	if (tag_len > sizeof(state->buf_tag))
771fca7e26SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
781fca7e26SJens Wiklander 
7954af8d67SJens Wiklander 	memset(state, 0, sizeof(*state));
801fca7e26SJens Wiklander 
8154af8d67SJens Wiklander 	state->tag_len = tag_len;
8254af8d67SJens Wiklander 	internal_aes_gcm_set_key(state, ek);
831fca7e26SJens Wiklander 
841fca7e26SJens Wiklander 	if (nonce_len == (96 / 8)) {
8554af8d67SJens Wiklander 		memcpy(state->ctr, nonce, nonce_len);
8654af8d67SJens Wiklander 		internal_aes_gcm_inc_ctr(state);
871fca7e26SJens Wiklander 	} else {
8854af8d67SJens Wiklander 		ghash_update_pad_zero(state, nonce, nonce_len);
8954af8d67SJens Wiklander 		ghash_update_lengths(state, 0, nonce_len);
901fca7e26SJens Wiklander 
9154af8d67SJens Wiklander 		memcpy(state->ctr, state->hash_state, sizeof(state->ctr));
9254af8d67SJens Wiklander 		memset(state->hash_state, 0, sizeof(state->hash_state));
931fca7e26SJens Wiklander 	}
941fca7e26SJens Wiklander 
954f6d7160SJens Wiklander 	crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds,
964f6d7160SJens Wiklander 			     state->ctr, state->buf_tag);
9754af8d67SJens Wiklander 	internal_aes_gcm_inc_ctr(state);
981fca7e26SJens Wiklander 	if (mode == TEE_MODE_ENCRYPT) {
991fca7e26SJens Wiklander 		/*
1001fca7e26SJens Wiklander 		 * Encryption uses the pre-encrypted xor-buffer to encrypt
1011fca7e26SJens Wiklander 		 * while decryption encrypts the xor-buffer when needed
1021fca7e26SJens Wiklander 		 * instead.
1031fca7e26SJens Wiklander 		 *
1041fca7e26SJens Wiklander 		 * The reason for this is that the combined encryption and
1051fca7e26SJens Wiklander 		 * ghash implementation does both operations intertwined.
1061fca7e26SJens Wiklander 		 * In the decrypt case the xor-buffer is needed at the end
1071fca7e26SJens Wiklander 		 * of processing each block, while the encryption case
1081fca7e26SJens Wiklander 		 * needs xor-buffer before processing each block.
1091fca7e26SJens Wiklander 		 *
1101fca7e26SJens Wiklander 		 * In a pure software implementation we wouldn't have any
1111fca7e26SJens Wiklander 		 * use for this kind of optimization, but since this
1121fca7e26SJens Wiklander 		 * AES-GCM implementation is aimed at being combined with
1131fca7e26SJens Wiklander 		 * accelerated routines it's more convenient to always have
1141fca7e26SJens Wiklander 		 * this optimization activated.
1151fca7e26SJens Wiklander 		 */
1164f6d7160SJens Wiklander 		crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds,
1174f6d7160SJens Wiklander 				     state->ctr, state->buf_cryp);
11854af8d67SJens Wiklander 		internal_aes_gcm_inc_ctr(state);
1191fca7e26SJens Wiklander 	}
1201fca7e26SJens Wiklander 
1211fca7e26SJens Wiklander 	return TEE_SUCCESS;
1221fca7e26SJens Wiklander }
1231fca7e26SJens Wiklander 
12454af8d67SJens Wiklander TEE_Result internal_aes_gcm_init(struct internal_aes_gcm_ctx *ctx,
12554af8d67SJens Wiklander 				 TEE_OperationMode mode, const void *key,
12654af8d67SJens Wiklander 				 size_t key_len, const void *nonce,
12754af8d67SJens Wiklander 				 size_t nonce_len, size_t tag_len)
12854af8d67SJens Wiklander {
12954af8d67SJens Wiklander 	TEE_Result res = internal_aes_gcm_expand_enc_key(key, key_len,
13054af8d67SJens Wiklander 							 &ctx->key);
13154af8d67SJens Wiklander 	if (res)
13254af8d67SJens Wiklander 		return res;
13354af8d67SJens Wiklander 
13454af8d67SJens Wiklander 	return __gcm_init(&ctx->state, &ctx->key, mode, nonce, nonce_len,
13554af8d67SJens Wiklander 			  tag_len);
13654af8d67SJens Wiklander }
13754af8d67SJens Wiklander 
138043411e5SJens Wiklander static TEE_Result __gcm_update_aad(struct internal_aes_gcm_state *state,
1391fca7e26SJens Wiklander 				   const void *data, size_t len)
1401fca7e26SJens Wiklander {
1411fca7e26SJens Wiklander 	const uint8_t *d = data;
1421fca7e26SJens Wiklander 	size_t l = len;
1431fca7e26SJens Wiklander 	const uint8_t *head = NULL;
1441fca7e26SJens Wiklander 	size_t n;
1451fca7e26SJens Wiklander 
14654af8d67SJens Wiklander 	if (state->payload_bytes)
1471fca7e26SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
1481fca7e26SJens Wiklander 
14954af8d67SJens Wiklander 	state->aad_bytes += len;
1501fca7e26SJens Wiklander 
1511fca7e26SJens Wiklander 	while (l) {
15254af8d67SJens Wiklander 		if (state->buf_pos ||
15354af8d67SJens Wiklander 		    !internal_aes_gcm_ptr_is_block_aligned(d) ||
1541fca7e26SJens Wiklander 		    l < TEE_AES_BLOCK_SIZE) {
15554af8d67SJens Wiklander 			n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l);
15654af8d67SJens Wiklander 			memcpy(state->buf_hash + state->buf_pos, d, n);
15754af8d67SJens Wiklander 			state->buf_pos += n;
1581fca7e26SJens Wiklander 
15954af8d67SJens Wiklander 			if (state->buf_pos != TEE_AES_BLOCK_SIZE)
1601fca7e26SJens Wiklander 				return TEE_SUCCESS;
1611fca7e26SJens Wiklander 
16254af8d67SJens Wiklander 			state->buf_pos = 0;
16354af8d67SJens Wiklander 			head = state->buf_hash;
1641fca7e26SJens Wiklander 			d += n;
1651fca7e26SJens Wiklander 			l -= n;
1661fca7e26SJens Wiklander 		}
1671fca7e26SJens Wiklander 
168b8c186b5SJens Wiklander 		if (internal_aes_gcm_ptr_is_block_aligned(d))
1691fca7e26SJens Wiklander 			n = l / TEE_AES_BLOCK_SIZE;
1701fca7e26SJens Wiklander 		else
1711fca7e26SJens Wiklander 			n = 0;
1721fca7e26SJens Wiklander 
17354af8d67SJens Wiklander 		internal_aes_gcm_ghash_update(state, head, d, n);
1741fca7e26SJens Wiklander 		l -= n * TEE_AES_BLOCK_SIZE;
1751fca7e26SJens Wiklander 		d += n * TEE_AES_BLOCK_SIZE;
1761fca7e26SJens Wiklander 	}
1771fca7e26SJens Wiklander 
1781fca7e26SJens Wiklander 	return TEE_SUCCESS;
1791fca7e26SJens Wiklander }
1801fca7e26SJens Wiklander 
181043411e5SJens Wiklander TEE_Result internal_aes_gcm_update_aad(struct internal_aes_gcm_ctx *ctx,
182043411e5SJens Wiklander 				       const void *data, size_t len)
1831fca7e26SJens Wiklander {
184043411e5SJens Wiklander 	return __gcm_update_aad(&ctx->state, data, len);
185043411e5SJens Wiklander }
186043411e5SJens Wiklander 
187043411e5SJens Wiklander static TEE_Result
188043411e5SJens Wiklander __gcm_update_payload(struct internal_aes_gcm_state *state,
189043411e5SJens Wiklander 		     const struct internal_aes_gcm_key *ek,
190043411e5SJens Wiklander 		     TEE_OperationMode mode, const void *src,
191043411e5SJens Wiklander 		     size_t len, void *dst)
192043411e5SJens Wiklander {
1931fca7e26SJens Wiklander 	size_t n;
1941fca7e26SJens Wiklander 	const uint8_t *s = src;
1951fca7e26SJens Wiklander 	uint8_t *d = dst;
1961fca7e26SJens Wiklander 	size_t l = len;
1971fca7e26SJens Wiklander 
19854af8d67SJens Wiklander 	if (!state->payload_bytes && state->buf_pos) {
1991fca7e26SJens Wiklander 		/* AAD part done, finish up the last bits. */
20054af8d67SJens Wiklander 		memset(state->buf_hash + state->buf_pos, 0,
20154af8d67SJens Wiklander 		       TEE_AES_BLOCK_SIZE - state->buf_pos);
20254af8d67SJens Wiklander 		internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0);
20354af8d67SJens Wiklander 		state->buf_pos = 0;
2041fca7e26SJens Wiklander 	}
2051fca7e26SJens Wiklander 
20654af8d67SJens Wiklander 	state->payload_bytes += len;
2071fca7e26SJens Wiklander 
2081fca7e26SJens Wiklander 	while (l) {
209d7fd8f87SJens Wiklander 		if (state->buf_pos || l < TEE_AES_BLOCK_SIZE) {
21054af8d67SJens Wiklander 			n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l);
2111fca7e26SJens Wiklander 
2124f6d7160SJens Wiklander 			if (!state->buf_pos && mode == TEE_MODE_DECRYPT)
2134f6d7160SJens Wiklander 				crypto_aes_enc_block(ek->data, sizeof(ek->data),
2144f6d7160SJens Wiklander 						     ek->rounds, state->ctr,
21554af8d67SJens Wiklander 						     state->buf_cryp);
2161fca7e26SJens Wiklander 
21754af8d67SJens Wiklander 			xor_buf(state->buf_cryp + state->buf_pos, s, n);
21854af8d67SJens Wiklander 			memcpy(d, state->buf_cryp + state->buf_pos, n);
2191fca7e26SJens Wiklander 			if (mode == TEE_MODE_ENCRYPT)
22054af8d67SJens Wiklander 				memcpy(state->buf_hash + state->buf_pos,
22154af8d67SJens Wiklander 				       state->buf_cryp + state->buf_pos, n);
2221fca7e26SJens Wiklander 			else
22354af8d67SJens Wiklander 				memcpy(state->buf_hash + state->buf_pos, s, n);
2241fca7e26SJens Wiklander 
22554af8d67SJens Wiklander 			state->buf_pos += n;
2261fca7e26SJens Wiklander 
22754af8d67SJens Wiklander 			if (state->buf_pos != TEE_AES_BLOCK_SIZE)
2281fca7e26SJens Wiklander 				return TEE_SUCCESS;
2291fca7e26SJens Wiklander 
23054af8d67SJens Wiklander 			internal_aes_gcm_ghash_update(state, state->buf_hash,
2311fca7e26SJens Wiklander 						      NULL, 0);
23254af8d67SJens Wiklander 			state->buf_pos = 0;
2331fca7e26SJens Wiklander 			d += n;
2341fca7e26SJens Wiklander 			s += n;
2351fca7e26SJens Wiklander 			l -= n;
2361fca7e26SJens Wiklander 
2371fca7e26SJens Wiklander 			if (mode == TEE_MODE_ENCRYPT)
2384f6d7160SJens Wiklander 				crypto_aes_enc_block(ek->data, sizeof(ek->data),
2394f6d7160SJens Wiklander 						     ek->rounds, state->ctr,
24054af8d67SJens Wiklander 						     state->buf_cryp);
24154af8d67SJens Wiklander 			internal_aes_gcm_inc_ctr(state);
2421fca7e26SJens Wiklander 		} else {
2431fca7e26SJens Wiklander 			n = l / TEE_AES_BLOCK_SIZE;
244d7fd8f87SJens Wiklander 			internal_aes_gcm_update_payload_blocks(state, ek, mode,
2451fca7e26SJens Wiklander 							       s, n, d);
2461fca7e26SJens Wiklander 			s += n * TEE_AES_BLOCK_SIZE;
2471fca7e26SJens Wiklander 			d += n * TEE_AES_BLOCK_SIZE;
2481fca7e26SJens Wiklander 			l -= n * TEE_AES_BLOCK_SIZE;
2491fca7e26SJens Wiklander 		}
2501fca7e26SJens Wiklander 	}
2511fca7e26SJens Wiklander 
2521fca7e26SJens Wiklander 	return TEE_SUCCESS;
2531fca7e26SJens Wiklander }
2541fca7e26SJens Wiklander 
255043411e5SJens Wiklander TEE_Result internal_aes_gcm_update_payload(struct internal_aes_gcm_ctx *ctx,
256043411e5SJens Wiklander 					   TEE_OperationMode mode,
257043411e5SJens Wiklander 					   const void *src, size_t len,
258043411e5SJens Wiklander 					   void *dst)
259043411e5SJens Wiklander {
260043411e5SJens Wiklander 	return __gcm_update_payload(&ctx->state, &ctx->key, mode, src, len,
261043411e5SJens Wiklander 				    dst);
262043411e5SJens Wiklander }
263043411e5SJens Wiklander 
264043411e5SJens Wiklander static TEE_Result operation_final(struct internal_aes_gcm_state *state,
265043411e5SJens Wiklander 				  const struct internal_aes_gcm_key *enc_key,
2661fca7e26SJens Wiklander 				  TEE_OperationMode m, const uint8_t *src,
2671fca7e26SJens Wiklander 				  size_t len, uint8_t *dst)
2681fca7e26SJens Wiklander {
2691fca7e26SJens Wiklander 	TEE_Result res;
2701fca7e26SJens Wiklander 
271043411e5SJens Wiklander 	res = __gcm_update_payload(state, enc_key, m, src, len, dst);
2721fca7e26SJens Wiklander 	if (res)
2731fca7e26SJens Wiklander 		return res;
2741fca7e26SJens Wiklander 
27554af8d67SJens Wiklander 	if (state->buf_pos) {
27654af8d67SJens Wiklander 		memset(state->buf_hash + state->buf_pos, 0,
27754af8d67SJens Wiklander 		       sizeof(state->buf_hash) - state->buf_pos);
27854af8d67SJens Wiklander 		internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0);
2791fca7e26SJens Wiklander 	}
2801fca7e26SJens Wiklander 
28154af8d67SJens Wiklander 	ghash_update_lengths(state, state->aad_bytes, state->payload_bytes);
2821fca7e26SJens Wiklander 	/* buf_tag was filled in with the first counter block aes_gcm_init() */
28354af8d67SJens Wiklander 	xor_buf(state->buf_tag, state->hash_state, state->tag_len);
2841fca7e26SJens Wiklander 
2851fca7e26SJens Wiklander 	return TEE_SUCCESS;
2861fca7e26SJens Wiklander }
2871fca7e26SJens Wiklander 
288043411e5SJens Wiklander static TEE_Result __gcm_enc_final(struct internal_aes_gcm_state *state,
289043411e5SJens Wiklander 				  const struct internal_aes_gcm_key *enc_key,
2901fca7e26SJens Wiklander 				  const void *src, size_t len, void *dst,
2911fca7e26SJens Wiklander 				  void *tag, size_t *tag_len)
2921fca7e26SJens Wiklander {
2931fca7e26SJens Wiklander 	TEE_Result res;
2941fca7e26SJens Wiklander 
29554af8d67SJens Wiklander 	if (*tag_len < state->tag_len)
2961fca7e26SJens Wiklander 		return TEE_ERROR_SHORT_BUFFER;
2971fca7e26SJens Wiklander 
298043411e5SJens Wiklander 	res = operation_final(state, enc_key, TEE_MODE_ENCRYPT, src, len, dst);
2991fca7e26SJens Wiklander 	if (res)
3001fca7e26SJens Wiklander 		return res;
3011fca7e26SJens Wiklander 
30254af8d67SJens Wiklander 	memcpy(tag, state->buf_tag, state->tag_len);
30354af8d67SJens Wiklander 	*tag_len = state->tag_len;
3041fca7e26SJens Wiklander 
3051fca7e26SJens Wiklander 	return TEE_SUCCESS;
3061fca7e26SJens Wiklander }
3071fca7e26SJens Wiklander 
308043411e5SJens Wiklander TEE_Result internal_aes_gcm_enc_final(struct internal_aes_gcm_ctx *ctx,
309043411e5SJens Wiklander 				      const void *src, size_t len, void *dst,
310043411e5SJens Wiklander 				      void *tag, size_t *tag_len)
311043411e5SJens Wiklander {
312043411e5SJens Wiklander 	return __gcm_enc_final(&ctx->state, &ctx->key, src, len, dst, tag,
313043411e5SJens Wiklander 			       tag_len);
314043411e5SJens Wiklander }
315043411e5SJens Wiklander 
316043411e5SJens Wiklander static TEE_Result __gcm_dec_final(struct internal_aes_gcm_state *state,
317043411e5SJens Wiklander 				  const struct internal_aes_gcm_key *enc_key,
3181fca7e26SJens Wiklander 				  const void *src, size_t len, void *dst,
3191fca7e26SJens Wiklander 				  const void *tag, size_t tag_len)
3201fca7e26SJens Wiklander {
3211fca7e26SJens Wiklander 	TEE_Result res;
3221fca7e26SJens Wiklander 
32354af8d67SJens Wiklander 	if (tag_len != state->tag_len)
3241fca7e26SJens Wiklander 		return TEE_ERROR_MAC_INVALID;
3251fca7e26SJens Wiklander 
326043411e5SJens Wiklander 	res = operation_final(state, enc_key, TEE_MODE_DECRYPT, src, len, dst);
3271fca7e26SJens Wiklander 	if (res)
3281fca7e26SJens Wiklander 		return res;
3291fca7e26SJens Wiklander 
33048e10604SJerome Forissier 	if (consttime_memcmp(state->buf_tag, tag, tag_len))
3311fca7e26SJens Wiklander 		return TEE_ERROR_MAC_INVALID;
3321fca7e26SJens Wiklander 
3331fca7e26SJens Wiklander 	return TEE_SUCCESS;
3341fca7e26SJens Wiklander }
3351fca7e26SJens Wiklander 
336043411e5SJens Wiklander TEE_Result internal_aes_gcm_dec_final(struct internal_aes_gcm_ctx *ctx,
337043411e5SJens Wiklander 				      const void *src, size_t len, void *dst,
338043411e5SJens Wiklander 				      const void *tag, size_t tag_len)
339043411e5SJens Wiklander {
340043411e5SJens Wiklander 	return __gcm_dec_final(&ctx->state, &ctx->key, src, len, dst, tag,
341043411e5SJens Wiklander 			       tag_len);
342043411e5SJens Wiklander }
343043411e5SJens Wiklander 
34454af8d67SJens Wiklander void internal_aes_gcm_inc_ctr(struct internal_aes_gcm_state *state)
3451fca7e26SJens Wiklander {
3461fca7e26SJens Wiklander 	uint64_t c;
3471fca7e26SJens Wiklander 
34854af8d67SJens Wiklander 	c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]) + 1;
34954af8d67SJens Wiklander 	state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c);
3501fca7e26SJens Wiklander 	if (!c) {
35154af8d67SJens Wiklander 		c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[0]) + 1;
35254af8d67SJens Wiklander 		state->ctr[0] = TEE_U64_TO_BIG_ENDIAN(c);
3531fca7e26SJens Wiklander 	}
3541fca7e26SJens Wiklander }
3551fca7e26SJens Wiklander 
356043411e5SJens Wiklander TEE_Result internal_aes_gcm_enc(const struct internal_aes_gcm_key *enc_key,
357043411e5SJens Wiklander 				const void *nonce, size_t nonce_len,
358043411e5SJens Wiklander 				const void *aad, size_t aad_len,
359043411e5SJens Wiklander 				const void *src, size_t len, void *dst,
360043411e5SJens Wiklander 				void *tag, size_t *tag_len)
361043411e5SJens Wiklander {
362043411e5SJens Wiklander 	TEE_Result res;
363043411e5SJens Wiklander 	struct internal_aes_gcm_state state;
364043411e5SJens Wiklander 
365043411e5SJens Wiklander 	res = __gcm_init(&state, enc_key, TEE_MODE_ENCRYPT, nonce, nonce_len,
366043411e5SJens Wiklander 			 *tag_len);
367043411e5SJens Wiklander 	if (res)
368043411e5SJens Wiklander 		return res;
369043411e5SJens Wiklander 
370043411e5SJens Wiklander 	if (aad) {
371043411e5SJens Wiklander 		res = __gcm_update_aad(&state, aad, aad_len);
372043411e5SJens Wiklander 		if (res)
373043411e5SJens Wiklander 			return res;
374043411e5SJens Wiklander 	}
375043411e5SJens Wiklander 
376043411e5SJens Wiklander 	return __gcm_enc_final(&state, enc_key, src, len, dst, tag, tag_len);
377043411e5SJens Wiklander }
378043411e5SJens Wiklander 
379043411e5SJens Wiklander TEE_Result internal_aes_gcm_dec(const struct internal_aes_gcm_key *enc_key,
380043411e5SJens Wiklander 				const void *nonce, size_t nonce_len,
381043411e5SJens Wiklander 				const void *aad, size_t aad_len,
382043411e5SJens Wiklander 				const void *src, size_t len, void *dst,
383043411e5SJens Wiklander 				const void *tag, size_t tag_len)
384043411e5SJens Wiklander {
385043411e5SJens Wiklander 	TEE_Result res;
386043411e5SJens Wiklander 	struct internal_aes_gcm_state state;
387043411e5SJens Wiklander 
388043411e5SJens Wiklander 	res = __gcm_init(&state, enc_key, TEE_MODE_DECRYPT, nonce, nonce_len,
389043411e5SJens Wiklander 			 tag_len);
390043411e5SJens Wiklander 	if (res)
391043411e5SJens Wiklander 		return res;
392043411e5SJens Wiklander 
393043411e5SJens Wiklander 	if (aad) {
394043411e5SJens Wiklander 		res = __gcm_update_aad(&state, aad, aad_len);
395043411e5SJens Wiklander 		if (res)
396043411e5SJens Wiklander 			return res;
397043411e5SJens Wiklander 	}
398043411e5SJens Wiklander 
399043411e5SJens Wiklander 	return __gcm_dec_final(&state, enc_key, src, len, dst, tag, tag_len);
400043411e5SJens Wiklander }
401043411e5SJens Wiklander 
402043411e5SJens Wiklander 
4031fca7e26SJens Wiklander #ifndef CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB
404d7ac7d0fSJens Wiklander #include <stdlib.h>
405f1e9b21bSJens Wiklander #include <crypto/crypto.h>
4061fca7e26SJens Wiklander 
407f1e9b21bSJens Wiklander struct aes_gcm_ctx {
408f1e9b21bSJens Wiklander 	struct crypto_authenc_ctx aec;
409f1e9b21bSJens Wiklander 	struct internal_aes_gcm_ctx ctx;
410f1e9b21bSJens Wiklander };
411f1e9b21bSJens Wiklander 
412f1e9b21bSJens Wiklander static const struct crypto_authenc_ops aes_gcm_ops;
413f1e9b21bSJens Wiklander 
414f1e9b21bSJens Wiklander static struct aes_gcm_ctx *
415f1e9b21bSJens Wiklander to_aes_gcm_ctx(struct crypto_authenc_ctx *aec)
4161fca7e26SJens Wiklander {
417f1e9b21bSJens Wiklander 	assert(aec->ops == &aes_gcm_ops);
418f1e9b21bSJens Wiklander 
419f1e9b21bSJens Wiklander 	return container_of(aec, struct aes_gcm_ctx, aec);
420f1e9b21bSJens Wiklander }
421f1e9b21bSJens Wiklander 
422f1e9b21bSJens Wiklander TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret)
423f1e9b21bSJens Wiklander {
424f1e9b21bSJens Wiklander 	struct aes_gcm_ctx *ctx = calloc(1, sizeof(*ctx));
425d7ac7d0fSJens Wiklander 
426d7ac7d0fSJens Wiklander 	if (!ctx)
427d7ac7d0fSJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
428f1e9b21bSJens Wiklander 	ctx->aec.ops = &aes_gcm_ops;
429d7ac7d0fSJens Wiklander 
430f1e9b21bSJens Wiklander 	*ctx_ret = &ctx->aec;
431f1e9b21bSJens Wiklander 
432d7ac7d0fSJens Wiklander 	return TEE_SUCCESS;
433d7ac7d0fSJens Wiklander }
434d7ac7d0fSJens Wiklander 
435f1e9b21bSJens Wiklander static void aes_gcm_free_ctx(struct crypto_authenc_ctx *aec)
436d7ac7d0fSJens Wiklander {
437f1e9b21bSJens Wiklander 	free(to_aes_gcm_ctx(aec));
438d7ac7d0fSJens Wiklander }
439d7ac7d0fSJens Wiklander 
440f1e9b21bSJens Wiklander static void aes_gcm_copy_state(struct crypto_authenc_ctx *dst_ctx,
441f1e9b21bSJens Wiklander 			       struct crypto_authenc_ctx *src_ctx)
442d7ac7d0fSJens Wiklander {
443f1e9b21bSJens Wiklander 	to_aes_gcm_ctx(dst_ctx)->ctx = to_aes_gcm_ctx(src_ctx)->ctx;
4441fca7e26SJens Wiklander }
4451fca7e26SJens Wiklander 
446f1e9b21bSJens Wiklander static TEE_Result aes_gcm_init(struct crypto_authenc_ctx *aec,
447f1e9b21bSJens Wiklander 			       TEE_OperationMode mode,
4481fca7e26SJens Wiklander 			       const uint8_t *key, size_t key_len,
4491fca7e26SJens Wiklander 			       const uint8_t *nonce, size_t nonce_len,
450f1e9b21bSJens Wiklander 			       size_t tag_len, size_t aad_len __unused,
451f1e9b21bSJens Wiklander 			       size_t payload_len __unused)
4521fca7e26SJens Wiklander {
453f1e9b21bSJens Wiklander 	return internal_aes_gcm_init(&to_aes_gcm_ctx(aec)->ctx, mode, key,
454f1e9b21bSJens Wiklander 				     key_len, nonce, nonce_len, tag_len);
4551fca7e26SJens Wiklander }
4561fca7e26SJens Wiklander 
457f1e9b21bSJens Wiklander static TEE_Result aes_gcm_update_aad(struct crypto_authenc_ctx *aec,
458f1e9b21bSJens Wiklander 				     const uint8_t *data, size_t len)
4591fca7e26SJens Wiklander {
460f1e9b21bSJens Wiklander 	return internal_aes_gcm_update_aad(&to_aes_gcm_ctx(aec)->ctx, data,
461f1e9b21bSJens Wiklander 					   len);
4621fca7e26SJens Wiklander }
4631fca7e26SJens Wiklander 
464f1e9b21bSJens Wiklander static TEE_Result aes_gcm_update_payload(struct crypto_authenc_ctx *aec,
465f1e9b21bSJens Wiklander 					 TEE_OperationMode m,
4661fca7e26SJens Wiklander 					 const uint8_t *src, size_t len,
4671fca7e26SJens Wiklander 					 uint8_t *dst)
4681fca7e26SJens Wiklander {
469f1e9b21bSJens Wiklander 	return internal_aes_gcm_update_payload(&to_aes_gcm_ctx(aec)->ctx,
470f1e9b21bSJens Wiklander 					       m, src, len, dst);
4711fca7e26SJens Wiklander }
4721fca7e26SJens Wiklander 
473f1e9b21bSJens Wiklander static TEE_Result aes_gcm_enc_final(struct crypto_authenc_ctx *aec,
474f1e9b21bSJens Wiklander 				    const uint8_t *src, size_t len,
4751fca7e26SJens Wiklander 				    uint8_t *dst, uint8_t *tag, size_t *tag_len)
4761fca7e26SJens Wiklander {
477f1e9b21bSJens Wiklander 	return internal_aes_gcm_enc_final(&to_aes_gcm_ctx(aec)->ctx, src, len,
478f1e9b21bSJens Wiklander 					  dst, tag, tag_len);
4791fca7e26SJens Wiklander }
4801fca7e26SJens Wiklander 
481f1e9b21bSJens Wiklander static TEE_Result aes_gcm_dec_final(struct crypto_authenc_ctx *aec,
482f1e9b21bSJens Wiklander 				    const uint8_t *src, size_t len,
4831fca7e26SJens Wiklander 				    uint8_t *dst, const uint8_t *tag,
4841fca7e26SJens Wiklander 				    size_t tag_len)
4851fca7e26SJens Wiklander {
486f1e9b21bSJens Wiklander 	return internal_aes_gcm_dec_final(&to_aes_gcm_ctx(aec)->ctx, src, len,
487f1e9b21bSJens Wiklander 					  dst, tag, tag_len);
4881fca7e26SJens Wiklander }
4891fca7e26SJens Wiklander 
490f1e9b21bSJens Wiklander static void aes_gcm_final(struct crypto_authenc_ctx *aec __unused)
4911fca7e26SJens Wiklander {
4921fca7e26SJens Wiklander }
493f1e9b21bSJens Wiklander 
494f1e9b21bSJens Wiklander static const struct crypto_authenc_ops aes_gcm_ops = {
495f1e9b21bSJens Wiklander 	.init = aes_gcm_init,
496f1e9b21bSJens Wiklander 	.update_aad = aes_gcm_update_aad,
497f1e9b21bSJens Wiklander 	.update_payload = aes_gcm_update_payload,
498f1e9b21bSJens Wiklander 	.enc_final = aes_gcm_enc_final,
499f1e9b21bSJens Wiklander 	.dec_final = aes_gcm_dec_final,
500f1e9b21bSJens Wiklander 	.final = aes_gcm_final,
501f1e9b21bSJens Wiklander 	.free_ctx = aes_gcm_free_ctx,
502f1e9b21bSJens Wiklander 	.copy_state = aes_gcm_copy_state,
503f1e9b21bSJens Wiklander };
504b314df1fSJens Wiklander 
505b314df1fSJens Wiklander /*
506b314df1fSJens Wiklander  * internal_aes_gcm_gfmul() is based on ghash_gfmul() from
507b314df1fSJens Wiklander  * https://github.com/openbsd/src/blob/master/sys/crypto/gmac.c
508b314df1fSJens Wiklander  */
509b314df1fSJens Wiklander void internal_aes_gcm_gfmul(const uint64_t X[2], const uint64_t Y[2],
510b314df1fSJens Wiklander 			    uint64_t product[2])
511b314df1fSJens Wiklander {
512b314df1fSJens Wiklander 	uint64_t y[2] = { 0 };
513b314df1fSJens Wiklander 	uint64_t z[2] = { 0 };
514b314df1fSJens Wiklander 	const uint8_t *x = (const uint8_t *)X;
515b314df1fSJens Wiklander 	uint32_t mul = 0;
516b314df1fSJens Wiklander 	size_t n = 0;
517b314df1fSJens Wiklander 
518b314df1fSJens Wiklander 	y[0] = TEE_U64_FROM_BIG_ENDIAN(Y[0]);
519b314df1fSJens Wiklander 	y[1] = TEE_U64_FROM_BIG_ENDIAN(Y[1]);
520b314df1fSJens Wiklander 
521b314df1fSJens Wiklander 	for (n = 0; n < TEE_AES_BLOCK_SIZE * 8; n++) {
522b314df1fSJens Wiklander 		/* update Z */
523b314df1fSJens Wiklander 		if (x[n >> 3] & (1 << (~n & 7)))
524b314df1fSJens Wiklander 			internal_aes_gcm_xor_block(z, y);
525b314df1fSJens Wiklander 
526b314df1fSJens Wiklander 		/* update Y */
527b314df1fSJens Wiklander 		mul = y[1] & 1;
528b314df1fSJens Wiklander 		y[1] = (y[0] << 63) | (y[1] >> 1);
529b314df1fSJens Wiklander 		y[0] = (y[0] >> 1) ^ (0xe100000000000000 * mul);
530b314df1fSJens Wiklander 	}
531b314df1fSJens Wiklander 
532b314df1fSJens Wiklander 	product[0] = TEE_U64_TO_BIG_ENDIAN(z[0]);
533b314df1fSJens Wiklander 	product[1] = TEE_U64_TO_BIG_ENDIAN(z[1]);
534b314df1fSJens Wiklander }
535b314df1fSJens Wiklander 
536*8f848cdbSJens Wiklander void internal_aes_gcm_encrypt_block(struct internal_aes_gcm_state *state,
537*8f848cdbSJens Wiklander 				    const struct internal_aes_gcm_key *enc_key,
538*8f848cdbSJens Wiklander 				    const uint64_t src[2], uint64_t dst[2])
539d7fd8f87SJens Wiklander {
540d7fd8f87SJens Wiklander 	void *buf_cryp = state->buf_cryp;
541d7fd8f87SJens Wiklander 	void *ctr = state->ctr;
542d7fd8f87SJens Wiklander 
543d7fd8f87SJens Wiklander 	internal_aes_gcm_xor_block(buf_cryp, src);
544d7fd8f87SJens Wiklander 	internal_aes_gcm_ghash_update(state, buf_cryp, NULL, 0);
545d7fd8f87SJens Wiklander 	memcpy(dst, buf_cryp, sizeof(state->buf_cryp));
546d7fd8f87SJens Wiklander 
547*8f848cdbSJens Wiklander 	crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data),
548*8f848cdbSJens Wiklander 			     enc_key->rounds, ctr, buf_cryp);
549d7fd8f87SJens Wiklander 	internal_aes_gcm_inc_ctr(state);
550d7fd8f87SJens Wiklander }
551d7fd8f87SJens Wiklander 
552d7fd8f87SJens Wiklander static void encrypt_pl(struct internal_aes_gcm_state *state,
553d7fd8f87SJens Wiklander 		       const struct internal_aes_gcm_key *ek,
554d7fd8f87SJens Wiklander 		       const uint8_t *src, size_t num_blocks, uint8_t *dst)
555d7fd8f87SJens Wiklander {
556d7fd8f87SJens Wiklander 	size_t n = 0;
557d7fd8f87SJens Wiklander 
558d7fd8f87SJens Wiklander 	if (ALIGNMENT_IS_OK(src, uint64_t)) {
559*8f848cdbSJens Wiklander 		for (n = 0; n < num_blocks; n++) {
560*8f848cdbSJens Wiklander 			const void *s = src + n * TEE_AES_BLOCK_SIZE;
561*8f848cdbSJens Wiklander 			void *d = dst + n * TEE_AES_BLOCK_SIZE;
562*8f848cdbSJens Wiklander 
563*8f848cdbSJens Wiklander 			internal_aes_gcm_encrypt_block(state, ek, s, d);
564*8f848cdbSJens Wiklander 		}
565d7fd8f87SJens Wiklander 	} else {
566d7fd8f87SJens Wiklander 		for (n = 0; n < num_blocks; n++) {
567d7fd8f87SJens Wiklander 			uint64_t tmp[2] = { 0 };
568*8f848cdbSJens Wiklander 			void *d = dst + n * TEE_AES_BLOCK_SIZE;
569d7fd8f87SJens Wiklander 
570d7fd8f87SJens Wiklander 			memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp));
571*8f848cdbSJens Wiklander 			internal_aes_gcm_encrypt_block(state, ek, tmp, d);
572d7fd8f87SJens Wiklander 		}
573d7fd8f87SJens Wiklander 	}
574d7fd8f87SJens Wiklander }
575d7fd8f87SJens Wiklander 
576*8f848cdbSJens Wiklander void internal_aes_gcm_decrypt_block(struct internal_aes_gcm_state *state,
577*8f848cdbSJens Wiklander 				    const struct internal_aes_gcm_key *enc_key,
578*8f848cdbSJens Wiklander 				    const uint64_t src[2], uint64_t dst[2])
579d7fd8f87SJens Wiklander {
580d7fd8f87SJens Wiklander 	void *buf_cryp = state->buf_cryp;
581d7fd8f87SJens Wiklander 	void *ctr = state->ctr;
582d7fd8f87SJens Wiklander 
583*8f848cdbSJens Wiklander 	crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data),
584*8f848cdbSJens Wiklander 			     enc_key->rounds, ctr, buf_cryp);
585d7fd8f87SJens Wiklander 	internal_aes_gcm_inc_ctr(state);
586d7fd8f87SJens Wiklander 
587d7fd8f87SJens Wiklander 	internal_aes_gcm_xor_block(buf_cryp, src);
588d7fd8f87SJens Wiklander 	internal_aes_gcm_ghash_update(state, src, NULL, 0);
589d7fd8f87SJens Wiklander 	memcpy(dst, buf_cryp, sizeof(state->buf_cryp));
590d7fd8f87SJens Wiklander }
591d7fd8f87SJens Wiklander 
592d7fd8f87SJens Wiklander static void decrypt_pl(struct internal_aes_gcm_state *state,
593d7fd8f87SJens Wiklander 		       const struct internal_aes_gcm_key *ek,
594d7fd8f87SJens Wiklander 		       const uint8_t *src, size_t num_blocks, uint8_t *dst)
595d7fd8f87SJens Wiklander {
596d7fd8f87SJens Wiklander 	size_t n = 0;
597d7fd8f87SJens Wiklander 
598d7fd8f87SJens Wiklander 	if (ALIGNMENT_IS_OK(src, uint64_t)) {
599*8f848cdbSJens Wiklander 		for (n = 0; n < num_blocks; n++) {
600*8f848cdbSJens Wiklander 			const void *s = src + n * TEE_AES_BLOCK_SIZE;
601*8f848cdbSJens Wiklander 			void *d = dst + n * TEE_AES_BLOCK_SIZE;
602*8f848cdbSJens Wiklander 
603*8f848cdbSJens Wiklander 			internal_aes_gcm_decrypt_block(state, ek, s, d);
604*8f848cdbSJens Wiklander 		}
605d7fd8f87SJens Wiklander 	} else {
606d7fd8f87SJens Wiklander 		for (n = 0; n < num_blocks; n++) {
607d7fd8f87SJens Wiklander 			uint64_t tmp[2] = { 0 };
608*8f848cdbSJens Wiklander 			void *d = dst + n * TEE_AES_BLOCK_SIZE;
609d7fd8f87SJens Wiklander 
610d7fd8f87SJens Wiklander 			memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp));
611*8f848cdbSJens Wiklander 			internal_aes_gcm_decrypt_block(state, ek, tmp, d);
612d7fd8f87SJens Wiklander 		}
613d7fd8f87SJens Wiklander 	}
614d7fd8f87SJens Wiklander }
615d7fd8f87SJens Wiklander 
616d7fd8f87SJens Wiklander void __weak
617d7fd8f87SJens Wiklander internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state,
618b314df1fSJens Wiklander 				       const struct internal_aes_gcm_key *ek,
619b314df1fSJens Wiklander 				       TEE_OperationMode m, const void *src,
620b314df1fSJens Wiklander 				       size_t num_blocks, void *dst)
621b314df1fSJens Wiklander {
622d7fd8f87SJens Wiklander 	assert(!state->buf_pos && num_blocks);
623b314df1fSJens Wiklander 
624d7fd8f87SJens Wiklander 	if (m == TEE_MODE_ENCRYPT)
625d7fd8f87SJens Wiklander 		encrypt_pl(state, ek, src, num_blocks, dst);
626d7fd8f87SJens Wiklander 	else
627d7fd8f87SJens Wiklander 		decrypt_pl(state, ek, src, num_blocks, dst);
628b314df1fSJens Wiklander }
6291fca7e26SJens Wiklander #endif /*!CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB*/
630