xref: /optee_os/core/lib/libtomcrypt/aes_accel.c (revision f6be0e138405da81ea4fd4e69af700c4aa54cf9e)
1f9429266SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2f9429266SJens Wiklander /*
3f9429266SJens Wiklander  * Copyright (c) 2015, Linaro Limited
4f9429266SJens Wiklander  * All rights reserved.
5f9429266SJens Wiklander  * Copyright (c) 2001-2007, Tom St Denis
6f9429266SJens Wiklander  * All rights reserved.
7f9429266SJens Wiklander  *
8f9429266SJens Wiklander  * Redistribution and use in source and binary forms, with or without
9f9429266SJens Wiklander  * modification, are permitted provided that the following conditions are met:
10f9429266SJens Wiklander  *
11f9429266SJens Wiklander  * 1. Redistributions of source code must retain the above copyright notice,
12f9429266SJens Wiklander  * this list of conditions and the following disclaimer.
13f9429266SJens Wiklander  *
14f9429266SJens Wiklander  * 2. Redistributions in binary form must reproduce the above copyright notice,
15f9429266SJens Wiklander  * this list of conditions and the following disclaimer in the documentation
16f9429266SJens Wiklander  * and/or other materials provided with the distribution.
17f9429266SJens Wiklander  *
18f9429266SJens Wiklander  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19f9429266SJens Wiklander  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20f9429266SJens Wiklander  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21f9429266SJens Wiklander  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22f9429266SJens Wiklander  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23f9429266SJens Wiklander  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24f9429266SJens Wiklander  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25f9429266SJens Wiklander  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26f9429266SJens Wiklander  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27f9429266SJens Wiklander  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28f9429266SJens Wiklander  * POSSIBILITY OF SUCH DAMAGE.
29f9429266SJens Wiklander  */
30f9429266SJens Wiklander 
31f9429266SJens Wiklander /* LibTomCrypt, modular cryptographic library -- Tom St Denis
32f9429266SJens Wiklander  *
33f9429266SJens Wiklander  * LibTomCrypt is a library that provides various cryptographic
34f9429266SJens Wiklander  * algorithms in a highly modular and flexible manner.
35f9429266SJens Wiklander  *
36f9429266SJens Wiklander  * The library is free for all purposes without any express
37f9429266SJens Wiklander  * guarantee it works.
38f9429266SJens Wiklander  *
39f9429266SJens Wiklander  * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
40f9429266SJens Wiklander  */
41f9429266SJens Wiklander 
42f9429266SJens Wiklander /*
43f9429266SJens Wiklander  * AES cipher for ARMv8 with Crypto Extensions
44f9429266SJens Wiklander  *
45f9429266SJens Wiklander  * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
46f9429266SJens Wiklander  */
47f9429266SJens Wiklander 
48f9429266SJens Wiklander #include <compiler.h>
49f9429266SJens Wiklander #include <crypto/crypto_accel.h>
50f9429266SJens Wiklander #include <tomcrypt_private.h>
51f9429266SJens Wiklander 
522a65ecafSJens Wiklander #define EXPANDED_AES_KEY_WORD_COUNT	60
532a65ecafSJens Wiklander #define EXPANDED_AES_KEY_LEN		(EXPANDED_AES_KEY_WORD_COUNT * \
542a65ecafSJens Wiklander 					 sizeof(uint32_t))
552a65ecafSJens Wiklander 
rijndael_setup(const unsigned char * key,int keylen,int num_rounds,symmetric_key * skey)56f9429266SJens Wiklander int rijndael_setup(const unsigned char *key, int keylen, int num_rounds,
57f9429266SJens Wiklander 	      symmetric_key *skey)
58f9429266SJens Wiklander {
59f9429266SJens Wiklander 	unsigned int round_count = 0;
60f9429266SJens Wiklander 
61f9429266SJens Wiklander 	LTC_ARGCHK(key);
62f9429266SJens Wiklander 	LTC_ARGCHK(skey);
63f9429266SJens Wiklander 
64f9429266SJens Wiklander 	if (keylen != 16 && keylen != 24 && keylen != 32)
65f9429266SJens Wiklander 		return CRYPT_INVALID_KEYSIZE;
66f9429266SJens Wiklander 
672a65ecafSJens Wiklander 	skey->rijndael.eK = LTC_ALIGN_BUF(skey->rijndael.K, 16);
682a65ecafSJens Wiklander 	skey->rijndael.dK = skey->rijndael.eK + EXPANDED_AES_KEY_WORD_COUNT;
692a65ecafSJens Wiklander 
70f9429266SJens Wiklander 	if (crypto_accel_aes_expand_keys(key, keylen, skey->rijndael.eK,
71f9429266SJens Wiklander 					 skey->rijndael.dK,
722a65ecafSJens Wiklander 					 EXPANDED_AES_KEY_LEN,
73f9429266SJens Wiklander 					 &round_count))
74f9429266SJens Wiklander 		return CRYPT_INVALID_ARG;
75f9429266SJens Wiklander 
76f9429266SJens Wiklander 	if (num_rounds && (unsigned int)num_rounds != round_count)
77f9429266SJens Wiklander 		return CRYPT_INVALID_ROUNDS;
78f9429266SJens Wiklander 
79f9429266SJens Wiklander 	skey->rijndael.Nr = round_count;
80f9429266SJens Wiklander 
81f9429266SJens Wiklander 	return CRYPT_OK;
82f9429266SJens Wiklander }
83f9429266SJens Wiklander 
rijndael_done(symmetric_key * skey __unused)84f9429266SJens Wiklander void rijndael_done(symmetric_key *skey __unused)
85f9429266SJens Wiklander {
86f9429266SJens Wiklander }
87f9429266SJens Wiklander 
rijndael_keysize(int * keysize)88f9429266SJens Wiklander int rijndael_keysize(int *keysize)
89f9429266SJens Wiklander {
90f9429266SJens Wiklander 	LTC_ARGCHK(keysize);
91f9429266SJens Wiklander 
92f9429266SJens Wiklander 	if (*keysize < 16)
93f9429266SJens Wiklander 		return CRYPT_INVALID_KEYSIZE;
94f9429266SJens Wiklander 	else if (*keysize < 24)
95f9429266SJens Wiklander 		*keysize = 16;
96f9429266SJens Wiklander 	else if (*keysize < 32)
97f9429266SJens Wiklander 		*keysize = 24;
98f9429266SJens Wiklander 	else
99f9429266SJens Wiklander 		*keysize = 32;
100f9429266SJens Wiklander 
101f9429266SJens Wiklander 	return CRYPT_OK;
102f9429266SJens Wiklander }
103f9429266SJens Wiklander 
aes_ecb_encrypt_nblocks(const unsigned char * pt,unsigned char * ct,unsigned long blocks,const symmetric_key * skey)104f9429266SJens Wiklander static int aes_ecb_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
105f9429266SJens Wiklander 				   unsigned long blocks,
106f9429266SJens Wiklander 				   const symmetric_key *skey)
107f9429266SJens Wiklander {
108f9429266SJens Wiklander 	LTC_ARGCHK(pt);
109f9429266SJens Wiklander 	LTC_ARGCHK(ct);
110f9429266SJens Wiklander 	LTC_ARGCHK(skey);
111f9429266SJens Wiklander 
112f9429266SJens Wiklander 	crypto_accel_aes_ecb_enc(ct, pt, skey->rijndael.eK, skey->rijndael.Nr,
113f9429266SJens Wiklander 				 blocks);
114f9429266SJens Wiklander 	return CRYPT_OK;
115f9429266SJens Wiklander }
116f9429266SJens Wiklander 
aes_ecb_decrypt_nblocks(const unsigned char * ct,unsigned char * pt,unsigned long blocks,const symmetric_key * skey)117f9429266SJens Wiklander static int aes_ecb_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
118f9429266SJens Wiklander 				   unsigned long blocks,
119f9429266SJens Wiklander 				   const symmetric_key *skey)
120f9429266SJens Wiklander {
121f9429266SJens Wiklander 	LTC_ARGCHK(pt);
122f9429266SJens Wiklander 	LTC_ARGCHK(ct);
123f9429266SJens Wiklander 	LTC_ARGCHK(skey);
124f9429266SJens Wiklander 
125f9429266SJens Wiklander 	crypto_accel_aes_ecb_dec(pt, ct, skey->rijndael.dK, skey->rijndael.Nr,
126f9429266SJens Wiklander 				 blocks);
127f9429266SJens Wiklander 
128f9429266SJens Wiklander 	return CRYPT_OK;
129f9429266SJens Wiklander }
130f9429266SJens Wiklander 
rijndael_ecb_encrypt(const unsigned char * pt,unsigned char * ct,const symmetric_key * skey)131f9429266SJens Wiklander int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
132f9429266SJens Wiklander 			 const symmetric_key *skey)
133f9429266SJens Wiklander {
134f9429266SJens Wiklander 	return aes_ecb_encrypt_nblocks(pt, ct, 1, skey);
135f9429266SJens Wiklander }
136f9429266SJens Wiklander 
rijndael_ecb_decrypt(const unsigned char * ct,unsigned char * pt,const symmetric_key * skey)137f9429266SJens Wiklander int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
138f9429266SJens Wiklander 			 const symmetric_key *skey)
139f9429266SJens Wiklander {
140f9429266SJens Wiklander 	return aes_ecb_decrypt_nblocks(ct, pt, 1, skey);
141f9429266SJens Wiklander }
142f9429266SJens Wiklander 
aes_cbc_encrypt_nblocks(const unsigned char * pt,unsigned char * ct,unsigned long blocks,unsigned char * IV,symmetric_key * skey)143f9429266SJens Wiklander static int aes_cbc_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
144f9429266SJens Wiklander 				   unsigned long blocks, unsigned char *IV,
145f9429266SJens Wiklander 				   symmetric_key *skey)
146f9429266SJens Wiklander {
147f9429266SJens Wiklander 	LTC_ARGCHK(pt);
148f9429266SJens Wiklander 	LTC_ARGCHK(ct);
149f9429266SJens Wiklander 	LTC_ARGCHK(IV);
150f9429266SJens Wiklander 	LTC_ARGCHK(skey);
151f9429266SJens Wiklander 
152f9429266SJens Wiklander 	crypto_accel_aes_cbc_enc(ct, pt, skey->rijndael.eK, skey->rijndael.Nr,
153f9429266SJens Wiklander 				 blocks, IV);
154f9429266SJens Wiklander 
155f9429266SJens Wiklander 	return CRYPT_OK;
156f9429266SJens Wiklander }
157f9429266SJens Wiklander 
aes_cbc_decrypt_nblocks(const unsigned char * ct,unsigned char * pt,unsigned long blocks,unsigned char * IV,symmetric_key * skey)158f9429266SJens Wiklander static int aes_cbc_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
159f9429266SJens Wiklander 				   unsigned long blocks, unsigned char *IV,
160f9429266SJens Wiklander 				   symmetric_key *skey)
161f9429266SJens Wiklander {
162f9429266SJens Wiklander 	LTC_ARGCHK(pt);
163f9429266SJens Wiklander 	LTC_ARGCHK(ct);
164f9429266SJens Wiklander 	LTC_ARGCHK(IV);
165f9429266SJens Wiklander 	LTC_ARGCHK(skey);
166f9429266SJens Wiklander 
167f9429266SJens Wiklander 	crypto_accel_aes_cbc_dec(pt, ct, skey->rijndael.dK, skey->rijndael.Nr,
168f9429266SJens Wiklander 				 blocks, IV);
169f9429266SJens Wiklander 
170f9429266SJens Wiklander 	return CRYPT_OK;
171f9429266SJens Wiklander }
172f9429266SJens Wiklander 
173*f6be0e13SJacob Kroon #ifdef LTC_CTR_MODE
aes_ctr_encrypt_nblocks(const unsigned char * pt,unsigned char * ct,unsigned long blocks,unsigned char * IV,int mode,symmetric_key * skey)174f9429266SJens Wiklander static int aes_ctr_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
175f9429266SJens Wiklander 				   unsigned long blocks, unsigned char *IV,
176f9429266SJens Wiklander 				   int mode, symmetric_key *skey)
177f9429266SJens Wiklander {
178f9429266SJens Wiklander 	LTC_ARGCHK(pt);
179f9429266SJens Wiklander 	LTC_ARGCHK(ct);
180f9429266SJens Wiklander 	LTC_ARGCHK(IV);
181f9429266SJens Wiklander 	LTC_ARGCHK(skey);
182f9429266SJens Wiklander 
183f9429266SJens Wiklander 	if (mode == CTR_COUNTER_LITTLE_ENDIAN) {
184f9429266SJens Wiklander 		/* Accelerated algorithm supports big endian only */
185f9429266SJens Wiklander 		return CRYPT_ERROR;
186f9429266SJens Wiklander 	}
187f9429266SJens Wiklander 
188f9429266SJens Wiklander 	crypto_accel_aes_ctr_be_enc(ct, pt, skey->rijndael.eK,
189f9429266SJens Wiklander 				    skey->rijndael.Nr, blocks, IV);
190f9429266SJens Wiklander 
191f9429266SJens Wiklander 	return CRYPT_OK;
192f9429266SJens Wiklander }
193*f6be0e13SJacob Kroon #endif
194f9429266SJens Wiklander 
aes_xts_encrypt_nblocks(const unsigned char * pt,unsigned char * ct,unsigned long blocks,unsigned char * tweak,const symmetric_key * skey1,const symmetric_key * skey2)195f9429266SJens Wiklander static int aes_xts_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
196f9429266SJens Wiklander 				   unsigned long blocks, unsigned char *tweak,
197f9429266SJens Wiklander 				   const symmetric_key *skey1,
198f9429266SJens Wiklander 				   const symmetric_key *skey2)
199f9429266SJens Wiklander {
200f9429266SJens Wiklander 	LTC_ARGCHK(pt);
201f9429266SJens Wiklander 	LTC_ARGCHK(ct);
202f9429266SJens Wiklander 	LTC_ARGCHK(tweak);
203f9429266SJens Wiklander 	LTC_ARGCHK(skey1);
204f9429266SJens Wiklander 	LTC_ARGCHK(skey2);
205f9429266SJens Wiklander 	LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr);
206f9429266SJens Wiklander 
207f9429266SJens Wiklander 
208f9429266SJens Wiklander 	crypto_accel_aes_xts_enc(ct, pt, skey1->rijndael.eK,
209f9429266SJens Wiklander 				 skey1->rijndael.Nr, blocks,
210f9429266SJens Wiklander 				 skey2->rijndael.eK, tweak);
211f9429266SJens Wiklander 
212f9429266SJens Wiklander 	return CRYPT_OK;
213f9429266SJens Wiklander }
214f9429266SJens Wiklander 
aes_xts_decrypt_nblocks(const unsigned char * ct,unsigned char * pt,unsigned long blocks,unsigned char * tweak,const symmetric_key * skey1,const symmetric_key * skey2)215f9429266SJens Wiklander static int aes_xts_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
216f9429266SJens Wiklander 				   unsigned long blocks, unsigned char *tweak,
217f9429266SJens Wiklander 				   const symmetric_key *skey1,
218f9429266SJens Wiklander 				   const symmetric_key *skey2)
219f9429266SJens Wiklander {
220f9429266SJens Wiklander 	LTC_ARGCHK(pt);
221f9429266SJens Wiklander 	LTC_ARGCHK(ct);
222f9429266SJens Wiklander 	LTC_ARGCHK(tweak);
223f9429266SJens Wiklander 	LTC_ARGCHK(skey1);
224f9429266SJens Wiklander 	LTC_ARGCHK(skey2);
225f9429266SJens Wiklander 	LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr);
226f9429266SJens Wiklander 
227f9429266SJens Wiklander 	crypto_accel_aes_xts_dec(pt, ct, skey1->rijndael.dK,
228f9429266SJens Wiklander 				 skey1->rijndael.Nr, blocks,
229f9429266SJens Wiklander 				 skey2->rijndael.eK, tweak);
230f9429266SJens Wiklander 
231f9429266SJens Wiklander 	return CRYPT_OK;
232f9429266SJens Wiklander }
233f9429266SJens Wiklander 
234f9429266SJens Wiklander const struct ltc_cipher_descriptor aes_desc = {
235f9429266SJens Wiklander 	.name = "aes",
236f9429266SJens Wiklander 	.ID = 6,
237f9429266SJens Wiklander 	.min_key_length = 16,
238f9429266SJens Wiklander 	.max_key_length = 32,
239f9429266SJens Wiklander 	.block_length = 16,
240f9429266SJens Wiklander 	.default_rounds = 10,
241f9429266SJens Wiklander 	.setup = rijndael_setup,
242f9429266SJens Wiklander 	.ecb_encrypt = rijndael_ecb_encrypt,
243f9429266SJens Wiklander 	.ecb_decrypt = rijndael_ecb_decrypt,
244f9429266SJens Wiklander 	.done = rijndael_done,
245f9429266SJens Wiklander 	.keysize = rijndael_keysize,
246f9429266SJens Wiklander 	.accel_ecb_encrypt = aes_ecb_encrypt_nblocks,
247f9429266SJens Wiklander 	.accel_ecb_decrypt = aes_ecb_decrypt_nblocks,
248f9429266SJens Wiklander 	.accel_cbc_encrypt = aes_cbc_encrypt_nblocks,
249f9429266SJens Wiklander 	.accel_cbc_decrypt = aes_cbc_decrypt_nblocks,
250*f6be0e13SJacob Kroon #ifdef LTC_CTR_MODE
251f9429266SJens Wiklander 	.accel_ctr_encrypt = aes_ctr_encrypt_nblocks,
252*f6be0e13SJacob Kroon #endif
253f9429266SJens Wiklander 	.accel_xts_encrypt = aes_xts_encrypt_nblocks,
254f9429266SJens Wiklander 	.accel_xts_decrypt = aes_xts_decrypt_nblocks,
255f9429266SJens Wiklander };
256