1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Crypto API support for AES block cipher 4 * 5 * Copyright 2026 Google LLC 6 */ 7 8 #include <crypto/aes-cbc-macs.h> 9 #include <crypto/aes.h> 10 #include <crypto/algapi.h> 11 #include <crypto/internal/hash.h> 12 #include <linux/module.h> 13 14 static_assert(__alignof__(struct aes_key) <= CRYPTO_MINALIGN); 15 16 static int crypto_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, 17 unsigned int key_len) 18 { 19 struct aes_key *key = crypto_tfm_ctx(tfm); 20 21 return aes_preparekey(key, in_key, key_len); 22 } 23 24 static void crypto_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 25 { 26 const struct aes_key *key = crypto_tfm_ctx(tfm); 27 28 aes_encrypt(key, out, in); 29 } 30 31 static void crypto_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 32 { 33 const struct aes_key *key = crypto_tfm_ctx(tfm); 34 35 aes_decrypt(key, out, in); 36 } 37 38 static_assert(__alignof__(struct aes_cmac_key) <= CRYPTO_MINALIGN); 39 #define AES_CMAC_KEY(tfm) ((struct aes_cmac_key *)crypto_shash_ctx(tfm)) 40 #define AES_CMAC_CTX(desc) ((struct aes_cmac_ctx *)shash_desc_ctx(desc)) 41 42 static int __maybe_unused crypto_aes_cmac_setkey(struct crypto_shash *tfm, 43 const u8 *in_key, 44 unsigned int key_len) 45 { 46 return aes_cmac_preparekey(AES_CMAC_KEY(tfm), in_key, key_len); 47 } 48 49 static int __maybe_unused crypto_aes_xcbc_setkey(struct crypto_shash *tfm, 50 const u8 *in_key, 51 unsigned int key_len) 52 { 53 if (key_len != AES_KEYSIZE_128) 54 return -EINVAL; 55 aes_xcbcmac_preparekey(AES_CMAC_KEY(tfm), in_key); 56 return 0; 57 } 58 59 static int __maybe_unused crypto_aes_cmac_init(struct shash_desc *desc) 60 { 61 aes_cmac_init(AES_CMAC_CTX(desc), AES_CMAC_KEY(desc->tfm)); 62 return 0; 63 } 64 65 static int __maybe_unused crypto_aes_cmac_update(struct shash_desc *desc, 66 const u8 *data, 67 unsigned int len) 68 { 69 aes_cmac_update(AES_CMAC_CTX(desc), data, len); 70 return 0; 71 } 72 73 static int __maybe_unused crypto_aes_cmac_final(struct shash_desc *desc, 74 u8 *out) 75 { 76 aes_cmac_final(AES_CMAC_CTX(desc), out); 77 return 0; 78 } 79 80 static int __maybe_unused crypto_aes_cmac_digest(struct shash_desc *desc, 81 const u8 *data, 82 unsigned int len, u8 *out) 83 { 84 aes_cmac(AES_CMAC_KEY(desc->tfm), data, len, out); 85 return 0; 86 } 87 88 static_assert(__alignof__(struct aes_enckey) <= CRYPTO_MINALIGN); 89 #define AES_CBCMAC_KEY(tfm) ((struct aes_enckey *)crypto_shash_ctx(tfm)) 90 #define AES_CBCMAC_CTX(desc) ((struct aes_cbcmac_ctx *)shash_desc_ctx(desc)) 91 92 static int __maybe_unused crypto_aes_cbcmac_setkey(struct crypto_shash *tfm, 93 const u8 *in_key, 94 unsigned int key_len) 95 { 96 return aes_prepareenckey(AES_CBCMAC_KEY(tfm), in_key, key_len); 97 } 98 99 static int __maybe_unused crypto_aes_cbcmac_init(struct shash_desc *desc) 100 { 101 aes_cbcmac_init(AES_CBCMAC_CTX(desc), AES_CBCMAC_KEY(desc->tfm)); 102 return 0; 103 } 104 105 static int __maybe_unused crypto_aes_cbcmac_update(struct shash_desc *desc, 106 const u8 *data, 107 unsigned int len) 108 { 109 aes_cbcmac_update(AES_CBCMAC_CTX(desc), data, len); 110 return 0; 111 } 112 113 static int __maybe_unused crypto_aes_cbcmac_final(struct shash_desc *desc, 114 u8 *out) 115 { 116 aes_cbcmac_final(AES_CBCMAC_CTX(desc), out); 117 return 0; 118 } 119 120 static int __maybe_unused crypto_aes_cbcmac_digest(struct shash_desc *desc, 121 const u8 *data, 122 unsigned int len, u8 *out) 123 { 124 aes_cbcmac_init(AES_CBCMAC_CTX(desc), AES_CBCMAC_KEY(desc->tfm)); 125 aes_cbcmac_update(AES_CBCMAC_CTX(desc), data, len); 126 aes_cbcmac_final(AES_CBCMAC_CTX(desc), out); 127 return 0; 128 } 129 130 static struct crypto_alg alg = { 131 .cra_name = "aes", 132 .cra_driver_name = "aes-lib", 133 .cra_priority = 100, 134 .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 135 .cra_blocksize = AES_BLOCK_SIZE, 136 .cra_ctxsize = sizeof(struct aes_key), 137 .cra_module = THIS_MODULE, 138 .cra_u = { .cipher = { .cia_min_keysize = AES_MIN_KEY_SIZE, 139 .cia_max_keysize = AES_MAX_KEY_SIZE, 140 .cia_setkey = crypto_aes_setkey, 141 .cia_encrypt = crypto_aes_encrypt, 142 .cia_decrypt = crypto_aes_decrypt } } 143 }; 144 145 static struct shash_alg mac_algs[] = { 146 #if IS_ENABLED(CONFIG_CRYPTO_CMAC) 147 { 148 .base.cra_name = "cmac(aes)", 149 .base.cra_driver_name = "cmac-aes-lib", 150 .base.cra_priority = 300, 151 .base.cra_blocksize = AES_BLOCK_SIZE, 152 .base.cra_ctxsize = sizeof(struct aes_cmac_key), 153 .base.cra_module = THIS_MODULE, 154 .digestsize = AES_BLOCK_SIZE, 155 .setkey = crypto_aes_cmac_setkey, 156 .init = crypto_aes_cmac_init, 157 .update = crypto_aes_cmac_update, 158 .final = crypto_aes_cmac_final, 159 .digest = crypto_aes_cmac_digest, 160 .descsize = sizeof(struct aes_cmac_ctx), 161 }, 162 #endif 163 #if IS_ENABLED(CONFIG_CRYPTO_XCBC) 164 { 165 /* 166 * Note that the only difference between xcbc(aes) and cmac(aes) 167 * is the preparekey function. 168 */ 169 .base.cra_name = "xcbc(aes)", 170 .base.cra_driver_name = "xcbc-aes-lib", 171 .base.cra_priority = 300, 172 .base.cra_blocksize = AES_BLOCK_SIZE, 173 .base.cra_ctxsize = sizeof(struct aes_cmac_key), 174 .base.cra_module = THIS_MODULE, 175 .digestsize = AES_BLOCK_SIZE, 176 .setkey = crypto_aes_xcbc_setkey, 177 .init = crypto_aes_cmac_init, 178 .update = crypto_aes_cmac_update, 179 .final = crypto_aes_cmac_final, 180 .digest = crypto_aes_cmac_digest, 181 .descsize = sizeof(struct aes_cmac_ctx), 182 }, 183 #endif 184 #if IS_ENABLED(CONFIG_CRYPTO_CCM) 185 { 186 .base.cra_name = "cbcmac(aes)", 187 .base.cra_driver_name = "cbcmac-aes-lib", 188 .base.cra_priority = 300, 189 .base.cra_blocksize = AES_BLOCK_SIZE, 190 .base.cra_ctxsize = sizeof(struct aes_enckey), 191 .base.cra_module = THIS_MODULE, 192 .digestsize = AES_BLOCK_SIZE, 193 .setkey = crypto_aes_cbcmac_setkey, 194 .init = crypto_aes_cbcmac_init, 195 .update = crypto_aes_cbcmac_update, 196 .final = crypto_aes_cbcmac_final, 197 .digest = crypto_aes_cbcmac_digest, 198 .descsize = sizeof(struct aes_cbcmac_ctx), 199 }, 200 #endif 201 }; 202 203 static int __init crypto_aes_mod_init(void) 204 { 205 int err = crypto_register_alg(&alg); 206 207 if (err) 208 return err; 209 210 if (ARRAY_SIZE(mac_algs) > 0) { 211 err = crypto_register_shashes(mac_algs, ARRAY_SIZE(mac_algs)); 212 if (err) 213 goto err_unregister_alg; 214 } /* Else, CONFIG_CRYPTO_HASH might not be enabled. */ 215 return 0; 216 217 err_unregister_alg: 218 crypto_unregister_alg(&alg); 219 return err; 220 } 221 module_init(crypto_aes_mod_init); 222 223 static void __exit crypto_aes_mod_exit(void) 224 { 225 if (ARRAY_SIZE(mac_algs) > 0) 226 crypto_unregister_shashes(mac_algs, ARRAY_SIZE(mac_algs)); 227 crypto_unregister_alg(&alg); 228 } 229 module_exit(crypto_aes_mod_exit); 230 231 MODULE_DESCRIPTION("Crypto API support for AES block cipher"); 232 MODULE_IMPORT_NS("CRYPTO_INTERNAL"); 233 MODULE_LICENSE("GPL"); 234 MODULE_ALIAS_CRYPTO("aes"); 235 MODULE_ALIAS_CRYPTO("aes-lib"); 236 #if IS_ENABLED(CONFIG_CRYPTO_CMAC) 237 MODULE_ALIAS_CRYPTO("cmac(aes)"); 238 MODULE_ALIAS_CRYPTO("cmac-aes-lib"); 239 #endif 240 #if IS_ENABLED(CONFIG_CRYPTO_XCBC) 241 MODULE_ALIAS_CRYPTO("xcbc(aes)"); 242 MODULE_ALIAS_CRYPTO("xcbc-aes-lib"); 243 #endif 244 #if IS_ENABLED(CONFIG_CRYPTO_CCM) 245 MODULE_ALIAS_CRYPTO("cbcmac(aes)"); 246 MODULE_ALIAS_CRYPTO("cbcmac-aes-lib"); 247 #endif 248