xref: /optee_os/core/crypto/aes-gcm-sw.c (revision b1469ba0bfd0371eb52bd50f5c52eeda7a8f5f1e)
1 /*
2  * Copyright (c) 2017, Linaro Limited
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-2-Clause
6  */
7 
8 /*
9  * gfmul() is based on ghash_gfmul from
10  * https://github.com/openbsd/src/blob/master/sys/crypto/gmac.c
11  * Which is:
12  * Copyright (c) 2010 Mike Belopuhov
13  *
14  * Permission to use, copy, modify, and distribute this software for any
15  * purpose with or without fee is hereby granted, provided that the above
16  * copyright notice and this permission notice appear in all copies.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25  */
26 
27 #include <crypto/internal_aes-gcm.h>
28 #include <kernel/panic.h>
29 #include <string.h>
30 #include <tee_api_types.h>
31 #include <tomcrypt.h>
32 #include <types_ext.h>
33 
34 static bool __maybe_unused ptr_is_block_aligned(const void *p)
35 {
36 	return !((vaddr_t)p & (TEE_AES_BLOCK_SIZE - 1));
37 }
38 
39 static void xor_block(void *dst, const void *src)
40 {
41 	uint64_t *d = dst;
42 	const uint64_t *s = src;
43 
44 	d[0] ^= s[0];
45 	d[1] ^= s[1];
46 }
47 
48 TEE_Result __weak internal_aes_gcm_set_key(struct internal_aes_gcm_ctx *ctx,
49 					   const void *key, size_t key_len)
50 {
51 	if (aes_setup(key, key_len, 0, &ctx->skey))
52 		return TEE_ERROR_BAD_PARAMETERS;
53 
54 	if (aes_ecb_encrypt((void *)ctx->ctr, ctx->hash_subkey, &ctx->skey))
55 		panic();
56 
57 	return TEE_SUCCESS;
58 }
59 
60 void __weak
61 internal_aes_gcm_update_payload_block_aligned(struct internal_aes_gcm_ctx *ctx,
62 					      TEE_OperationMode m,
63 					      const void *src,
64 					      size_t num_blocks, void *dst)
65 {
66 	size_t n;
67 	const uint8_t *s = src;
68 	uint8_t *d = dst;
69 
70 	assert(!ctx->buf_pos && num_blocks &&
71 	       ptr_is_block_aligned(s) && ptr_is_block_aligned(d));
72 
73 	for (n = 0; n < num_blocks; n++) {
74 		if (m == TEE_MODE_ENCRYPT) {
75 			xor_block(ctx->buf_cryp, s);
76 			internal_aes_gcm_ghash_update(ctx, ctx->buf_cryp,
77 						      NULL, 0);
78 			memcpy(d, ctx->buf_cryp, sizeof(ctx->buf_cryp));
79 			internal_aes_gcm_encrypt_block(ctx, ctx->ctr,
80 						       ctx->buf_cryp);
81 			internal_aes_gcm_inc_ctr(ctx);
82 		} else {
83 			internal_aes_gcm_encrypt_block(ctx, ctx->ctr,
84 						       ctx->buf_cryp);
85 
86 			xor_block(ctx->buf_cryp, s);
87 			internal_aes_gcm_ghash_update(ctx, s, NULL, 0);
88 			memcpy(d, ctx->buf_cryp, sizeof(ctx->buf_cryp));
89 
90 			internal_aes_gcm_inc_ctr(ctx);
91 		}
92 		s += TEE_AES_BLOCK_SIZE;
93 		d += TEE_AES_BLOCK_SIZE;
94 	}
95 }
96 
97 void __weak internal_aes_gcm_encrypt_block(struct internal_aes_gcm_ctx *ctx,
98 					   const void *src, void *dst)
99 {
100 	if (aes_ecb_encrypt(src, dst, &ctx->skey))
101 		panic();
102 }
103