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