1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * AEAD: Authenticated Encryption with Associated Data 4 * 5 * This file provides API support for AEAD algorithms. 6 * 7 * Copyright (c) 2007-2015 Herbert Xu <herbert@gondor.apana.org.au> 8 */ 9 10 #include <crypto/internal/aead.h> 11 #include <linux/errno.h> 12 #include <linux/init.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 #include <linux/seq_file.h> 17 #include <linux/cryptouser.h> 18 #include <net/netlink.h> 19 20 #include "internal.h" 21 22 static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, 23 unsigned int keylen) 24 { 25 unsigned long alignmask = crypto_aead_alignmask(tfm); 26 int ret; 27 u8 *buffer, *alignbuffer; 28 unsigned long absize; 29 30 absize = keylen + alignmask; 31 buffer = kmalloc(absize, GFP_ATOMIC); 32 if (!buffer) 33 return -ENOMEM; 34 35 alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); 36 memcpy(alignbuffer, key, keylen); 37 ret = crypto_aead_alg(tfm)->setkey(tfm, alignbuffer, keylen); 38 memset(alignbuffer, 0, keylen); 39 kfree(buffer); 40 return ret; 41 } 42 43 int crypto_aead_setkey(struct crypto_aead *tfm, 44 const u8 *key, unsigned int keylen) 45 { 46 unsigned long alignmask = crypto_aead_alignmask(tfm); 47 int err; 48 49 if ((unsigned long)key & alignmask) 50 err = setkey_unaligned(tfm, key, keylen); 51 else 52 err = crypto_aead_alg(tfm)->setkey(tfm, key, keylen); 53 54 if (unlikely(err)) { 55 crypto_aead_set_flags(tfm, CRYPTO_TFM_NEED_KEY); 56 return err; 57 } 58 59 crypto_aead_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); 60 return 0; 61 } 62 EXPORT_SYMBOL_GPL(crypto_aead_setkey); 63 64 int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 65 { 66 int err; 67 68 if ((!authsize && crypto_aead_maxauthsize(tfm)) || 69 authsize > crypto_aead_maxauthsize(tfm)) 70 return -EINVAL; 71 72 if (crypto_aead_alg(tfm)->setauthsize) { 73 err = crypto_aead_alg(tfm)->setauthsize(tfm, authsize); 74 if (err) 75 return err; 76 } 77 78 tfm->authsize = authsize; 79 return 0; 80 } 81 EXPORT_SYMBOL_GPL(crypto_aead_setauthsize); 82 83 int crypto_aead_encrypt(struct aead_request *req) 84 { 85 struct crypto_aead *aead = crypto_aead_reqtfm(req); 86 struct crypto_alg *alg = aead->base.__crt_alg; 87 unsigned int cryptlen = req->cryptlen; 88 int ret; 89 90 crypto_stats_get(alg); 91 if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY) 92 ret = -ENOKEY; 93 else 94 ret = crypto_aead_alg(aead)->encrypt(req); 95 crypto_stats_aead_encrypt(cryptlen, alg, ret); 96 return ret; 97 } 98 EXPORT_SYMBOL_GPL(crypto_aead_encrypt); 99 100 int crypto_aead_decrypt(struct aead_request *req) 101 { 102 struct crypto_aead *aead = crypto_aead_reqtfm(req); 103 struct crypto_alg *alg = aead->base.__crt_alg; 104 unsigned int cryptlen = req->cryptlen; 105 int ret; 106 107 crypto_stats_get(alg); 108 if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY) 109 ret = -ENOKEY; 110 else if (req->cryptlen < crypto_aead_authsize(aead)) 111 ret = -EINVAL; 112 else 113 ret = crypto_aead_alg(aead)->decrypt(req); 114 crypto_stats_aead_decrypt(cryptlen, alg, ret); 115 return ret; 116 } 117 EXPORT_SYMBOL_GPL(crypto_aead_decrypt); 118 119 static void crypto_aead_exit_tfm(struct crypto_tfm *tfm) 120 { 121 struct crypto_aead *aead = __crypto_aead_cast(tfm); 122 struct aead_alg *alg = crypto_aead_alg(aead); 123 124 alg->exit(aead); 125 } 126 127 static int crypto_aead_init_tfm(struct crypto_tfm *tfm) 128 { 129 struct crypto_aead *aead = __crypto_aead_cast(tfm); 130 struct aead_alg *alg = crypto_aead_alg(aead); 131 132 crypto_aead_set_flags(aead, CRYPTO_TFM_NEED_KEY); 133 134 aead->authsize = alg->maxauthsize; 135 136 if (alg->exit) 137 aead->base.exit = crypto_aead_exit_tfm; 138 139 if (alg->init) 140 return alg->init(aead); 141 142 return 0; 143 } 144 145 #ifdef CONFIG_NET 146 static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) 147 { 148 struct crypto_report_aead raead; 149 struct aead_alg *aead = container_of(alg, struct aead_alg, base); 150 151 memset(&raead, 0, sizeof(raead)); 152 153 strscpy(raead.type, "aead", sizeof(raead.type)); 154 strscpy(raead.geniv, "<none>", sizeof(raead.geniv)); 155 156 raead.blocksize = alg->cra_blocksize; 157 raead.maxauthsize = aead->maxauthsize; 158 raead.ivsize = aead->ivsize; 159 160 return nla_put(skb, CRYPTOCFGA_REPORT_AEAD, sizeof(raead), &raead); 161 } 162 #else 163 static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) 164 { 165 return -ENOSYS; 166 } 167 #endif 168 169 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) 170 __maybe_unused; 171 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) 172 { 173 struct aead_alg *aead = container_of(alg, struct aead_alg, base); 174 175 seq_printf(m, "type : aead\n"); 176 seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? 177 "yes" : "no"); 178 seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 179 seq_printf(m, "ivsize : %u\n", aead->ivsize); 180 seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); 181 seq_printf(m, "geniv : <none>\n"); 182 } 183 184 static void crypto_aead_free_instance(struct crypto_instance *inst) 185 { 186 struct aead_instance *aead = aead_instance(inst); 187 188 if (!aead->free) { 189 inst->tmpl->free(inst); 190 return; 191 } 192 193 aead->free(aead); 194 } 195 196 static const struct crypto_type crypto_aead_type = { 197 .extsize = crypto_alg_extsize, 198 .init_tfm = crypto_aead_init_tfm, 199 .free = crypto_aead_free_instance, 200 #ifdef CONFIG_PROC_FS 201 .show = crypto_aead_show, 202 #endif 203 .report = crypto_aead_report, 204 .maskclear = ~CRYPTO_ALG_TYPE_MASK, 205 .maskset = CRYPTO_ALG_TYPE_MASK, 206 .type = CRYPTO_ALG_TYPE_AEAD, 207 .tfmsize = offsetof(struct crypto_aead, base), 208 }; 209 210 int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, 211 u32 type, u32 mask) 212 { 213 spawn->base.frontend = &crypto_aead_type; 214 return crypto_grab_spawn(&spawn->base, name, type, mask); 215 } 216 EXPORT_SYMBOL_GPL(crypto_grab_aead); 217 218 struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask) 219 { 220 return crypto_alloc_tfm(alg_name, &crypto_aead_type, type, mask); 221 } 222 EXPORT_SYMBOL_GPL(crypto_alloc_aead); 223 224 static int aead_prepare_alg(struct aead_alg *alg) 225 { 226 struct crypto_alg *base = &alg->base; 227 228 if (max3(alg->maxauthsize, alg->ivsize, alg->chunksize) > 229 PAGE_SIZE / 8) 230 return -EINVAL; 231 232 if (!alg->chunksize) 233 alg->chunksize = base->cra_blocksize; 234 235 base->cra_type = &crypto_aead_type; 236 base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; 237 base->cra_flags |= CRYPTO_ALG_TYPE_AEAD; 238 239 return 0; 240 } 241 242 int crypto_register_aead(struct aead_alg *alg) 243 { 244 struct crypto_alg *base = &alg->base; 245 int err; 246 247 err = aead_prepare_alg(alg); 248 if (err) 249 return err; 250 251 return crypto_register_alg(base); 252 } 253 EXPORT_SYMBOL_GPL(crypto_register_aead); 254 255 void crypto_unregister_aead(struct aead_alg *alg) 256 { 257 crypto_unregister_alg(&alg->base); 258 } 259 EXPORT_SYMBOL_GPL(crypto_unregister_aead); 260 261 int crypto_register_aeads(struct aead_alg *algs, int count) 262 { 263 int i, ret; 264 265 for (i = 0; i < count; i++) { 266 ret = crypto_register_aead(&algs[i]); 267 if (ret) 268 goto err; 269 } 270 271 return 0; 272 273 err: 274 for (--i; i >= 0; --i) 275 crypto_unregister_aead(&algs[i]); 276 277 return ret; 278 } 279 EXPORT_SYMBOL_GPL(crypto_register_aeads); 280 281 void crypto_unregister_aeads(struct aead_alg *algs, int count) 282 { 283 int i; 284 285 for (i = count - 1; i >= 0; --i) 286 crypto_unregister_aead(&algs[i]); 287 } 288 EXPORT_SYMBOL_GPL(crypto_unregister_aeads); 289 290 int aead_register_instance(struct crypto_template *tmpl, 291 struct aead_instance *inst) 292 { 293 int err; 294 295 err = aead_prepare_alg(&inst->alg); 296 if (err) 297 return err; 298 299 return crypto_register_instance(tmpl, aead_crypto_instance(inst)); 300 } 301 EXPORT_SYMBOL_GPL(aead_register_instance); 302 303 MODULE_LICENSE("GPL"); 304 MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); 305