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 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 77 void rijndael_done(symmetric_key *skey __unused) 78 { 79 } 80 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 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 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 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 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 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 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 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 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 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