xref: /optee_os/core/arch/arm/crypto/aes-gcm-ce.c (revision 4f6d71606482a7cc346546de5b6be277985650f6)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <crypto/crypto_accel.h>
7 #include <crypto/crypto.h>
8 #include <crypto/ghash-ce-core.h>
9 #include <crypto/internal_aes-gcm.h>
10 #include <io.h>
11 #include <kernel/panic.h>
12 #include <kernel/thread.h>
13 #include <string.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 void internal_aes_gcm_set_key(struct internal_aes_gcm_state *state,
33 			      const struct internal_aes_gcm_key *enc_key)
34 {
35 	uint64_t k[2];
36 	uint64_t a;
37 	uint64_t b;
38 
39 	crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data),
40 			     enc_key->rounds, state->ctr, k);
41 
42 	/* Store hash key in little endian and multiply by 'x' */
43 	b = get_be64(k);
44 	a = get_be64(k + 1);
45 	state->ghash_key.k[0] = (a << 1) | (b >> 63);
46 	state->ghash_key.k[1] = (b << 1) | (a >> 63);
47 	if (b >> 63)
48 		state->ghash_key.k[1] ^= 0xc200000000000000UL;
49 }
50 
51 void internal_aes_gcm_ghash_update(struct internal_aes_gcm_state *state,
52 				   const void *head, const void *data,
53 				   size_t num_blocks)
54 {
55 	uint32_t vfp_state;
56 	uint64_t dg[2];
57 
58 	get_be_block(dg, state->hash_state);
59 
60 	vfp_state = thread_kernel_enable_vfp();
61 
62 #ifdef CFG_HWSUPP_PMULT_64
63 	pmull_ghash_update_p64(num_blocks, dg, data, &state->ghash_key, head);
64 #else
65 	pmull_ghash_update_p8(num_blocks, dg, data, &state->ghash_key, head);
66 #endif
67 	thread_kernel_disable_vfp(vfp_state);
68 
69 	put_be_block(state->hash_state, dg);
70 }
71 
72 TEE_Result internal_aes_gcm_expand_enc_key(const void *key, size_t key_len,
73 					   struct internal_aes_gcm_key *enc_key)
74 {
75 	return crypto_accel_aes_expand_keys(key, key_len, enc_key->data, NULL,
76 					    sizeof(enc_key->data),
77 					    &enc_key->rounds);
78 }
79 
80 #ifdef ARM64
81 void
82 internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state,
83 				       const struct internal_aes_gcm_key *ek,
84 				       TEE_OperationMode mode, const void *src,
85 				       size_t num_blocks, void *dst)
86 {
87 	uint32_t vfp_state;
88 	uint64_t dg[2];
89 	uint64_t ctr[2];
90 
91 	get_be_block(dg, state->hash_state);
92 	get_be_block(ctr, state->ctr);
93 
94 	vfp_state = thread_kernel_enable_vfp();
95 
96 	pmull_gcm_load_round_keys(ek->data, ek->rounds);
97 
98 	if (mode == TEE_MODE_ENCRYPT)
99 		pmull_gcm_encrypt(num_blocks, dg, dst, src, &state->ghash_key,
100 				  ctr, ek->rounds, state->buf_cryp);
101 	else
102 		pmull_gcm_decrypt(num_blocks, dg, dst, src, &state->ghash_key,
103 				  ctr, ek->rounds);
104 
105 	thread_kernel_disable_vfp(vfp_state);
106 
107 	put_be_block(state->ctr, ctr);
108 	put_be_block(state->hash_state, dg);
109 }
110 #endif /*ARM64*/
111