Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 75985
b: refs/heads/master
c: 5b6d2d7
h: refs/heads/master
i:
  75983: 39c560b
v: v3
  • Loading branch information
Herbert Xu committed Jan 10, 2008
1 parent d15bcfe commit 7159b77
Show file tree
Hide file tree
Showing 4 changed files with 298 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: aedb30dc49eeecd48558b601c47e0b3f9e42c602
refs/heads/master: 5b6d2d7fdf806f2b5a9352416f9e670911fc4748
216 changes: 211 additions & 5 deletions trunk/crypto/aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@
*
*/

#include <crypto/algapi.h>
#include <linux/errno.h>
#include <crypto/internal/aead.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/seq_file.h>

#include "internal.h"

static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen)
{
Expand Down Expand Up @@ -55,18 +57,20 @@ static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)

int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
{
struct aead_tfm *crt = crypto_aead_crt(tfm);
int err;

if (authsize > crypto_aead_alg(tfm)->maxauthsize)
return -EINVAL;

if (crypto_aead_alg(tfm)->setauthsize) {
err = crypto_aead_alg(tfm)->setauthsize(tfm, authsize);
err = crypto_aead_alg(tfm)->setauthsize(crt->base, authsize);
if (err)
return err;
}

crypto_aead_crt(tfm)->authsize = authsize;
crypto_aead_crt(crt->base)->authsize = authsize;
crt->authsize = authsize;
return 0;
}
EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
Expand All @@ -90,11 +94,13 @@ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
return -EINVAL;

crt->setkey = setkey;
crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ?
alg->setkey : setkey;
crt->encrypt = alg->encrypt;
crt->decrypt = alg->decrypt;
crt->givencrypt = alg->givencrypt ?: no_givcrypt;
crt->givdecrypt = alg->givdecrypt ?: no_givcrypt;
crt->base = __crypto_aead_cast(tfm);
crt->ivsize = alg->ivsize;
crt->authsize = alg->maxauthsize;

Expand All @@ -111,6 +117,7 @@ static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "ivsize : %u\n", aead->ivsize);
seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize);
seq_printf(m, "geniv : %s\n", aead->geniv ?: "<built-in>");
}

const struct crypto_type crypto_aead_type = {
Expand All @@ -122,5 +129,204 @@ const struct crypto_type crypto_aead_type = {
};
EXPORT_SYMBOL_GPL(crypto_aead_type);

static int aead_null_givencrypt(struct aead_givcrypt_request *req)
{
return crypto_aead_encrypt(&req->areq);
}

static int aead_null_givdecrypt(struct aead_givcrypt_request *req)
{
return crypto_aead_decrypt(&req->areq);
}

static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
{
struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
struct aead_tfm *crt = &tfm->crt_aead;

if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
return -EINVAL;

crt->setkey = setkey;
crt->encrypt = alg->encrypt;
crt->decrypt = alg->decrypt;
if (!alg->ivsize) {
crt->givencrypt = aead_null_givencrypt;
crt->givdecrypt = aead_null_givdecrypt;
}
crt->base = __crypto_aead_cast(tfm);
crt->ivsize = alg->ivsize;
crt->authsize = alg->maxauthsize;

return 0;
}

static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
__attribute__ ((unused));
static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
{
struct aead_alg *aead = &alg->cra_aead;

seq_printf(m, "type : nivaead\n");
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "ivsize : %u\n", aead->ivsize);
seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize);
seq_printf(m, "geniv : %s\n", aead->geniv);
}

const struct crypto_type crypto_nivaead_type = {
.ctxsize = crypto_aead_ctxsize,
.init = crypto_init_nivaead_ops,
#ifdef CONFIG_PROC_FS
.show = crypto_nivaead_show,
#endif
};
EXPORT_SYMBOL_GPL(crypto_nivaead_type);

static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn,
const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;
int err;

type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
type |= CRYPTO_ALG_TYPE_AEAD;
mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV;

alg = crypto_alg_mod_lookup(name, type, mask);
if (IS_ERR(alg))
return PTR_ERR(alg);

err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
crypto_mod_put(alg);
return err;
}

struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
struct rtattr **tb, u32 type,
u32 mask)
{
const char *name;
struct crypto_aead_spawn *spawn;
struct crypto_attr_type *algt;
struct crypto_instance *inst;
struct crypto_alg *alg;
int err;

algt = crypto_get_attr_type(tb);
err = PTR_ERR(algt);
if (IS_ERR(algt))
return ERR_PTR(err);

if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) &
algt->mask)
return ERR_PTR(-EINVAL);

name = crypto_attr_alg_name(tb[1]);
err = PTR_ERR(name);
if (IS_ERR(name))
return ERR_PTR(err);

inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
if (!inst)
return ERR_PTR(-ENOMEM);

spawn = crypto_instance_ctx(inst);

/* Ignore async algorithms if necessary. */
mask |= crypto_requires_sync(algt->type, algt->mask);

crypto_set_aead_spawn(spawn, inst);
err = crypto_grab_nivaead(spawn, name, type, mask);
if (err)
goto err_free_inst;

alg = crypto_aead_spawn_alg(spawn);

err = -EINVAL;
if (!alg->cra_aead.ivsize)
goto err_drop_alg;

/*
* This is only true if we're constructing an algorithm with its
* default IV generator. For the default generator we elide the
* template name and double-check the IV generator.
*/
if (algt->mask & CRYPTO_ALG_GENIV) {
if (strcmp(tmpl->name, alg->cra_aead.geniv))
goto err_drop_alg;

memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
CRYPTO_MAX_ALG_NAME);
} else {
err = -ENAMETOOLONG;
if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
"%s(%s)", tmpl->name, alg->cra_name) >=
CRYPTO_MAX_ALG_NAME)
goto err_drop_alg;
if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
"%s(%s)", tmpl->name, alg->cra_driver_name) >=
CRYPTO_MAX_ALG_NAME)
goto err_drop_alg;
}

inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV;
inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
inst->alg.cra_priority = alg->cra_priority;
inst->alg.cra_blocksize = alg->cra_blocksize;
inst->alg.cra_alignmask = alg->cra_alignmask;
inst->alg.cra_type = &crypto_aead_type;

inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize;
inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize;
inst->alg.cra_aead.geniv = alg->cra_aead.geniv;

inst->alg.cra_aead.setkey = alg->cra_aead.setkey;
inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize;
inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt;
inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt;

out:
return inst;

err_drop_alg:
crypto_drop_aead(spawn);
err_free_inst:
kfree(inst);
inst = ERR_PTR(err);
goto out;
}
EXPORT_SYMBOL_GPL(aead_geniv_alloc);

void aead_geniv_free(struct crypto_instance *inst)
{
crypto_drop_aead(crypto_instance_ctx(inst));
kfree(inst);
}
EXPORT_SYMBOL_GPL(aead_geniv_free);

int aead_geniv_init(struct crypto_tfm *tfm)
{
struct crypto_instance *inst = (void *)tfm->__crt_alg;
struct crypto_aead *aead;

aead = crypto_spawn_aead(crypto_instance_ctx(inst));
if (IS_ERR(aead))
return PTR_ERR(aead);

tfm->crt_aead.base = aead;
tfm->crt_aead.reqsize += crypto_aead_reqsize(aead);

return 0;
}
EXPORT_SYMBOL_GPL(aead_geniv_init);

void aead_geniv_exit(struct crypto_tfm *tfm)
{
crypto_free_aead(tfm->crt_aead.base);
}
EXPORT_SYMBOL_GPL(aead_geniv_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
77 changes: 77 additions & 0 deletions trunk/include/crypto/internal/aead.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* AEAD: Authenticated Encryption with Associated Data
*
* Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
*/

#ifndef _CRYPTO_INTERNAL_AEAD_H
#define _CRYPTO_INTERNAL_AEAD_H

#include <crypto/aead.h>
#include <crypto/algapi.h>
#include <linux/types.h>

struct rtattr;

struct crypto_aead_spawn {
struct crypto_spawn base;
};

extern const struct crypto_type crypto_nivaead_type;

static inline void crypto_set_aead_spawn(
struct crypto_aead_spawn *spawn, struct crypto_instance *inst)
{
crypto_set_spawn(&spawn->base, inst);
}

static inline void crypto_drop_aead(struct crypto_aead_spawn *spawn)
{
crypto_drop_spawn(&spawn->base);
}

static inline struct crypto_alg *crypto_aead_spawn_alg(
struct crypto_aead_spawn *spawn)
{
return spawn->base.alg;
}

static inline struct crypto_aead *crypto_spawn_aead(
struct crypto_aead_spawn *spawn)
{
return __crypto_aead_cast(
crypto_spawn_tfm(&spawn->base, CRYPTO_ALG_TYPE_AEAD,
CRYPTO_ALG_TYPE_MASK));
}

struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
struct rtattr **tb, u32 type,
u32 mask);
void aead_geniv_free(struct crypto_instance *inst);
int aead_geniv_init(struct crypto_tfm *tfm);
void aead_geniv_exit(struct crypto_tfm *tfm);

static inline struct crypto_aead *aead_geniv_base(struct crypto_aead *geniv)
{
return crypto_aead_crt(geniv)->base;
}

static inline void *aead_givcrypt_reqctx(struct aead_givcrypt_request *req)
{
return aead_request_ctx(&req->areq);
}

static inline void aead_givcrypt_complete(struct aead_givcrypt_request *req,
int err)
{
aead_request_complete(&req->areq, err);
}

#endif /* _CRYPTO_INTERNAL_AEAD_H */

11 changes: 9 additions & 2 deletions trunk/include/linux/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ struct aead_alg {
int (*givencrypt)(struct aead_givcrypt_request *req);
int (*givdecrypt)(struct aead_givcrypt_request *req);

const char *geniv;

unsigned int ivsize;
unsigned int maxauthsize;
};
Expand Down Expand Up @@ -353,6 +355,9 @@ struct aead_tfm {
int (*decrypt)(struct aead_request *req);
int (*givencrypt)(struct aead_givcrypt_request *req);
int (*givdecrypt)(struct aead_givcrypt_request *req);

struct crypto_aead *base;

unsigned int ivsize;
unsigned int authsize;
unsigned int reqsize;
Expand Down Expand Up @@ -781,7 +786,9 @@ static inline void crypto_aead_clear_flags(struct crypto_aead *tfm, u32 flags)
static inline int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen)
{
return crypto_aead_crt(tfm)->setkey(tfm, key, keylen);
struct aead_tfm *crt = crypto_aead_crt(tfm);

return crt->setkey(crt->base, key, keylen);
}

int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize);
Expand Down Expand Up @@ -809,7 +816,7 @@ static inline unsigned int crypto_aead_reqsize(struct crypto_aead *tfm)
static inline void aead_request_set_tfm(struct aead_request *req,
struct crypto_aead *tfm)
{
req->base.tfm = crypto_aead_tfm(tfm);
req->base.tfm = crypto_aead_tfm(crypto_aead_crt(tfm)->base);
}

static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm,
Expand Down

0 comments on commit 7159b77

Please sign in to comment.