11ae97820SHerbert Xu /* 21ae97820SHerbert Xu * AEAD: Authenticated Encryption with Associated Data 31ae97820SHerbert Xu * 41ae97820SHerbert Xu * This file provides API support for AEAD algorithms. 51ae97820SHerbert Xu * 61ae97820SHerbert Xu * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au> 71ae97820SHerbert Xu * 81ae97820SHerbert Xu * This program is free software; you can redistribute it and/or modify it 91ae97820SHerbert Xu * under the terms of the GNU General Public License as published by the Free 101ae97820SHerbert Xu * Software Foundation; either version 2 of the License, or (at your option) 111ae97820SHerbert Xu * any later version. 121ae97820SHerbert Xu * 131ae97820SHerbert Xu */ 141ae97820SHerbert Xu 155b6d2d7fSHerbert Xu #include <crypto/internal/aead.h> 165b6d2d7fSHerbert Xu #include <linux/err.h> 171ae97820SHerbert Xu #include <linux/init.h> 181ae97820SHerbert Xu #include <linux/kernel.h> 191ae97820SHerbert Xu #include <linux/module.h> 20d29ce988SHerbert Xu #include <linux/rtnetlink.h> 21d43c36dcSAlexey Dobriyan #include <linux/sched.h> 221ae97820SHerbert Xu #include <linux/slab.h> 231ae97820SHerbert Xu #include <linux/seq_file.h> 246ad414feSSteffen Klassert #include <linux/cryptouser.h> 256ad414feSSteffen Klassert #include <net/netlink.h> 261ae97820SHerbert Xu 275b6d2d7fSHerbert Xu #include "internal.h" 285b6d2d7fSHerbert Xu 291ae97820SHerbert Xu static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, 301ae97820SHerbert Xu unsigned int keylen) 311ae97820SHerbert Xu { 321ae97820SHerbert Xu struct aead_alg *aead = crypto_aead_alg(tfm); 331ae97820SHerbert Xu unsigned long alignmask = crypto_aead_alignmask(tfm); 341ae97820SHerbert Xu int ret; 351ae97820SHerbert Xu u8 *buffer, *alignbuffer; 361ae97820SHerbert Xu unsigned long absize; 371ae97820SHerbert Xu 381ae97820SHerbert Xu absize = keylen + alignmask; 391ae97820SHerbert Xu buffer = kmalloc(absize, GFP_ATOMIC); 401ae97820SHerbert Xu if (!buffer) 411ae97820SHerbert Xu return -ENOMEM; 421ae97820SHerbert Xu 431ae97820SHerbert Xu alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); 441ae97820SHerbert Xu memcpy(alignbuffer, key, keylen); 451ae97820SHerbert Xu ret = aead->setkey(tfm, alignbuffer, keylen); 461ae97820SHerbert Xu memset(alignbuffer, 0, keylen); 471ae97820SHerbert Xu kfree(buffer); 481ae97820SHerbert Xu return ret; 491ae97820SHerbert Xu } 501ae97820SHerbert Xu 511ae97820SHerbert Xu static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) 521ae97820SHerbert Xu { 531ae97820SHerbert Xu struct aead_alg *aead = crypto_aead_alg(tfm); 541ae97820SHerbert Xu unsigned long alignmask = crypto_aead_alignmask(tfm); 551ae97820SHerbert Xu 561ae97820SHerbert Xu if ((unsigned long)key & alignmask) 571ae97820SHerbert Xu return setkey_unaligned(tfm, key, keylen); 581ae97820SHerbert Xu 591ae97820SHerbert Xu return aead->setkey(tfm, key, keylen); 601ae97820SHerbert Xu } 611ae97820SHerbert Xu 627ba683a6SHerbert Xu int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 637ba683a6SHerbert Xu { 645b6d2d7fSHerbert Xu struct aead_tfm *crt = crypto_aead_crt(tfm); 657ba683a6SHerbert Xu int err; 667ba683a6SHerbert Xu 677ba683a6SHerbert Xu if (authsize > crypto_aead_alg(tfm)->maxauthsize) 687ba683a6SHerbert Xu return -EINVAL; 697ba683a6SHerbert Xu 707ba683a6SHerbert Xu if (crypto_aead_alg(tfm)->setauthsize) { 715b6d2d7fSHerbert Xu err = crypto_aead_alg(tfm)->setauthsize(crt->base, authsize); 727ba683a6SHerbert Xu if (err) 737ba683a6SHerbert Xu return err; 747ba683a6SHerbert Xu } 757ba683a6SHerbert Xu 765b6d2d7fSHerbert Xu crypto_aead_crt(crt->base)->authsize = authsize; 775b6d2d7fSHerbert Xu crt->authsize = authsize; 787ba683a6SHerbert Xu return 0; 797ba683a6SHerbert Xu } 807ba683a6SHerbert Xu EXPORT_SYMBOL_GPL(crypto_aead_setauthsize); 817ba683a6SHerbert Xu 821ae97820SHerbert Xu static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type, 831ae97820SHerbert Xu u32 mask) 841ae97820SHerbert Xu { 851ae97820SHerbert Xu return alg->cra_ctxsize; 861ae97820SHerbert Xu } 871ae97820SHerbert Xu 88aedb30dcSHerbert Xu static int no_givcrypt(struct aead_givcrypt_request *req) 89743edf57SHerbert Xu { 90743edf57SHerbert Xu return -ENOSYS; 91743edf57SHerbert Xu } 92743edf57SHerbert Xu 931ae97820SHerbert Xu static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask) 941ae97820SHerbert Xu { 951ae97820SHerbert Xu struct aead_alg *alg = &tfm->__crt_alg->cra_aead; 961ae97820SHerbert Xu struct aead_tfm *crt = &tfm->crt_aead; 971ae97820SHerbert Xu 987ba683a6SHerbert Xu if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) 991ae97820SHerbert Xu return -EINVAL; 1001ae97820SHerbert Xu 1015b6d2d7fSHerbert Xu crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ? 1025b6d2d7fSHerbert Xu alg->setkey : setkey; 1031ae97820SHerbert Xu crt->encrypt = alg->encrypt; 1041ae97820SHerbert Xu crt->decrypt = alg->decrypt; 105aedb30dcSHerbert Xu crt->givencrypt = alg->givencrypt ?: no_givcrypt; 106aedb30dcSHerbert Xu crt->givdecrypt = alg->givdecrypt ?: no_givcrypt; 1075b6d2d7fSHerbert Xu crt->base = __crypto_aead_cast(tfm); 1081ae97820SHerbert Xu crt->ivsize = alg->ivsize; 1097ba683a6SHerbert Xu crt->authsize = alg->maxauthsize; 1101ae97820SHerbert Xu 1111ae97820SHerbert Xu return 0; 1121ae97820SHerbert Xu } 1131ae97820SHerbert Xu 1143acc8473SHerbert Xu #ifdef CONFIG_NET 1156ad414feSSteffen Klassert static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) 1166ad414feSSteffen Klassert { 1176ad414feSSteffen Klassert struct crypto_report_aead raead; 1186ad414feSSteffen Klassert struct aead_alg *aead = &alg->cra_aead; 1196ad414feSSteffen Klassert 120*9a5467bfSMathias Krause strncpy(raead.type, "aead", sizeof(raead.type)); 121*9a5467bfSMathias Krause strncpy(raead.geniv, aead->geniv ?: "<built-in>", sizeof(raead.geniv)); 1226ad414feSSteffen Klassert 1236ad414feSSteffen Klassert raead.blocksize = alg->cra_blocksize; 1246ad414feSSteffen Klassert raead.maxauthsize = aead->maxauthsize; 1256ad414feSSteffen Klassert raead.ivsize = aead->ivsize; 1266ad414feSSteffen Klassert 1276662df33SDavid S. Miller if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD, 1286662df33SDavid S. Miller sizeof(struct crypto_report_aead), &raead)) 1296662df33SDavid S. Miller goto nla_put_failure; 1306ad414feSSteffen Klassert return 0; 1316ad414feSSteffen Klassert 1326ad414feSSteffen Klassert nla_put_failure: 1336ad414feSSteffen Klassert return -EMSGSIZE; 1346ad414feSSteffen Klassert } 1353acc8473SHerbert Xu #else 1363acc8473SHerbert Xu static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) 1373acc8473SHerbert Xu { 1383acc8473SHerbert Xu return -ENOSYS; 1393acc8473SHerbert Xu } 1403acc8473SHerbert Xu #endif 1416ad414feSSteffen Klassert 1421ae97820SHerbert Xu static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) 1431ae97820SHerbert Xu __attribute__ ((unused)); 1441ae97820SHerbert Xu static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) 1451ae97820SHerbert Xu { 1461ae97820SHerbert Xu struct aead_alg *aead = &alg->cra_aead; 1471ae97820SHerbert Xu 1481ae97820SHerbert Xu seq_printf(m, "type : aead\n"); 149189ed66eSHerbert Xu seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? 150189ed66eSHerbert Xu "yes" : "no"); 1511ae97820SHerbert Xu seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 1521ae97820SHerbert Xu seq_printf(m, "ivsize : %u\n", aead->ivsize); 1537ba683a6SHerbert Xu seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); 1545b6d2d7fSHerbert Xu seq_printf(m, "geniv : %s\n", aead->geniv ?: "<built-in>"); 1551ae97820SHerbert Xu } 1561ae97820SHerbert Xu 1571ae97820SHerbert Xu const struct crypto_type crypto_aead_type = { 1581ae97820SHerbert Xu .ctxsize = crypto_aead_ctxsize, 1591ae97820SHerbert Xu .init = crypto_init_aead_ops, 1601ae97820SHerbert Xu #ifdef CONFIG_PROC_FS 1611ae97820SHerbert Xu .show = crypto_aead_show, 1621ae97820SHerbert Xu #endif 1636ad414feSSteffen Klassert .report = crypto_aead_report, 1641ae97820SHerbert Xu }; 1651ae97820SHerbert Xu EXPORT_SYMBOL_GPL(crypto_aead_type); 1661ae97820SHerbert Xu 1675b6d2d7fSHerbert Xu static int aead_null_givencrypt(struct aead_givcrypt_request *req) 1685b6d2d7fSHerbert Xu { 1695b6d2d7fSHerbert Xu return crypto_aead_encrypt(&req->areq); 1705b6d2d7fSHerbert Xu } 1715b6d2d7fSHerbert Xu 1725b6d2d7fSHerbert Xu static int aead_null_givdecrypt(struct aead_givcrypt_request *req) 1735b6d2d7fSHerbert Xu { 1745b6d2d7fSHerbert Xu return crypto_aead_decrypt(&req->areq); 1755b6d2d7fSHerbert Xu } 1765b6d2d7fSHerbert Xu 1775b6d2d7fSHerbert Xu static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask) 1785b6d2d7fSHerbert Xu { 1795b6d2d7fSHerbert Xu struct aead_alg *alg = &tfm->__crt_alg->cra_aead; 1805b6d2d7fSHerbert Xu struct aead_tfm *crt = &tfm->crt_aead; 1815b6d2d7fSHerbert Xu 1825b6d2d7fSHerbert Xu if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) 1835b6d2d7fSHerbert Xu return -EINVAL; 1845b6d2d7fSHerbert Xu 1855b6d2d7fSHerbert Xu crt->setkey = setkey; 1865b6d2d7fSHerbert Xu crt->encrypt = alg->encrypt; 1875b6d2d7fSHerbert Xu crt->decrypt = alg->decrypt; 1885b6d2d7fSHerbert Xu if (!alg->ivsize) { 1895b6d2d7fSHerbert Xu crt->givencrypt = aead_null_givencrypt; 1905b6d2d7fSHerbert Xu crt->givdecrypt = aead_null_givdecrypt; 1915b6d2d7fSHerbert Xu } 1925b6d2d7fSHerbert Xu crt->base = __crypto_aead_cast(tfm); 1935b6d2d7fSHerbert Xu crt->ivsize = alg->ivsize; 1945b6d2d7fSHerbert Xu crt->authsize = alg->maxauthsize; 1955b6d2d7fSHerbert Xu 1965b6d2d7fSHerbert Xu return 0; 1975b6d2d7fSHerbert Xu } 1985b6d2d7fSHerbert Xu 1993acc8473SHerbert Xu #ifdef CONFIG_NET 200b735d0a9SSteffen Klassert static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg) 201b735d0a9SSteffen Klassert { 202b735d0a9SSteffen Klassert struct crypto_report_aead raead; 203b735d0a9SSteffen Klassert struct aead_alg *aead = &alg->cra_aead; 204b735d0a9SSteffen Klassert 205*9a5467bfSMathias Krause strncpy(raead.type, "nivaead", sizeof(raead.type)); 206*9a5467bfSMathias Krause strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv)); 207b735d0a9SSteffen Klassert 208b735d0a9SSteffen Klassert raead.blocksize = alg->cra_blocksize; 209b735d0a9SSteffen Klassert raead.maxauthsize = aead->maxauthsize; 210b735d0a9SSteffen Klassert raead.ivsize = aead->ivsize; 211b735d0a9SSteffen Klassert 2126662df33SDavid S. Miller if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD, 2136662df33SDavid S. Miller sizeof(struct crypto_report_aead), &raead)) 2146662df33SDavid S. Miller goto nla_put_failure; 215b735d0a9SSteffen Klassert return 0; 216b735d0a9SSteffen Klassert 217b735d0a9SSteffen Klassert nla_put_failure: 218b735d0a9SSteffen Klassert return -EMSGSIZE; 219b735d0a9SSteffen Klassert } 2203acc8473SHerbert Xu #else 2213acc8473SHerbert Xu static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg) 2223acc8473SHerbert Xu { 2233acc8473SHerbert Xu return -ENOSYS; 2243acc8473SHerbert Xu } 2253acc8473SHerbert Xu #endif 226b735d0a9SSteffen Klassert 227b735d0a9SSteffen Klassert 2285b6d2d7fSHerbert Xu static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg) 2295b6d2d7fSHerbert Xu __attribute__ ((unused)); 2305b6d2d7fSHerbert Xu static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg) 2315b6d2d7fSHerbert Xu { 2325b6d2d7fSHerbert Xu struct aead_alg *aead = &alg->cra_aead; 2335b6d2d7fSHerbert Xu 2345b6d2d7fSHerbert Xu seq_printf(m, "type : nivaead\n"); 235189ed66eSHerbert Xu seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? 236189ed66eSHerbert Xu "yes" : "no"); 2375b6d2d7fSHerbert Xu seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 2385b6d2d7fSHerbert Xu seq_printf(m, "ivsize : %u\n", aead->ivsize); 2395b6d2d7fSHerbert Xu seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); 2405b6d2d7fSHerbert Xu seq_printf(m, "geniv : %s\n", aead->geniv); 2415b6d2d7fSHerbert Xu } 2425b6d2d7fSHerbert Xu 2435b6d2d7fSHerbert Xu const struct crypto_type crypto_nivaead_type = { 2445b6d2d7fSHerbert Xu .ctxsize = crypto_aead_ctxsize, 2455b6d2d7fSHerbert Xu .init = crypto_init_nivaead_ops, 2465b6d2d7fSHerbert Xu #ifdef CONFIG_PROC_FS 2475b6d2d7fSHerbert Xu .show = crypto_nivaead_show, 2485b6d2d7fSHerbert Xu #endif 249b735d0a9SSteffen Klassert .report = crypto_nivaead_report, 2505b6d2d7fSHerbert Xu }; 2515b6d2d7fSHerbert Xu EXPORT_SYMBOL_GPL(crypto_nivaead_type); 2525b6d2d7fSHerbert Xu 2535b6d2d7fSHerbert Xu static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn, 2545b6d2d7fSHerbert Xu const char *name, u32 type, u32 mask) 2555b6d2d7fSHerbert Xu { 2565b6d2d7fSHerbert Xu struct crypto_alg *alg; 2575b6d2d7fSHerbert Xu int err; 2585b6d2d7fSHerbert Xu 2595b6d2d7fSHerbert Xu type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); 2605b6d2d7fSHerbert Xu type |= CRYPTO_ALG_TYPE_AEAD; 2615b6d2d7fSHerbert Xu mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV; 2625b6d2d7fSHerbert Xu 2635b6d2d7fSHerbert Xu alg = crypto_alg_mod_lookup(name, type, mask); 2645b6d2d7fSHerbert Xu if (IS_ERR(alg)) 2655b6d2d7fSHerbert Xu return PTR_ERR(alg); 2665b6d2d7fSHerbert Xu 2675b6d2d7fSHerbert Xu err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask); 2685b6d2d7fSHerbert Xu crypto_mod_put(alg); 2695b6d2d7fSHerbert Xu return err; 2705b6d2d7fSHerbert Xu } 2715b6d2d7fSHerbert Xu 2725b6d2d7fSHerbert Xu struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl, 2735b6d2d7fSHerbert Xu struct rtattr **tb, u32 type, 2745b6d2d7fSHerbert Xu u32 mask) 2755b6d2d7fSHerbert Xu { 2765b6d2d7fSHerbert Xu const char *name; 2775b6d2d7fSHerbert Xu struct crypto_aead_spawn *spawn; 2785b6d2d7fSHerbert Xu struct crypto_attr_type *algt; 2795b6d2d7fSHerbert Xu struct crypto_instance *inst; 2805b6d2d7fSHerbert Xu struct crypto_alg *alg; 2815b6d2d7fSHerbert Xu int err; 2825b6d2d7fSHerbert Xu 2835b6d2d7fSHerbert Xu algt = crypto_get_attr_type(tb); 2845b6d2d7fSHerbert Xu if (IS_ERR(algt)) 2853e8afe35SJulia Lawall return ERR_CAST(algt); 2865b6d2d7fSHerbert Xu 2875b6d2d7fSHerbert Xu if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) & 2885b6d2d7fSHerbert Xu algt->mask) 2895b6d2d7fSHerbert Xu return ERR_PTR(-EINVAL); 2905b6d2d7fSHerbert Xu 2915b6d2d7fSHerbert Xu name = crypto_attr_alg_name(tb[1]); 2925b6d2d7fSHerbert Xu if (IS_ERR(name)) 2933e8afe35SJulia Lawall return ERR_CAST(name); 2945b6d2d7fSHerbert Xu 2955b6d2d7fSHerbert Xu inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 2965b6d2d7fSHerbert Xu if (!inst) 2975b6d2d7fSHerbert Xu return ERR_PTR(-ENOMEM); 2985b6d2d7fSHerbert Xu 2995b6d2d7fSHerbert Xu spawn = crypto_instance_ctx(inst); 3005b6d2d7fSHerbert Xu 3015b6d2d7fSHerbert Xu /* Ignore async algorithms if necessary. */ 3025b6d2d7fSHerbert Xu mask |= crypto_requires_sync(algt->type, algt->mask); 3035b6d2d7fSHerbert Xu 3045b6d2d7fSHerbert Xu crypto_set_aead_spawn(spawn, inst); 3055b6d2d7fSHerbert Xu err = crypto_grab_nivaead(spawn, name, type, mask); 3065b6d2d7fSHerbert Xu if (err) 3075b6d2d7fSHerbert Xu goto err_free_inst; 3085b6d2d7fSHerbert Xu 3095b6d2d7fSHerbert Xu alg = crypto_aead_spawn_alg(spawn); 3105b6d2d7fSHerbert Xu 3115b6d2d7fSHerbert Xu err = -EINVAL; 3125b6d2d7fSHerbert Xu if (!alg->cra_aead.ivsize) 3135b6d2d7fSHerbert Xu goto err_drop_alg; 3145b6d2d7fSHerbert Xu 3155b6d2d7fSHerbert Xu /* 3165b6d2d7fSHerbert Xu * This is only true if we're constructing an algorithm with its 3175b6d2d7fSHerbert Xu * default IV generator. For the default generator we elide the 3185b6d2d7fSHerbert Xu * template name and double-check the IV generator. 3195b6d2d7fSHerbert Xu */ 3205b6d2d7fSHerbert Xu if (algt->mask & CRYPTO_ALG_GENIV) { 3215b6d2d7fSHerbert Xu if (strcmp(tmpl->name, alg->cra_aead.geniv)) 3225b6d2d7fSHerbert Xu goto err_drop_alg; 3235b6d2d7fSHerbert Xu 3245b6d2d7fSHerbert Xu memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); 3255b6d2d7fSHerbert Xu memcpy(inst->alg.cra_driver_name, alg->cra_driver_name, 3265b6d2d7fSHerbert Xu CRYPTO_MAX_ALG_NAME); 3275b6d2d7fSHerbert Xu } else { 3285b6d2d7fSHerbert Xu err = -ENAMETOOLONG; 3295b6d2d7fSHerbert Xu if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, 3305b6d2d7fSHerbert Xu "%s(%s)", tmpl->name, alg->cra_name) >= 3315b6d2d7fSHerbert Xu CRYPTO_MAX_ALG_NAME) 3325b6d2d7fSHerbert Xu goto err_drop_alg; 3335b6d2d7fSHerbert Xu if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 3345b6d2d7fSHerbert Xu "%s(%s)", tmpl->name, alg->cra_driver_name) >= 3355b6d2d7fSHerbert Xu CRYPTO_MAX_ALG_NAME) 3365b6d2d7fSHerbert Xu goto err_drop_alg; 3375b6d2d7fSHerbert Xu } 3385b6d2d7fSHerbert Xu 3395b6d2d7fSHerbert Xu inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV; 3405b6d2d7fSHerbert Xu inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC; 3415b6d2d7fSHerbert Xu inst->alg.cra_priority = alg->cra_priority; 3425b6d2d7fSHerbert Xu inst->alg.cra_blocksize = alg->cra_blocksize; 3435b6d2d7fSHerbert Xu inst->alg.cra_alignmask = alg->cra_alignmask; 3445b6d2d7fSHerbert Xu inst->alg.cra_type = &crypto_aead_type; 3455b6d2d7fSHerbert Xu 3465b6d2d7fSHerbert Xu inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize; 3475b6d2d7fSHerbert Xu inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize; 3485b6d2d7fSHerbert Xu inst->alg.cra_aead.geniv = alg->cra_aead.geniv; 3495b6d2d7fSHerbert Xu 3505b6d2d7fSHerbert Xu inst->alg.cra_aead.setkey = alg->cra_aead.setkey; 3515b6d2d7fSHerbert Xu inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize; 3525b6d2d7fSHerbert Xu inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt; 3535b6d2d7fSHerbert Xu inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt; 3545b6d2d7fSHerbert Xu 3555b6d2d7fSHerbert Xu out: 3565b6d2d7fSHerbert Xu return inst; 3575b6d2d7fSHerbert Xu 3585b6d2d7fSHerbert Xu err_drop_alg: 3595b6d2d7fSHerbert Xu crypto_drop_aead(spawn); 3605b6d2d7fSHerbert Xu err_free_inst: 3615b6d2d7fSHerbert Xu kfree(inst); 3625b6d2d7fSHerbert Xu inst = ERR_PTR(err); 3635b6d2d7fSHerbert Xu goto out; 3645b6d2d7fSHerbert Xu } 3655b6d2d7fSHerbert Xu EXPORT_SYMBOL_GPL(aead_geniv_alloc); 3665b6d2d7fSHerbert Xu 3675b6d2d7fSHerbert Xu void aead_geniv_free(struct crypto_instance *inst) 3685b6d2d7fSHerbert Xu { 3695b6d2d7fSHerbert Xu crypto_drop_aead(crypto_instance_ctx(inst)); 3705b6d2d7fSHerbert Xu kfree(inst); 3715b6d2d7fSHerbert Xu } 3725b6d2d7fSHerbert Xu EXPORT_SYMBOL_GPL(aead_geniv_free); 3735b6d2d7fSHerbert Xu 3745b6d2d7fSHerbert Xu int aead_geniv_init(struct crypto_tfm *tfm) 3755b6d2d7fSHerbert Xu { 3765b6d2d7fSHerbert Xu struct crypto_instance *inst = (void *)tfm->__crt_alg; 3775b6d2d7fSHerbert Xu struct crypto_aead *aead; 3785b6d2d7fSHerbert Xu 3795b6d2d7fSHerbert Xu aead = crypto_spawn_aead(crypto_instance_ctx(inst)); 3805b6d2d7fSHerbert Xu if (IS_ERR(aead)) 3815b6d2d7fSHerbert Xu return PTR_ERR(aead); 3825b6d2d7fSHerbert Xu 3835b6d2d7fSHerbert Xu tfm->crt_aead.base = aead; 3845b6d2d7fSHerbert Xu tfm->crt_aead.reqsize += crypto_aead_reqsize(aead); 3855b6d2d7fSHerbert Xu 3865b6d2d7fSHerbert Xu return 0; 3875b6d2d7fSHerbert Xu } 3885b6d2d7fSHerbert Xu EXPORT_SYMBOL_GPL(aead_geniv_init); 3895b6d2d7fSHerbert Xu 3905b6d2d7fSHerbert Xu void aead_geniv_exit(struct crypto_tfm *tfm) 3915b6d2d7fSHerbert Xu { 3925b6d2d7fSHerbert Xu crypto_free_aead(tfm->crt_aead.base); 3935b6d2d7fSHerbert Xu } 3945b6d2d7fSHerbert Xu EXPORT_SYMBOL_GPL(aead_geniv_exit); 3955b6d2d7fSHerbert Xu 396d29ce988SHerbert Xu static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask) 397d29ce988SHerbert Xu { 398d29ce988SHerbert Xu struct rtattr *tb[3]; 399d29ce988SHerbert Xu struct { 400d29ce988SHerbert Xu struct rtattr attr; 401d29ce988SHerbert Xu struct crypto_attr_type data; 402d29ce988SHerbert Xu } ptype; 403d29ce988SHerbert Xu struct { 404d29ce988SHerbert Xu struct rtattr attr; 405d29ce988SHerbert Xu struct crypto_attr_alg data; 406d29ce988SHerbert Xu } palg; 407d29ce988SHerbert Xu struct crypto_template *tmpl; 408d29ce988SHerbert Xu struct crypto_instance *inst; 409d29ce988SHerbert Xu struct crypto_alg *larval; 410d29ce988SHerbert Xu const char *geniv; 411d29ce988SHerbert Xu int err; 412d29ce988SHerbert Xu 413d29ce988SHerbert Xu larval = crypto_larval_lookup(alg->cra_driver_name, 414d29ce988SHerbert Xu CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV, 415d29ce988SHerbert Xu CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); 416d29ce988SHerbert Xu err = PTR_ERR(larval); 417d29ce988SHerbert Xu if (IS_ERR(larval)) 418d29ce988SHerbert Xu goto out; 419d29ce988SHerbert Xu 420d29ce988SHerbert Xu err = -EAGAIN; 421d29ce988SHerbert Xu if (!crypto_is_larval(larval)) 422d29ce988SHerbert Xu goto drop_larval; 423d29ce988SHerbert Xu 424d29ce988SHerbert Xu ptype.attr.rta_len = sizeof(ptype); 425d29ce988SHerbert Xu ptype.attr.rta_type = CRYPTOA_TYPE; 426d29ce988SHerbert Xu ptype.data.type = type | CRYPTO_ALG_GENIV; 427d29ce988SHerbert Xu /* GENIV tells the template that we're making a default geniv. */ 428d29ce988SHerbert Xu ptype.data.mask = mask | CRYPTO_ALG_GENIV; 429d29ce988SHerbert Xu tb[0] = &ptype.attr; 430d29ce988SHerbert Xu 431d29ce988SHerbert Xu palg.attr.rta_len = sizeof(palg); 432d29ce988SHerbert Xu palg.attr.rta_type = CRYPTOA_ALG; 433d29ce988SHerbert Xu /* Must use the exact name to locate ourselves. */ 434d29ce988SHerbert Xu memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME); 435d29ce988SHerbert Xu tb[1] = &palg.attr; 436d29ce988SHerbert Xu 437d29ce988SHerbert Xu tb[2] = NULL; 438d29ce988SHerbert Xu 439d29ce988SHerbert Xu geniv = alg->cra_aead.geniv; 440d29ce988SHerbert Xu 441d29ce988SHerbert Xu tmpl = crypto_lookup_template(geniv); 442d29ce988SHerbert Xu err = -ENOENT; 443d29ce988SHerbert Xu if (!tmpl) 444d29ce988SHerbert Xu goto kill_larval; 445d29ce988SHerbert Xu 446d29ce988SHerbert Xu inst = tmpl->alloc(tb); 447d29ce988SHerbert Xu err = PTR_ERR(inst); 448d29ce988SHerbert Xu if (IS_ERR(inst)) 449d29ce988SHerbert Xu goto put_tmpl; 450d29ce988SHerbert Xu 451d29ce988SHerbert Xu if ((err = crypto_register_instance(tmpl, inst))) { 452d29ce988SHerbert Xu tmpl->free(inst); 453d29ce988SHerbert Xu goto put_tmpl; 454d29ce988SHerbert Xu } 455d29ce988SHerbert Xu 456d29ce988SHerbert Xu /* Redo the lookup to use the instance we just registered. */ 457d29ce988SHerbert Xu err = -EAGAIN; 458d29ce988SHerbert Xu 459d29ce988SHerbert Xu put_tmpl: 460d29ce988SHerbert Xu crypto_tmpl_put(tmpl); 461d29ce988SHerbert Xu kill_larval: 462d29ce988SHerbert Xu crypto_larval_kill(larval); 463d29ce988SHerbert Xu drop_larval: 464d29ce988SHerbert Xu crypto_mod_put(larval); 465d29ce988SHerbert Xu out: 466d29ce988SHerbert Xu crypto_mod_put(alg); 467d29ce988SHerbert Xu return err; 468d29ce988SHerbert Xu } 469d29ce988SHerbert Xu 4701e122994SSteffen Klassert struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask) 471d29ce988SHerbert Xu { 472d29ce988SHerbert Xu struct crypto_alg *alg; 473d29ce988SHerbert Xu 474d29ce988SHerbert Xu alg = crypto_alg_mod_lookup(name, type, mask); 475d29ce988SHerbert Xu if (IS_ERR(alg)) 476d29ce988SHerbert Xu return alg; 477d29ce988SHerbert Xu 478d29ce988SHerbert Xu if (alg->cra_type == &crypto_aead_type) 479d29ce988SHerbert Xu return alg; 480d29ce988SHerbert Xu 481d29ce988SHerbert Xu if (!alg->cra_aead.ivsize) 482d29ce988SHerbert Xu return alg; 483d29ce988SHerbert Xu 4845852ae42SHerbert Xu crypto_mod_put(alg); 4855852ae42SHerbert Xu alg = crypto_alg_mod_lookup(name, type | CRYPTO_ALG_TESTED, 4865852ae42SHerbert Xu mask & ~CRYPTO_ALG_TESTED); 4875852ae42SHerbert Xu if (IS_ERR(alg)) 4885852ae42SHerbert Xu return alg; 4895852ae42SHerbert Xu 4905852ae42SHerbert Xu if (alg->cra_type == &crypto_aead_type) { 4915852ae42SHerbert Xu if ((alg->cra_flags ^ type ^ ~mask) & CRYPTO_ALG_TESTED) { 4925852ae42SHerbert Xu crypto_mod_put(alg); 4935852ae42SHerbert Xu alg = ERR_PTR(-ENOENT); 4945852ae42SHerbert Xu } 4955852ae42SHerbert Xu return alg; 4965852ae42SHerbert Xu } 4975852ae42SHerbert Xu 4985852ae42SHerbert Xu BUG_ON(!alg->cra_aead.ivsize); 4995852ae42SHerbert Xu 500d29ce988SHerbert Xu return ERR_PTR(crypto_nivaead_default(alg, type, mask)); 501d29ce988SHerbert Xu } 5021e122994SSteffen Klassert EXPORT_SYMBOL_GPL(crypto_lookup_aead); 503d29ce988SHerbert Xu 504d29ce988SHerbert Xu int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, 505d29ce988SHerbert Xu u32 type, u32 mask) 506d29ce988SHerbert Xu { 507d29ce988SHerbert Xu struct crypto_alg *alg; 508d29ce988SHerbert Xu int err; 509d29ce988SHerbert Xu 510d29ce988SHerbert Xu type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); 511d29ce988SHerbert Xu type |= CRYPTO_ALG_TYPE_AEAD; 512d29ce988SHerbert Xu mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); 513d29ce988SHerbert Xu mask |= CRYPTO_ALG_TYPE_MASK; 514d29ce988SHerbert Xu 515d29ce988SHerbert Xu alg = crypto_lookup_aead(name, type, mask); 516d29ce988SHerbert Xu if (IS_ERR(alg)) 517d29ce988SHerbert Xu return PTR_ERR(alg); 518d29ce988SHerbert Xu 519d29ce988SHerbert Xu err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask); 520d29ce988SHerbert Xu crypto_mod_put(alg); 521d29ce988SHerbert Xu return err; 522d29ce988SHerbert Xu } 523d29ce988SHerbert Xu EXPORT_SYMBOL_GPL(crypto_grab_aead); 524d29ce988SHerbert Xu 525d29ce988SHerbert Xu struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask) 526d29ce988SHerbert Xu { 527d29ce988SHerbert Xu struct crypto_tfm *tfm; 528d29ce988SHerbert Xu int err; 529d29ce988SHerbert Xu 530d29ce988SHerbert Xu type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); 531d29ce988SHerbert Xu type |= CRYPTO_ALG_TYPE_AEAD; 532d29ce988SHerbert Xu mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); 533d29ce988SHerbert Xu mask |= CRYPTO_ALG_TYPE_MASK; 534d29ce988SHerbert Xu 535d29ce988SHerbert Xu for (;;) { 536d29ce988SHerbert Xu struct crypto_alg *alg; 537d29ce988SHerbert Xu 538d29ce988SHerbert Xu alg = crypto_lookup_aead(alg_name, type, mask); 539d29ce988SHerbert Xu if (IS_ERR(alg)) { 540d29ce988SHerbert Xu err = PTR_ERR(alg); 541d29ce988SHerbert Xu goto err; 542d29ce988SHerbert Xu } 543d29ce988SHerbert Xu 544d29ce988SHerbert Xu tfm = __crypto_alloc_tfm(alg, type, mask); 545d29ce988SHerbert Xu if (!IS_ERR(tfm)) 546d29ce988SHerbert Xu return __crypto_aead_cast(tfm); 547d29ce988SHerbert Xu 548d29ce988SHerbert Xu crypto_mod_put(alg); 549d29ce988SHerbert Xu err = PTR_ERR(tfm); 550d29ce988SHerbert Xu 551d29ce988SHerbert Xu err: 552d29ce988SHerbert Xu if (err != -EAGAIN) 553d29ce988SHerbert Xu break; 554d29ce988SHerbert Xu if (signal_pending(current)) { 555d29ce988SHerbert Xu err = -EINTR; 556d29ce988SHerbert Xu break; 557d29ce988SHerbert Xu } 558d29ce988SHerbert Xu } 559d29ce988SHerbert Xu 560d29ce988SHerbert Xu return ERR_PTR(err); 561d29ce988SHerbert Xu } 562d29ce988SHerbert Xu EXPORT_SYMBOL_GPL(crypto_alloc_aead); 563d29ce988SHerbert Xu 5641ae97820SHerbert Xu MODULE_LICENSE("GPL"); 5651ae97820SHerbert Xu MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); 566