Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 75971
b: refs/heads/master
c: 7f47073
h: refs/heads/master
i:
  75969: 7f8c9f2
  75967: 4b4532c
v: v3
  • Loading branch information
Herbert Xu committed Jan 10, 2008
1 parent ad5c854 commit c7fb1f3
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ecfc43292f68566c144afca966b46b371c26d56c
refs/heads/master: 7f47073911f0e4384d38a0827d28305a177c8816
1 change: 1 addition & 0 deletions trunk/crypto/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ obj-$(CONFIG_CRYPTO_AEAD) += aead.o
crypto_blkcipher-objs := ablkcipher.o
crypto_blkcipher-objs += blkcipher.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o

crypto_hash-objs := hash.o
obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
Expand Down
139 changes: 139 additions & 0 deletions trunk/crypto/chainiv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* chainiv: Chain IV Generator
*
* Generate IVs simply be using the last block of the previous encryption.
* This is mainly useful for CBC with a synchronous algorithm.
*
* 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.
*
*/

#include <crypto/internal/skcipher.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/random.h>
#include <linux/spinlock.h>
#include <linux/string.h>

struct chainiv_ctx {
spinlock_t lock;
char iv[];
};

static int chainiv_givencrypt(struct skcipher_givcrypt_request *req)
{
struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
unsigned int ivsize;
int err;

ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
ablkcipher_request_set_callback(subreq, req->creq.base.flags &
~CRYPTO_TFM_REQ_MAY_SLEEP,
req->creq.base.complete,
req->creq.base.data);
ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
req->creq.nbytes, req->creq.info);

spin_lock_bh(&ctx->lock);

ivsize = crypto_ablkcipher_ivsize(geniv);

memcpy(req->giv, ctx->iv, ivsize);
memcpy(subreq->info, ctx->iv, ivsize);

err = crypto_ablkcipher_encrypt(subreq);
if (err)
goto unlock;

memcpy(ctx->iv, subreq->info, ivsize);

unlock:
spin_unlock_bh(&ctx->lock);

return err;
}

static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
{
struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);

spin_lock_bh(&ctx->lock);
if (crypto_ablkcipher_crt(geniv)->givencrypt !=
chainiv_givencrypt_first)
goto unlock;

crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt;
get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));

unlock:
spin_unlock_bh(&ctx->lock);

return chainiv_givencrypt(req);
}

static int chainiv_init(struct crypto_tfm *tfm)
{
struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);

spin_lock_init(&ctx->lock);

tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);

return skcipher_geniv_init(tfm);
}

static struct crypto_template chainiv_tmpl;

static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
{
struct crypto_instance *inst;

inst = skcipher_geniv_alloc(&chainiv_tmpl, tb, 0,
CRYPTO_ALG_ASYNC);
if (IS_ERR(inst))
goto out;

inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt_first;

inst->alg.cra_init = chainiv_init;
inst->alg.cra_exit = skcipher_geniv_exit;

inst->alg.cra_ctxsize = sizeof(struct chainiv_ctx) +
inst->alg.cra_ablkcipher.ivsize;

out:
return inst;
}

static struct crypto_template chainiv_tmpl = {
.name = "chainiv",
.alloc = chainiv_alloc,
.free = skcipher_geniv_free,
.module = THIS_MODULE,
};

static int __init chainiv_module_init(void)
{
return crypto_register_template(&chainiv_tmpl);
}

static void __exit chainiv_module_exit(void)
{
crypto_unregister_template(&chainiv_tmpl);
}

module_init(chainiv_module_init);
module_exit(chainiv_module_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Chain IV Generator");

0 comments on commit c7fb1f3

Please sign in to comment.