0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <crypto/internal/aead.h>
0011 #include <linux/errno.h>
0012 #include <linux/init.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016 #include <linux/seq_file.h>
0017 #include <linux/cryptouser.h>
0018 #include <net/netlink.h>
0019
0020 #include "internal.h"
0021
0022 static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
0023 unsigned int keylen)
0024 {
0025 unsigned long alignmask = crypto_aead_alignmask(tfm);
0026 int ret;
0027 u8 *buffer, *alignbuffer;
0028 unsigned long absize;
0029
0030 absize = keylen + alignmask;
0031 buffer = kmalloc(absize, GFP_ATOMIC);
0032 if (!buffer)
0033 return -ENOMEM;
0034
0035 alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
0036 memcpy(alignbuffer, key, keylen);
0037 ret = crypto_aead_alg(tfm)->setkey(tfm, alignbuffer, keylen);
0038 memset(alignbuffer, 0, keylen);
0039 kfree(buffer);
0040 return ret;
0041 }
0042
0043 int crypto_aead_setkey(struct crypto_aead *tfm,
0044 const u8 *key, unsigned int keylen)
0045 {
0046 unsigned long alignmask = crypto_aead_alignmask(tfm);
0047 int err;
0048
0049 if ((unsigned long)key & alignmask)
0050 err = setkey_unaligned(tfm, key, keylen);
0051 else
0052 err = crypto_aead_alg(tfm)->setkey(tfm, key, keylen);
0053
0054 if (unlikely(err)) {
0055 crypto_aead_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
0056 return err;
0057 }
0058
0059 crypto_aead_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
0060 return 0;
0061 }
0062 EXPORT_SYMBOL_GPL(crypto_aead_setkey);
0063
0064 int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
0065 {
0066 int err;
0067
0068 if ((!authsize && crypto_aead_maxauthsize(tfm)) ||
0069 authsize > crypto_aead_maxauthsize(tfm))
0070 return -EINVAL;
0071
0072 if (crypto_aead_alg(tfm)->setauthsize) {
0073 err = crypto_aead_alg(tfm)->setauthsize(tfm, authsize);
0074 if (err)
0075 return err;
0076 }
0077
0078 tfm->authsize = authsize;
0079 return 0;
0080 }
0081 EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
0082
0083 int crypto_aead_encrypt(struct aead_request *req)
0084 {
0085 struct crypto_aead *aead = crypto_aead_reqtfm(req);
0086 struct crypto_alg *alg = aead->base.__crt_alg;
0087 unsigned int cryptlen = req->cryptlen;
0088 int ret;
0089
0090 crypto_stats_get(alg);
0091 if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
0092 ret = -ENOKEY;
0093 else
0094 ret = crypto_aead_alg(aead)->encrypt(req);
0095 crypto_stats_aead_encrypt(cryptlen, alg, ret);
0096 return ret;
0097 }
0098 EXPORT_SYMBOL_GPL(crypto_aead_encrypt);
0099
0100 int crypto_aead_decrypt(struct aead_request *req)
0101 {
0102 struct crypto_aead *aead = crypto_aead_reqtfm(req);
0103 struct crypto_alg *alg = aead->base.__crt_alg;
0104 unsigned int cryptlen = req->cryptlen;
0105 int ret;
0106
0107 crypto_stats_get(alg);
0108 if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
0109 ret = -ENOKEY;
0110 else if (req->cryptlen < crypto_aead_authsize(aead))
0111 ret = -EINVAL;
0112 else
0113 ret = crypto_aead_alg(aead)->decrypt(req);
0114 crypto_stats_aead_decrypt(cryptlen, alg, ret);
0115 return ret;
0116 }
0117 EXPORT_SYMBOL_GPL(crypto_aead_decrypt);
0118
0119 static void crypto_aead_exit_tfm(struct crypto_tfm *tfm)
0120 {
0121 struct crypto_aead *aead = __crypto_aead_cast(tfm);
0122 struct aead_alg *alg = crypto_aead_alg(aead);
0123
0124 alg->exit(aead);
0125 }
0126
0127 static int crypto_aead_init_tfm(struct crypto_tfm *tfm)
0128 {
0129 struct crypto_aead *aead = __crypto_aead_cast(tfm);
0130 struct aead_alg *alg = crypto_aead_alg(aead);
0131
0132 crypto_aead_set_flags(aead, CRYPTO_TFM_NEED_KEY);
0133
0134 aead->authsize = alg->maxauthsize;
0135
0136 if (alg->exit)
0137 aead->base.exit = crypto_aead_exit_tfm;
0138
0139 if (alg->init)
0140 return alg->init(aead);
0141
0142 return 0;
0143 }
0144
0145 #ifdef CONFIG_NET
0146 static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
0147 {
0148 struct crypto_report_aead raead;
0149 struct aead_alg *aead = container_of(alg, struct aead_alg, base);
0150
0151 memset(&raead, 0, sizeof(raead));
0152
0153 strscpy(raead.type, "aead", sizeof(raead.type));
0154 strscpy(raead.geniv, "<none>", sizeof(raead.geniv));
0155
0156 raead.blocksize = alg->cra_blocksize;
0157 raead.maxauthsize = aead->maxauthsize;
0158 raead.ivsize = aead->ivsize;
0159
0160 return nla_put(skb, CRYPTOCFGA_REPORT_AEAD, sizeof(raead), &raead);
0161 }
0162 #else
0163 static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
0164 {
0165 return -ENOSYS;
0166 }
0167 #endif
0168
0169 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
0170 __maybe_unused;
0171 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
0172 {
0173 struct aead_alg *aead = container_of(alg, struct aead_alg, base);
0174
0175 seq_printf(m, "type : aead\n");
0176 seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
0177 "yes" : "no");
0178 seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
0179 seq_printf(m, "ivsize : %u\n", aead->ivsize);
0180 seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize);
0181 seq_printf(m, "geniv : <none>\n");
0182 }
0183
0184 static void crypto_aead_free_instance(struct crypto_instance *inst)
0185 {
0186 struct aead_instance *aead = aead_instance(inst);
0187
0188 aead->free(aead);
0189 }
0190
0191 static const struct crypto_type crypto_aead_type = {
0192 .extsize = crypto_alg_extsize,
0193 .init_tfm = crypto_aead_init_tfm,
0194 .free = crypto_aead_free_instance,
0195 #ifdef CONFIG_PROC_FS
0196 .show = crypto_aead_show,
0197 #endif
0198 .report = crypto_aead_report,
0199 .maskclear = ~CRYPTO_ALG_TYPE_MASK,
0200 .maskset = CRYPTO_ALG_TYPE_MASK,
0201 .type = CRYPTO_ALG_TYPE_AEAD,
0202 .tfmsize = offsetof(struct crypto_aead, base),
0203 };
0204
0205 int crypto_grab_aead(struct crypto_aead_spawn *spawn,
0206 struct crypto_instance *inst,
0207 const char *name, u32 type, u32 mask)
0208 {
0209 spawn->base.frontend = &crypto_aead_type;
0210 return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
0211 }
0212 EXPORT_SYMBOL_GPL(crypto_grab_aead);
0213
0214 struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
0215 {
0216 return crypto_alloc_tfm(alg_name, &crypto_aead_type, type, mask);
0217 }
0218 EXPORT_SYMBOL_GPL(crypto_alloc_aead);
0219
0220 static int aead_prepare_alg(struct aead_alg *alg)
0221 {
0222 struct crypto_alg *base = &alg->base;
0223
0224 if (max3(alg->maxauthsize, alg->ivsize, alg->chunksize) >
0225 PAGE_SIZE / 8)
0226 return -EINVAL;
0227
0228 if (!alg->chunksize)
0229 alg->chunksize = base->cra_blocksize;
0230
0231 base->cra_type = &crypto_aead_type;
0232 base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
0233 base->cra_flags |= CRYPTO_ALG_TYPE_AEAD;
0234
0235 return 0;
0236 }
0237
0238 int crypto_register_aead(struct aead_alg *alg)
0239 {
0240 struct crypto_alg *base = &alg->base;
0241 int err;
0242
0243 err = aead_prepare_alg(alg);
0244 if (err)
0245 return err;
0246
0247 return crypto_register_alg(base);
0248 }
0249 EXPORT_SYMBOL_GPL(crypto_register_aead);
0250
0251 void crypto_unregister_aead(struct aead_alg *alg)
0252 {
0253 crypto_unregister_alg(&alg->base);
0254 }
0255 EXPORT_SYMBOL_GPL(crypto_unregister_aead);
0256
0257 int crypto_register_aeads(struct aead_alg *algs, int count)
0258 {
0259 int i, ret;
0260
0261 for (i = 0; i < count; i++) {
0262 ret = crypto_register_aead(&algs[i]);
0263 if (ret)
0264 goto err;
0265 }
0266
0267 return 0;
0268
0269 err:
0270 for (--i; i >= 0; --i)
0271 crypto_unregister_aead(&algs[i]);
0272
0273 return ret;
0274 }
0275 EXPORT_SYMBOL_GPL(crypto_register_aeads);
0276
0277 void crypto_unregister_aeads(struct aead_alg *algs, int count)
0278 {
0279 int i;
0280
0281 for (i = count - 1; i >= 0; --i)
0282 crypto_unregister_aead(&algs[i]);
0283 }
0284 EXPORT_SYMBOL_GPL(crypto_unregister_aeads);
0285
0286 int aead_register_instance(struct crypto_template *tmpl,
0287 struct aead_instance *inst)
0288 {
0289 int err;
0290
0291 if (WARN_ON(!inst->free))
0292 return -EINVAL;
0293
0294 err = aead_prepare_alg(&inst->alg);
0295 if (err)
0296 return err;
0297
0298 return crypto_register_instance(tmpl, aead_crypto_instance(inst));
0299 }
0300 EXPORT_SYMBOL_GPL(aead_register_instance);
0301
0302 MODULE_LICENSE("GPL");
0303 MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");