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