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
52 #define EXPANDED_AES_KEY_WORD_COUNT 60
53 #define EXPANDED_AES_KEY_LEN (EXPANDED_AES_KEY_WORD_COUNT * \
54 sizeof(uint32_t))
55
rijndael_setup(const unsigned char * key,int keylen,int num_rounds,symmetric_key * skey)56 int rijndael_setup(const unsigned char *key, int keylen, int num_rounds,
57 symmetric_key *skey)
58 {
59 unsigned int round_count = 0;
60
61 LTC_ARGCHK(key);
62 LTC_ARGCHK(skey);
63
64 if (keylen != 16 && keylen != 24 && keylen != 32)
65 return CRYPT_INVALID_KEYSIZE;
66
67 skey->rijndael.eK = LTC_ALIGN_BUF(skey->rijndael.K, 16);
68 skey->rijndael.dK = skey->rijndael.eK + EXPANDED_AES_KEY_WORD_COUNT;
69
70 if (crypto_accel_aes_expand_keys(key, keylen, skey->rijndael.eK,
71 skey->rijndael.dK,
72 EXPANDED_AES_KEY_LEN,
73 &round_count))
74 return CRYPT_INVALID_ARG;
75
76 if (num_rounds && (unsigned int)num_rounds != round_count)
77 return CRYPT_INVALID_ROUNDS;
78
79 skey->rijndael.Nr = round_count;
80
81 return CRYPT_OK;
82 }
83
rijndael_done(symmetric_key * skey __unused)84 void rijndael_done(symmetric_key *skey __unused)
85 {
86 }
87
rijndael_keysize(int * keysize)88 int rijndael_keysize(int *keysize)
89 {
90 LTC_ARGCHK(keysize);
91
92 if (*keysize < 16)
93 return CRYPT_INVALID_KEYSIZE;
94 else if (*keysize < 24)
95 *keysize = 16;
96 else if (*keysize < 32)
97 *keysize = 24;
98 else
99 *keysize = 32;
100
101 return CRYPT_OK;
102 }
103
aes_ecb_encrypt_nblocks(const unsigned char * pt,unsigned char * ct,unsigned long blocks,const symmetric_key * skey)104 static int aes_ecb_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
105 unsigned long blocks,
106 const symmetric_key *skey)
107 {
108 LTC_ARGCHK(pt);
109 LTC_ARGCHK(ct);
110 LTC_ARGCHK(skey);
111
112 crypto_accel_aes_ecb_enc(ct, pt, skey->rijndael.eK, skey->rijndael.Nr,
113 blocks);
114 return CRYPT_OK;
115 }
116
aes_ecb_decrypt_nblocks(const unsigned char * ct,unsigned char * pt,unsigned long blocks,const symmetric_key * skey)117 static int aes_ecb_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
118 unsigned long blocks,
119 const symmetric_key *skey)
120 {
121 LTC_ARGCHK(pt);
122 LTC_ARGCHK(ct);
123 LTC_ARGCHK(skey);
124
125 crypto_accel_aes_ecb_dec(pt, ct, skey->rijndael.dK, skey->rijndael.Nr,
126 blocks);
127
128 return CRYPT_OK;
129 }
130
rijndael_ecb_encrypt(const unsigned char * pt,unsigned char * ct,const symmetric_key * skey)131 int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
132 const symmetric_key *skey)
133 {
134 return aes_ecb_encrypt_nblocks(pt, ct, 1, skey);
135 }
136
rijndael_ecb_decrypt(const unsigned char * ct,unsigned char * pt,const symmetric_key * skey)137 int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
138 const symmetric_key *skey)
139 {
140 return aes_ecb_decrypt_nblocks(ct, pt, 1, skey);
141 }
142
aes_cbc_encrypt_nblocks(const unsigned char * pt,unsigned char * ct,unsigned long blocks,unsigned char * IV,symmetric_key * skey)143 static int aes_cbc_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
144 unsigned long blocks, unsigned char *IV,
145 symmetric_key *skey)
146 {
147 LTC_ARGCHK(pt);
148 LTC_ARGCHK(ct);
149 LTC_ARGCHK(IV);
150 LTC_ARGCHK(skey);
151
152 crypto_accel_aes_cbc_enc(ct, pt, skey->rijndael.eK, skey->rijndael.Nr,
153 blocks, IV);
154
155 return CRYPT_OK;
156 }
157
aes_cbc_decrypt_nblocks(const unsigned char * ct,unsigned char * pt,unsigned long blocks,unsigned char * IV,symmetric_key * skey)158 static int aes_cbc_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
159 unsigned long blocks, unsigned char *IV,
160 symmetric_key *skey)
161 {
162 LTC_ARGCHK(pt);
163 LTC_ARGCHK(ct);
164 LTC_ARGCHK(IV);
165 LTC_ARGCHK(skey);
166
167 crypto_accel_aes_cbc_dec(pt, ct, skey->rijndael.dK, skey->rijndael.Nr,
168 blocks, IV);
169
170 return CRYPT_OK;
171 }
172
173 #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)174 static int aes_ctr_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
175 unsigned long blocks, unsigned char *IV,
176 int mode, symmetric_key *skey)
177 {
178 LTC_ARGCHK(pt);
179 LTC_ARGCHK(ct);
180 LTC_ARGCHK(IV);
181 LTC_ARGCHK(skey);
182
183 if (mode == CTR_COUNTER_LITTLE_ENDIAN) {
184 /* Accelerated algorithm supports big endian only */
185 return CRYPT_ERROR;
186 }
187
188 crypto_accel_aes_ctr_be_enc(ct, pt, skey->rijndael.eK,
189 skey->rijndael.Nr, blocks, IV);
190
191 return CRYPT_OK;
192 }
193 #endif
194
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)195 static int aes_xts_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
196 unsigned long blocks, unsigned char *tweak,
197 const symmetric_key *skey1,
198 const symmetric_key *skey2)
199 {
200 LTC_ARGCHK(pt);
201 LTC_ARGCHK(ct);
202 LTC_ARGCHK(tweak);
203 LTC_ARGCHK(skey1);
204 LTC_ARGCHK(skey2);
205 LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr);
206
207
208 crypto_accel_aes_xts_enc(ct, pt, skey1->rijndael.eK,
209 skey1->rijndael.Nr, blocks,
210 skey2->rijndael.eK, tweak);
211
212 return CRYPT_OK;
213 }
214
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)215 static int aes_xts_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
216 unsigned long blocks, unsigned char *tweak,
217 const symmetric_key *skey1,
218 const symmetric_key *skey2)
219 {
220 LTC_ARGCHK(pt);
221 LTC_ARGCHK(ct);
222 LTC_ARGCHK(tweak);
223 LTC_ARGCHK(skey1);
224 LTC_ARGCHK(skey2);
225 LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr);
226
227 crypto_accel_aes_xts_dec(pt, ct, skey1->rijndael.dK,
228 skey1->rijndael.Nr, blocks,
229 skey2->rijndael.eK, tweak);
230
231 return CRYPT_OK;
232 }
233
234 const struct ltc_cipher_descriptor aes_desc = {
235 .name = "aes",
236 .ID = 6,
237 .min_key_length = 16,
238 .max_key_length = 32,
239 .block_length = 16,
240 .default_rounds = 10,
241 .setup = rijndael_setup,
242 .ecb_encrypt = rijndael_ecb_encrypt,
243 .ecb_decrypt = rijndael_ecb_decrypt,
244 .done = rijndael_done,
245 .keysize = rijndael_keysize,
246 .accel_ecb_encrypt = aes_ecb_encrypt_nblocks,
247 .accel_ecb_decrypt = aes_ecb_decrypt_nblocks,
248 .accel_cbc_encrypt = aes_cbc_encrypt_nblocks,
249 .accel_cbc_decrypt = aes_cbc_decrypt_nblocks,
250 #ifdef LTC_CTR_MODE
251 .accel_ctr_encrypt = aes_ctr_encrypt_nblocks,
252 #endif
253 .accel_xts_encrypt = aes_xts_encrypt_nblocks,
254 .accel_xts_decrypt = aes_xts_decrypt_nblocks,
255 };
256