xref: /optee_os/core/arch/arm/crypto/aes-gcm-ce.c (revision 1fca7e269b134c6a02d662cdbd6ee67fa3b9801c)
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 TEE_Result internal_aes_gcm_set_key(struct internal_aes_gcm_ctx *ctx,
17 				    const void *key, size_t key_len)
18 {
19 	uint64_t k[2];
20 	uint64_t a;
21 	uint64_t b;
22 
23 	if (aes_setup(key, key_len, 0, &ctx->skey))
24 		return TEE_ERROR_BAD_PARAMETERS;
25 
26 	internal_aes_gcm_encrypt_block(ctx, ctx->ctr, ctx->hash_subkey);
27 
28 	/* Store hash key in little endian and multiply by 'x' */
29 	b = get_be64(ctx->hash_subkey);
30 	a = get_be64(ctx->hash_subkey + 8);
31 	k[0] = (a << 1) | (b >> 63);
32 	k[1] = (b << 1) | (a >> 63);
33 	if (b >> 63)
34 		k[1] ^= 0xc200000000000000UL;
35 
36 	memcpy(ctx->hash_subkey, k, TEE_AES_BLOCK_SIZE);
37 	return TEE_SUCCESS;
38 }
39 
40 static void get_dg(uint64_t dg[2], struct internal_aes_gcm_ctx *ctx)
41 {
42 	dg[1] = get_be64(ctx->hash_state);
43 	dg[0] = get_be64(ctx->hash_state + 8);
44 }
45 
46 static void put_dg(struct internal_aes_gcm_ctx *ctx, uint64_t dg[2])
47 {
48 	put_be64(ctx->hash_state, dg[1]);
49 	put_be64(ctx->hash_state + 8, dg[0]);
50 }
51 
52 void internal_aes_gcm_ghash_update(struct internal_aes_gcm_ctx *ctx,
53 				   const void *head, const void *data,
54 				 size_t num_blocks)
55 {
56 	uint32_t vfp_state;
57 	uint64_t dg[2];
58 	uint64_t *k;
59 
60 	get_dg(dg, ctx);
61 
62 	k = (void *)ctx->hash_subkey;
63 
64 	vfp_state = thread_kernel_enable_vfp();
65 
66 #ifdef CFG_HWSUPP_PMULL
67 	pmull_ghash_update_p64(num_blocks, dg, data, k, head);
68 #else
69 	pmull_ghash_update_p8(num_blocks, dg, data, k, head);
70 #endif
71 	thread_kernel_disable_vfp(vfp_state);
72 
73 	put_dg(ctx, dg);
74 }
75 
76 #ifdef ARM64
77 void internal_aes_gcm_encrypt_block(struct internal_aes_gcm_ctx *ctx,
78 				    const void *src, void *dst)
79 {
80 	uint32_t vfp_state;
81 	void *enc_key = ctx->skey.rijndael.eK;
82 	size_t rounds = ctx->skey.rijndael.Nr;
83 
84 	vfp_state = thread_kernel_enable_vfp();
85 
86 	pmull_gcm_load_round_keys(enc_key, rounds);
87 	pmull_gcm_encrypt_block(dst, src, rounds);
88 
89 	thread_kernel_disable_vfp(vfp_state);
90 }
91 
92 void
93 internal_aes_gcm_update_payload_block_aligned(struct internal_aes_gcm_ctx *ctx,
94 					      TEE_OperationMode m,
95 					      const void *src,
96 					      size_t num_blocks, void *dst)
97 {
98 	uint32_t vfp_state;
99 	uint64_t dg[2];
100 	uint64_t *k;
101 	void *ctr = ctx->ctr;
102 	void *enc_key = ctx->skey.rijndael.eK;
103 	size_t rounds = ctx->skey.rijndael.Nr;
104 
105 	get_dg(dg, ctx);
106 	k = (void *)ctx->hash_subkey;
107 
108 	vfp_state = thread_kernel_enable_vfp();
109 
110 	pmull_gcm_load_round_keys(enc_key, rounds);
111 
112 	if (m == TEE_MODE_ENCRYPT)
113 		pmull_gcm_encrypt(num_blocks, dg, dst, src, k, ctr, rounds,
114 				  ctx->buf_cryp);
115 	else
116 		pmull_gcm_decrypt(num_blocks, dg, dst, src, k, ctr, rounds);
117 
118 	thread_kernel_disable_vfp(vfp_state);
119 
120 	put_dg(ctx, dg);
121 }
122 #endif /*ARM64*/
123