xref: /optee_os/core/crypto/aes-gcm.c (revision d7ac7d0f6ac0a7837a7d821e5e31eaae08ff7af8)
1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
21fca7e26SJens Wiklander /*
31fca7e26SJens Wiklander  * Copyright (c) 2017, Linaro Limited
41fca7e26SJens Wiklander  */
51fca7e26SJens Wiklander 
661b4cd9cSJens Wiklander #include <assert.h>
71fca7e26SJens Wiklander #include <crypto/internal_aes-gcm.h>
81fca7e26SJens Wiklander #include <io.h>
91fca7e26SJens Wiklander #include <string_ext.h>
101fca7e26SJens Wiklander #include <string.h>
111fca7e26SJens Wiklander #include <tee_api_types.h>
121fca7e26SJens Wiklander #include <types_ext.h>
131fca7e26SJens Wiklander #include <utee_defines.h>
141fca7e26SJens Wiklander #include <util.h>
151fca7e26SJens Wiklander 
16b8c186b5SJens Wiklander #include "aes-gcm-private.h"
17b8c186b5SJens 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 
9554af8d67SJens Wiklander 	internal_aes_gcm_encrypt_block(ek, state->ctr, state->buf_tag);
9654af8d67SJens Wiklander 	internal_aes_gcm_inc_ctr(state);
971fca7e26SJens Wiklander 	if (mode == TEE_MODE_ENCRYPT) {
981fca7e26SJens Wiklander 		/*
991fca7e26SJens Wiklander 		 * Encryption uses the pre-encrypted xor-buffer to encrypt
1001fca7e26SJens Wiklander 		 * while decryption encrypts the xor-buffer when needed
1011fca7e26SJens Wiklander 		 * instead.
1021fca7e26SJens Wiklander 		 *
1031fca7e26SJens Wiklander 		 * The reason for this is that the combined encryption and
1041fca7e26SJens Wiklander 		 * ghash implementation does both operations intertwined.
1051fca7e26SJens Wiklander 		 * In the decrypt case the xor-buffer is needed at the end
1061fca7e26SJens Wiklander 		 * of processing each block, while the encryption case
1071fca7e26SJens Wiklander 		 * needs xor-buffer before processing each block.
1081fca7e26SJens Wiklander 		 *
1091fca7e26SJens Wiklander 		 * In a pure software implementation we wouldn't have any
1101fca7e26SJens Wiklander 		 * use for this kind of optimization, but since this
1111fca7e26SJens Wiklander 		 * AES-GCM implementation is aimed at being combined with
1121fca7e26SJens Wiklander 		 * accelerated routines it's more convenient to always have
1131fca7e26SJens Wiklander 		 * this optimization activated.
1141fca7e26SJens Wiklander 		 */
11554af8d67SJens Wiklander 		internal_aes_gcm_encrypt_block(ek, state->ctr, state->buf_cryp);
11654af8d67SJens Wiklander 		internal_aes_gcm_inc_ctr(state);
1171fca7e26SJens Wiklander 	}
1181fca7e26SJens Wiklander 
1191fca7e26SJens Wiklander 	return TEE_SUCCESS;
1201fca7e26SJens Wiklander }
1211fca7e26SJens Wiklander 
12254af8d67SJens Wiklander TEE_Result internal_aes_gcm_init(struct internal_aes_gcm_ctx *ctx,
12354af8d67SJens Wiklander 				 TEE_OperationMode mode, const void *key,
12454af8d67SJens Wiklander 				 size_t key_len, const void *nonce,
12554af8d67SJens Wiklander 				 size_t nonce_len, size_t tag_len)
12654af8d67SJens Wiklander {
12754af8d67SJens Wiklander 	TEE_Result res = internal_aes_gcm_expand_enc_key(key, key_len,
12854af8d67SJens Wiklander 							 &ctx->key);
12954af8d67SJens Wiklander 	if (res)
13054af8d67SJens Wiklander 		return res;
13154af8d67SJens Wiklander 
13254af8d67SJens Wiklander 	return __gcm_init(&ctx->state, &ctx->key, mode, nonce, nonce_len,
13354af8d67SJens Wiklander 			  tag_len);
13454af8d67SJens Wiklander }
13554af8d67SJens Wiklander 
136043411e5SJens Wiklander static TEE_Result __gcm_update_aad(struct internal_aes_gcm_state *state,
1371fca7e26SJens Wiklander 				   const void *data, size_t len)
1381fca7e26SJens Wiklander {
1391fca7e26SJens Wiklander 	const uint8_t *d = data;
1401fca7e26SJens Wiklander 	size_t l = len;
1411fca7e26SJens Wiklander 	const uint8_t *head = NULL;
1421fca7e26SJens Wiklander 	size_t n;
1431fca7e26SJens Wiklander 
14454af8d67SJens Wiklander 	if (state->payload_bytes)
1451fca7e26SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
1461fca7e26SJens Wiklander 
14754af8d67SJens Wiklander 	state->aad_bytes += len;
1481fca7e26SJens Wiklander 
1491fca7e26SJens Wiklander 	while (l) {
15054af8d67SJens Wiklander 		if (state->buf_pos ||
15154af8d67SJens Wiklander 		    !internal_aes_gcm_ptr_is_block_aligned(d) ||
1521fca7e26SJens Wiklander 		    l < TEE_AES_BLOCK_SIZE) {
15354af8d67SJens Wiklander 			n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l);
15454af8d67SJens Wiklander 			memcpy(state->buf_hash + state->buf_pos, d, n);
15554af8d67SJens Wiklander 			state->buf_pos += n;
1561fca7e26SJens Wiklander 
15754af8d67SJens Wiklander 			if (state->buf_pos != TEE_AES_BLOCK_SIZE)
1581fca7e26SJens Wiklander 				return TEE_SUCCESS;
1591fca7e26SJens Wiklander 
16054af8d67SJens Wiklander 			state->buf_pos = 0;
16154af8d67SJens Wiklander 			head = state->buf_hash;
1621fca7e26SJens Wiklander 			d += n;
1631fca7e26SJens Wiklander 			l -= n;
1641fca7e26SJens Wiklander 		}
1651fca7e26SJens Wiklander 
166b8c186b5SJens Wiklander 		if (internal_aes_gcm_ptr_is_block_aligned(d))
1671fca7e26SJens Wiklander 			n = l / TEE_AES_BLOCK_SIZE;
1681fca7e26SJens Wiklander 		else
1691fca7e26SJens Wiklander 			n = 0;
1701fca7e26SJens Wiklander 
17154af8d67SJens Wiklander 		internal_aes_gcm_ghash_update(state, head, d, n);
1721fca7e26SJens Wiklander 		l -= n * TEE_AES_BLOCK_SIZE;
1731fca7e26SJens Wiklander 		d += n * TEE_AES_BLOCK_SIZE;
1741fca7e26SJens Wiklander 	}
1751fca7e26SJens Wiklander 
1761fca7e26SJens Wiklander 	return TEE_SUCCESS;
1771fca7e26SJens Wiklander }
1781fca7e26SJens Wiklander 
179043411e5SJens Wiklander TEE_Result internal_aes_gcm_update_aad(struct internal_aes_gcm_ctx *ctx,
180043411e5SJens Wiklander 				       const void *data, size_t len)
1811fca7e26SJens Wiklander {
182043411e5SJens Wiklander 	return __gcm_update_aad(&ctx->state, data, len);
183043411e5SJens Wiklander }
184043411e5SJens Wiklander 
185043411e5SJens Wiklander static TEE_Result
186043411e5SJens Wiklander __gcm_update_payload(struct internal_aes_gcm_state *state,
187043411e5SJens Wiklander 		     const struct internal_aes_gcm_key *ek,
188043411e5SJens Wiklander 		     TEE_OperationMode mode, const void *src,
189043411e5SJens Wiklander 		     size_t len, void *dst)
190043411e5SJens Wiklander {
1911fca7e26SJens Wiklander 	size_t n;
1921fca7e26SJens Wiklander 	const uint8_t *s = src;
1931fca7e26SJens Wiklander 	uint8_t *d = dst;
1941fca7e26SJens Wiklander 	size_t l = len;
1951fca7e26SJens Wiklander 
19654af8d67SJens Wiklander 	if (!state->payload_bytes && state->buf_pos) {
1971fca7e26SJens Wiklander 		/* AAD part done, finish up the last bits. */
19854af8d67SJens Wiklander 		memset(state->buf_hash + state->buf_pos, 0,
19954af8d67SJens Wiklander 		       TEE_AES_BLOCK_SIZE - state->buf_pos);
20054af8d67SJens Wiklander 		internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0);
20154af8d67SJens Wiklander 		state->buf_pos = 0;
2021fca7e26SJens Wiklander 	}
2031fca7e26SJens Wiklander 
20454af8d67SJens Wiklander 	state->payload_bytes += len;
2051fca7e26SJens Wiklander 
2061fca7e26SJens Wiklander 	while (l) {
20754af8d67SJens Wiklander 		if (state->buf_pos ||
20854af8d67SJens Wiklander 		    !internal_aes_gcm_ptr_is_block_aligned(s) ||
209b8c186b5SJens Wiklander 		    !internal_aes_gcm_ptr_is_block_aligned(d) ||
210b8c186b5SJens Wiklander 		    l < TEE_AES_BLOCK_SIZE) {
21154af8d67SJens Wiklander 			n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l);
2121fca7e26SJens Wiklander 
21354af8d67SJens Wiklander 			if (!state->buf_pos && mode == TEE_MODE_DECRYPT) {
21454af8d67SJens Wiklander 				internal_aes_gcm_encrypt_block(ek, state->ctr,
21554af8d67SJens Wiklander 							       state->buf_cryp);
2161fca7e26SJens Wiklander 			}
2171fca7e26SJens Wiklander 
21854af8d67SJens Wiklander 			xor_buf(state->buf_cryp + state->buf_pos, s, n);
21954af8d67SJens Wiklander 			memcpy(d, state->buf_cryp + state->buf_pos, n);
2201fca7e26SJens Wiklander 			if (mode == TEE_MODE_ENCRYPT)
22154af8d67SJens Wiklander 				memcpy(state->buf_hash + state->buf_pos,
22254af8d67SJens Wiklander 				       state->buf_cryp + state->buf_pos, n);
2231fca7e26SJens Wiklander 			else
22454af8d67SJens Wiklander 				memcpy(state->buf_hash + state->buf_pos, s, n);
2251fca7e26SJens Wiklander 
22654af8d67SJens Wiklander 			state->buf_pos += n;
2271fca7e26SJens Wiklander 
22854af8d67SJens Wiklander 			if (state->buf_pos != TEE_AES_BLOCK_SIZE)
2291fca7e26SJens Wiklander 				return TEE_SUCCESS;
2301fca7e26SJens Wiklander 
23154af8d67SJens Wiklander 			internal_aes_gcm_ghash_update(state, state->buf_hash,
2321fca7e26SJens Wiklander 						      NULL, 0);
23354af8d67SJens Wiklander 			state->buf_pos = 0;
2341fca7e26SJens Wiklander 			d += n;
2351fca7e26SJens Wiklander 			s += n;
2361fca7e26SJens Wiklander 			l -= n;
2371fca7e26SJens Wiklander 
2381fca7e26SJens Wiklander 			if (mode == TEE_MODE_ENCRYPT)
23954af8d67SJens Wiklander 				internal_aes_gcm_encrypt_block(ek, 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;
24454af8d67SJens Wiklander 			internal_aes_gcm_update_payload_block_aligned(state, ek,
24554af8d67SJens Wiklander 								      mode,
2461fca7e26SJens Wiklander 								      s, n, d);
2471fca7e26SJens Wiklander 			s += n * TEE_AES_BLOCK_SIZE;
2481fca7e26SJens Wiklander 			d += n * TEE_AES_BLOCK_SIZE;
2491fca7e26SJens Wiklander 			l -= n * TEE_AES_BLOCK_SIZE;
2501fca7e26SJens Wiklander 		}
2511fca7e26SJens Wiklander 	}
2521fca7e26SJens Wiklander 
2531fca7e26SJens Wiklander 	return TEE_SUCCESS;
2541fca7e26SJens Wiklander }
2551fca7e26SJens Wiklander 
256043411e5SJens Wiklander TEE_Result internal_aes_gcm_update_payload(struct internal_aes_gcm_ctx *ctx,
257043411e5SJens Wiklander 					   TEE_OperationMode mode,
258043411e5SJens Wiklander 					   const void *src, size_t len,
259043411e5SJens Wiklander 					   void *dst)
260043411e5SJens Wiklander {
261043411e5SJens Wiklander 	return __gcm_update_payload(&ctx->state, &ctx->key, mode, src, len,
262043411e5SJens Wiklander 				    dst);
263043411e5SJens Wiklander }
264043411e5SJens Wiklander 
265043411e5SJens Wiklander static TEE_Result operation_final(struct internal_aes_gcm_state *state,
266043411e5SJens Wiklander 				  const struct internal_aes_gcm_key *enc_key,
2671fca7e26SJens Wiklander 				  TEE_OperationMode m, const uint8_t *src,
2681fca7e26SJens Wiklander 				  size_t len, uint8_t *dst)
2691fca7e26SJens Wiklander {
2701fca7e26SJens Wiklander 	TEE_Result res;
2711fca7e26SJens Wiklander 
272043411e5SJens Wiklander 	res = __gcm_update_payload(state, enc_key, m, src, len, dst);
2731fca7e26SJens Wiklander 	if (res)
2741fca7e26SJens Wiklander 		return res;
2751fca7e26SJens Wiklander 
27654af8d67SJens Wiklander 	if (state->buf_pos) {
27754af8d67SJens Wiklander 		memset(state->buf_hash + state->buf_pos, 0,
27854af8d67SJens Wiklander 		       sizeof(state->buf_hash) - state->buf_pos);
27954af8d67SJens Wiklander 		internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0);
2801fca7e26SJens Wiklander 	}
2811fca7e26SJens Wiklander 
28254af8d67SJens Wiklander 	ghash_update_lengths(state, state->aad_bytes, state->payload_bytes);
2831fca7e26SJens Wiklander 	/* buf_tag was filled in with the first counter block aes_gcm_init() */
28454af8d67SJens Wiklander 	xor_buf(state->buf_tag, state->hash_state, state->tag_len);
2851fca7e26SJens Wiklander 
2861fca7e26SJens Wiklander 	return TEE_SUCCESS;
2871fca7e26SJens Wiklander }
2881fca7e26SJens Wiklander 
289043411e5SJens Wiklander static TEE_Result __gcm_enc_final(struct internal_aes_gcm_state *state,
290043411e5SJens Wiklander 				  const struct internal_aes_gcm_key *enc_key,
2911fca7e26SJens Wiklander 				  const void *src, size_t len, void *dst,
2921fca7e26SJens Wiklander 				  void *tag, size_t *tag_len)
2931fca7e26SJens Wiklander {
2941fca7e26SJens Wiklander 	TEE_Result res;
2951fca7e26SJens Wiklander 
29654af8d67SJens Wiklander 	if (*tag_len < state->tag_len)
2971fca7e26SJens Wiklander 		return TEE_ERROR_SHORT_BUFFER;
2981fca7e26SJens Wiklander 
299043411e5SJens Wiklander 	res = operation_final(state, enc_key, TEE_MODE_ENCRYPT, src, len, dst);
3001fca7e26SJens Wiklander 	if (res)
3011fca7e26SJens Wiklander 		return res;
3021fca7e26SJens Wiklander 
30354af8d67SJens Wiklander 	memcpy(tag, state->buf_tag, state->tag_len);
30454af8d67SJens Wiklander 	*tag_len = state->tag_len;
3051fca7e26SJens Wiklander 
3061fca7e26SJens Wiklander 	return TEE_SUCCESS;
3071fca7e26SJens Wiklander }
3081fca7e26SJens Wiklander 
309043411e5SJens Wiklander TEE_Result internal_aes_gcm_enc_final(struct internal_aes_gcm_ctx *ctx,
310043411e5SJens Wiklander 				      const void *src, size_t len, void *dst,
311043411e5SJens Wiklander 				      void *tag, size_t *tag_len)
312043411e5SJens Wiklander {
313043411e5SJens Wiklander 	return __gcm_enc_final(&ctx->state, &ctx->key, src, len, dst, tag,
314043411e5SJens Wiklander 			       tag_len);
315043411e5SJens Wiklander }
316043411e5SJens Wiklander 
317043411e5SJens Wiklander static TEE_Result __gcm_dec_final(struct internal_aes_gcm_state *state,
318043411e5SJens Wiklander 				  const struct internal_aes_gcm_key *enc_key,
3191fca7e26SJens Wiklander 				  const void *src, size_t len, void *dst,
3201fca7e26SJens Wiklander 				  const void *tag, size_t tag_len)
3211fca7e26SJens Wiklander {
3221fca7e26SJens Wiklander 	TEE_Result res;
3231fca7e26SJens Wiklander 
32454af8d67SJens Wiklander 	if (tag_len != state->tag_len)
3251fca7e26SJens Wiklander 		return TEE_ERROR_MAC_INVALID;
3261fca7e26SJens Wiklander 
327043411e5SJens Wiklander 	res = operation_final(state, enc_key, TEE_MODE_DECRYPT, src, len, dst);
3281fca7e26SJens Wiklander 	if (res)
3291fca7e26SJens Wiklander 		return res;
3301fca7e26SJens Wiklander 
33154af8d67SJens Wiklander 	if (buf_compare_ct(state->buf_tag, tag, tag_len))
3321fca7e26SJens Wiklander 		return TEE_ERROR_MAC_INVALID;
3331fca7e26SJens Wiklander 
3341fca7e26SJens Wiklander 	return TEE_SUCCESS;
3351fca7e26SJens Wiklander }
3361fca7e26SJens Wiklander 
337043411e5SJens Wiklander TEE_Result internal_aes_gcm_dec_final(struct internal_aes_gcm_ctx *ctx,
338043411e5SJens Wiklander 				      const void *src, size_t len, void *dst,
339043411e5SJens Wiklander 				      const void *tag, size_t tag_len)
340043411e5SJens Wiklander {
341043411e5SJens Wiklander 	return __gcm_dec_final(&ctx->state, &ctx->key, src, len, dst, tag,
342043411e5SJens Wiklander 			       tag_len);
343043411e5SJens Wiklander }
344043411e5SJens Wiklander 
34554af8d67SJens Wiklander void internal_aes_gcm_inc_ctr(struct internal_aes_gcm_state *state)
3461fca7e26SJens Wiklander {
3471fca7e26SJens Wiklander 	uint64_t c;
3481fca7e26SJens Wiklander 
34954af8d67SJens Wiklander 	c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]) + 1;
35054af8d67SJens Wiklander 	state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c);
3511fca7e26SJens Wiklander 	if (!c) {
35254af8d67SJens Wiklander 		c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[0]) + 1;
35354af8d67SJens Wiklander 		state->ctr[0] = TEE_U64_TO_BIG_ENDIAN(c);
3541fca7e26SJens Wiklander 	}
3551fca7e26SJens Wiklander }
3561fca7e26SJens Wiklander 
357043411e5SJens Wiklander TEE_Result internal_aes_gcm_enc(const struct internal_aes_gcm_key *enc_key,
358043411e5SJens Wiklander 				const void *nonce, size_t nonce_len,
359043411e5SJens Wiklander 				const void *aad, size_t aad_len,
360043411e5SJens Wiklander 				const void *src, size_t len, void *dst,
361043411e5SJens Wiklander 				void *tag, size_t *tag_len)
362043411e5SJens Wiklander {
363043411e5SJens Wiklander 	TEE_Result res;
364043411e5SJens Wiklander 	struct internal_aes_gcm_state state;
365043411e5SJens Wiklander 
366043411e5SJens Wiklander 	res = __gcm_init(&state, enc_key, TEE_MODE_ENCRYPT, nonce, nonce_len,
367043411e5SJens Wiklander 			 *tag_len);
368043411e5SJens Wiklander 	if (res)
369043411e5SJens Wiklander 		return res;
370043411e5SJens Wiklander 
371043411e5SJens Wiklander 	if (aad) {
372043411e5SJens Wiklander 		res = __gcm_update_aad(&state, aad, aad_len);
373043411e5SJens Wiklander 		if (res)
374043411e5SJens Wiklander 			return res;
375043411e5SJens Wiklander 	}
376043411e5SJens Wiklander 
377043411e5SJens Wiklander 	return __gcm_enc_final(&state, enc_key, src, len, dst, tag, tag_len);
378043411e5SJens Wiklander }
379043411e5SJens Wiklander 
380043411e5SJens Wiklander TEE_Result internal_aes_gcm_dec(const struct internal_aes_gcm_key *enc_key,
381043411e5SJens Wiklander 				const void *nonce, size_t nonce_len,
382043411e5SJens Wiklander 				const void *aad, size_t aad_len,
383043411e5SJens Wiklander 				const void *src, size_t len, void *dst,
384043411e5SJens Wiklander 				const void *tag, size_t tag_len)
385043411e5SJens Wiklander {
386043411e5SJens Wiklander 	TEE_Result res;
387043411e5SJens Wiklander 	struct internal_aes_gcm_state state;
388043411e5SJens Wiklander 
389043411e5SJens Wiklander 	res = __gcm_init(&state, enc_key, TEE_MODE_DECRYPT, nonce, nonce_len,
390043411e5SJens Wiklander 			 tag_len);
391043411e5SJens Wiklander 	if (res)
392043411e5SJens Wiklander 		return res;
393043411e5SJens Wiklander 
394043411e5SJens Wiklander 	if (aad) {
395043411e5SJens Wiklander 		res = __gcm_update_aad(&state, aad, aad_len);
396043411e5SJens Wiklander 		if (res)
397043411e5SJens Wiklander 			return res;
398043411e5SJens Wiklander 	}
399043411e5SJens Wiklander 
400043411e5SJens Wiklander 	return __gcm_dec_final(&state, enc_key, src, len, dst, tag, tag_len);
401043411e5SJens Wiklander }
402043411e5SJens Wiklander 
403043411e5SJens Wiklander 
4041fca7e26SJens Wiklander #ifndef CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB
4051fca7e26SJens Wiklander #include <crypto/aes-gcm.h>
406*d7ac7d0fSJens Wiklander #include <stdlib.h>
4071fca7e26SJens Wiklander 
408*d7ac7d0fSJens Wiklander TEE_Result crypto_aes_gcm_alloc_ctx(void **ctx_ret)
4091fca7e26SJens Wiklander {
410*d7ac7d0fSJens Wiklander 	struct internal_aes_gcm_ctx *ctx = calloc(1, sizeof(*ctx));
411*d7ac7d0fSJens Wiklander 
412*d7ac7d0fSJens Wiklander 	if (!ctx)
413*d7ac7d0fSJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
414*d7ac7d0fSJens Wiklander 
415*d7ac7d0fSJens Wiklander 	*ctx_ret = ctx;
416*d7ac7d0fSJens Wiklander 	return TEE_SUCCESS;
417*d7ac7d0fSJens Wiklander }
418*d7ac7d0fSJens Wiklander 
419*d7ac7d0fSJens Wiklander void crypto_aes_gcm_free_ctx(void *ctx)
420*d7ac7d0fSJens Wiklander {
421*d7ac7d0fSJens Wiklander 	free(ctx);
422*d7ac7d0fSJens Wiklander }
423*d7ac7d0fSJens Wiklander 
424*d7ac7d0fSJens Wiklander void crypto_aes_gcm_copy_state(void *dst_ctx, void *src_ctx)
425*d7ac7d0fSJens Wiklander {
426*d7ac7d0fSJens Wiklander 	memcpy(dst_ctx, src_ctx, sizeof(struct internal_aes_gcm_ctx));
4271fca7e26SJens Wiklander }
4281fca7e26SJens Wiklander 
4291fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_init(void *c, TEE_OperationMode mode,
4301fca7e26SJens Wiklander 			       const uint8_t *key, size_t key_len,
4311fca7e26SJens Wiklander 			       const uint8_t *nonce, size_t nonce_len,
4321fca7e26SJens Wiklander 			       size_t tag_len)
4331fca7e26SJens Wiklander {
4341fca7e26SJens Wiklander 	return internal_aes_gcm_init(c, mode, key, key_len, nonce, nonce_len,
4351fca7e26SJens Wiklander 				     tag_len);
4361fca7e26SJens Wiklander }
4371fca7e26SJens Wiklander 
4381fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_update_aad(void *c, const uint8_t *data, size_t len)
4391fca7e26SJens Wiklander {
4401fca7e26SJens Wiklander 	return internal_aes_gcm_update_aad(c, data, len);
4411fca7e26SJens Wiklander }
4421fca7e26SJens Wiklander 
4431fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_update_payload(void *c, TEE_OperationMode m,
4441fca7e26SJens Wiklander 					 const uint8_t *src, size_t len,
4451fca7e26SJens Wiklander 					 uint8_t *dst)
4461fca7e26SJens Wiklander {
4471fca7e26SJens Wiklander 	return internal_aes_gcm_update_payload(c, m, src, len, dst);
4481fca7e26SJens Wiklander }
4491fca7e26SJens Wiklander 
4501fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_enc_final(void *c, const uint8_t *src, size_t len,
4511fca7e26SJens Wiklander 				    uint8_t *dst, uint8_t *tag, size_t *tag_len)
4521fca7e26SJens Wiklander {
4531fca7e26SJens Wiklander 	return internal_aes_gcm_enc_final(c, src, len, dst, tag, tag_len);
4541fca7e26SJens Wiklander }
4551fca7e26SJens Wiklander 
4561fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_dec_final(void *c, const uint8_t *src, size_t len,
4571fca7e26SJens Wiklander 				    uint8_t *dst, const uint8_t *tag,
4581fca7e26SJens Wiklander 				    size_t tag_len)
4591fca7e26SJens Wiklander {
4601fca7e26SJens Wiklander 	return internal_aes_gcm_dec_final(c, src, len, dst, tag, tag_len);
4611fca7e26SJens Wiklander }
4621fca7e26SJens Wiklander 
4631fca7e26SJens Wiklander void crypto_aes_gcm_final(void *c __unused)
4641fca7e26SJens Wiklander {
4651fca7e26SJens Wiklander }
4661fca7e26SJens Wiklander #endif /*!CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB*/
467