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