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 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 84 void rijndael_done(symmetric_key *skey __unused) 85 { 86 } 87 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 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 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 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 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 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 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 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 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 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