xref: /optee_os/core/arch/arm/crypto/aes-gcm-ce.c (revision 61b4cd9c4374b872e59d84b3d6b564264716c485)
1 /*
2  * Copyright (c) 2017, Linaro Limited
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-2-Clause
6  */
7 
8 #include <crypto/internal_aes-gcm.h>
9 #include <crypto/ghash-ce-core.h>
10 #include <io.h>
11 #include <kernel/panic.h>
12 #include <kernel/thread.h>
13 #include <tomcrypt.h>
14 #include <types_ext.h>
15 
16 static void get_be_block(void *dst, const void *src)
17 {
18 	uint64_t *d = dst;
19 
20 	d[1] = get_be64(src);
21 	d[0] = get_be64((const uint8_t *)src + 8);
22 }
23 
24 static void put_be_block(void *dst, const void *src)
25 {
26 	const uint64_t *s = src;
27 
28 	put_be64(dst, s[1]);
29 	put_be64((uint8_t *)dst + 8, s[0]);
30 }
31 
32 TEE_Result internal_aes_gcm_set_key(struct internal_aes_gcm_ctx *ctx,
33 				    const void *key, size_t key_len)
34 {
35 	TEE_Result res;
36 	uint64_t k[2];
37 	uint64_t a;
38 	uint64_t b;
39 
40 	res = internal_aes_gcm_expand_enc_key(key, key_len, ctx->enc_key,
41 					      &ctx->rounds);
42 	if (res)
43 		return res;
44 
45 	internal_aes_gcm_encrypt_block(ctx, ctx->ctr, ctx->hash_subkey);
46 
47 	/* Store hash key in little endian and multiply by 'x' */
48 	b = get_be64(ctx->hash_subkey);
49 	a = get_be64(ctx->hash_subkey + 8);
50 	k[0] = (a << 1) | (b >> 63);
51 	k[1] = (b << 1) | (a >> 63);
52 	if (b >> 63)
53 		k[1] ^= 0xc200000000000000UL;
54 
55 	memcpy(ctx->hash_subkey, k, TEE_AES_BLOCK_SIZE);
56 	return TEE_SUCCESS;
57 }
58 
59 void internal_aes_gcm_ghash_update(struct internal_aes_gcm_ctx *ctx,
60 				   const void *head, const void *data,
61 				 size_t num_blocks)
62 {
63 	uint32_t vfp_state;
64 	uint64_t dg[2];
65 	uint64_t *k;
66 
67 	get_be_block(dg, ctx->hash_state);
68 
69 	k = (void *)ctx->hash_subkey;
70 
71 	vfp_state = thread_kernel_enable_vfp();
72 
73 #ifdef CFG_HWSUPP_PMULL
74 	pmull_ghash_update_p64(num_blocks, dg, data, k, head);
75 #else
76 	pmull_ghash_update_p8(num_blocks, dg, data, k, head);
77 #endif
78 	thread_kernel_disable_vfp(vfp_state);
79 
80 	put_be_block(ctx->hash_state, dg);
81 }
82 
83 #ifdef ARM64
84 void internal_aes_gcm_encrypt_block(struct internal_aes_gcm_ctx *ctx,
85 				    const void *src, void *dst)
86 {
87 	uint32_t vfp_state;
88 
89 	vfp_state = thread_kernel_enable_vfp();
90 
91 	pmull_gcm_load_round_keys(ctx->enc_key, ctx->rounds);
92 	pmull_gcm_encrypt_block(dst, src, ctx->rounds);
93 
94 	thread_kernel_disable_vfp(vfp_state);
95 }
96 
97 void
98 internal_aes_gcm_update_payload_block_aligned(struct internal_aes_gcm_ctx *ctx,
99 					      TEE_OperationMode m,
100 					      const void *src,
101 					      size_t num_blocks, void *dst)
102 {
103 	uint32_t vfp_state;
104 	uint64_t dg[2];
105 	uint64_t ctr[2];
106 	uint64_t *k;
107 
108 	get_be_block(dg, ctx->hash_state);
109 	get_be_block(ctr, ctx->ctr);
110 
111 	k = (void *)ctx->hash_subkey;
112 
113 	vfp_state = thread_kernel_enable_vfp();
114 
115 	pmull_gcm_load_round_keys(ctx->enc_key, ctx->rounds);
116 
117 	if (m == TEE_MODE_ENCRYPT)
118 		pmull_gcm_encrypt(num_blocks, dg, dst, src, k, ctr, ctx->rounds,
119 				  ctx->buf_cryp);
120 	else
121 		pmull_gcm_decrypt(num_blocks, dg, dst, src, k, ctr,
122 				  ctx->rounds);
123 
124 	thread_kernel_disable_vfp(vfp_state);
125 
126 	put_be_block(ctx->ctr, ctr);
127 	put_be_block(ctx->hash_state, dg);
128 }
129 #endif /*ARM64*/
130