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 151ae97820SHerbert Xu #include <crypto/algapi.h> 161ae97820SHerbert Xu #include <linux/errno.h> 171ae97820SHerbert Xu #include <linux/init.h> 181ae97820SHerbert Xu #include <linux/kernel.h> 191ae97820SHerbert Xu #include <linux/module.h> 201ae97820SHerbert Xu #include <linux/slab.h> 211ae97820SHerbert Xu #include <linux/seq_file.h> 221ae97820SHerbert Xu 231ae97820SHerbert Xu static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, 241ae97820SHerbert Xu unsigned int keylen) 251ae97820SHerbert Xu { 261ae97820SHerbert Xu struct aead_alg *aead = crypto_aead_alg(tfm); 271ae97820SHerbert Xu unsigned long alignmask = crypto_aead_alignmask(tfm); 281ae97820SHerbert Xu int ret; 291ae97820SHerbert Xu u8 *buffer, *alignbuffer; 301ae97820SHerbert Xu unsigned long absize; 311ae97820SHerbert Xu 321ae97820SHerbert Xu absize = keylen + alignmask; 331ae97820SHerbert Xu buffer = kmalloc(absize, GFP_ATOMIC); 341ae97820SHerbert Xu if (!buffer) 351ae97820SHerbert Xu return -ENOMEM; 361ae97820SHerbert Xu 371ae97820SHerbert Xu alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); 381ae97820SHerbert Xu memcpy(alignbuffer, key, keylen); 391ae97820SHerbert Xu ret = aead->setkey(tfm, alignbuffer, keylen); 401ae97820SHerbert Xu memset(alignbuffer, 0, keylen); 411ae97820SHerbert Xu kfree(buffer); 421ae97820SHerbert Xu return ret; 431ae97820SHerbert Xu } 441ae97820SHerbert Xu 451ae97820SHerbert Xu static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) 461ae97820SHerbert Xu { 471ae97820SHerbert Xu struct aead_alg *aead = crypto_aead_alg(tfm); 481ae97820SHerbert Xu unsigned long alignmask = crypto_aead_alignmask(tfm); 491ae97820SHerbert Xu 501ae97820SHerbert Xu if ((unsigned long)key & alignmask) 511ae97820SHerbert Xu return setkey_unaligned(tfm, key, keylen); 521ae97820SHerbert Xu 531ae97820SHerbert Xu return aead->setkey(tfm, key, keylen); 541ae97820SHerbert Xu } 551ae97820SHerbert Xu 56*7ba683a6SHerbert Xu int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 57*7ba683a6SHerbert Xu { 58*7ba683a6SHerbert Xu int err; 59*7ba683a6SHerbert Xu 60*7ba683a6SHerbert Xu if (authsize > crypto_aead_alg(tfm)->maxauthsize) 61*7ba683a6SHerbert Xu return -EINVAL; 62*7ba683a6SHerbert Xu 63*7ba683a6SHerbert Xu if (crypto_aead_alg(tfm)->setauthsize) { 64*7ba683a6SHerbert Xu err = crypto_aead_alg(tfm)->setauthsize(tfm, authsize); 65*7ba683a6SHerbert Xu if (err) 66*7ba683a6SHerbert Xu return err; 67*7ba683a6SHerbert Xu } 68*7ba683a6SHerbert Xu 69*7ba683a6SHerbert Xu crypto_aead_crt(tfm)->authsize = authsize; 70*7ba683a6SHerbert Xu return 0; 71*7ba683a6SHerbert Xu } 72*7ba683a6SHerbert Xu EXPORT_SYMBOL_GPL(crypto_aead_setauthsize); 73*7ba683a6SHerbert Xu 741ae97820SHerbert Xu static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type, 751ae97820SHerbert Xu u32 mask) 761ae97820SHerbert Xu { 771ae97820SHerbert Xu return alg->cra_ctxsize; 781ae97820SHerbert Xu } 791ae97820SHerbert Xu 801ae97820SHerbert Xu static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask) 811ae97820SHerbert Xu { 821ae97820SHerbert Xu struct aead_alg *alg = &tfm->__crt_alg->cra_aead; 831ae97820SHerbert Xu struct aead_tfm *crt = &tfm->crt_aead; 841ae97820SHerbert Xu 85*7ba683a6SHerbert Xu if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) 861ae97820SHerbert Xu return -EINVAL; 871ae97820SHerbert Xu 881ae97820SHerbert Xu crt->setkey = setkey; 891ae97820SHerbert Xu crt->encrypt = alg->encrypt; 901ae97820SHerbert Xu crt->decrypt = alg->decrypt; 911ae97820SHerbert Xu crt->ivsize = alg->ivsize; 92*7ba683a6SHerbert Xu crt->authsize = alg->maxauthsize; 931ae97820SHerbert Xu 941ae97820SHerbert Xu return 0; 951ae97820SHerbert Xu } 961ae97820SHerbert Xu 971ae97820SHerbert Xu static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) 981ae97820SHerbert Xu __attribute__ ((unused)); 991ae97820SHerbert Xu static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) 1001ae97820SHerbert Xu { 1011ae97820SHerbert Xu struct aead_alg *aead = &alg->cra_aead; 1021ae97820SHerbert Xu 1031ae97820SHerbert Xu seq_printf(m, "type : aead\n"); 1041ae97820SHerbert Xu seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 1051ae97820SHerbert Xu seq_printf(m, "ivsize : %u\n", aead->ivsize); 106*7ba683a6SHerbert Xu seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); 1071ae97820SHerbert Xu } 1081ae97820SHerbert Xu 1091ae97820SHerbert Xu const struct crypto_type crypto_aead_type = { 1101ae97820SHerbert Xu .ctxsize = crypto_aead_ctxsize, 1111ae97820SHerbert Xu .init = crypto_init_aead_ops, 1121ae97820SHerbert Xu #ifdef CONFIG_PROC_FS 1131ae97820SHerbert Xu .show = crypto_aead_show, 1141ae97820SHerbert Xu #endif 1151ae97820SHerbert Xu }; 1161ae97820SHerbert Xu EXPORT_SYMBOL_GPL(crypto_aead_type); 1171ae97820SHerbert Xu 1181ae97820SHerbert Xu MODULE_LICENSE("GPL"); 1191ae97820SHerbert Xu MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); 120