Skip to content

Commit

Permalink
Merge branch 'testing' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/klassert/ipsec-next

Steffen Klassert says:

====================
1) Add a statistic counter for invalid output states and
   remove a superfluous state valid check, from Li RongQing.

2) Probe for asynchronous block ciphers instead of synchronous block
   ciphers to make the asynchronous variants available even if no
   synchronous block ciphers are found, from Jussi Kivilinna.

3) Make rfc3686 asynchronous block cipher and make use of
   the new asynchronous variant, from Jussi Kivilinna.

4) Replace some rwlocks by rcu, from Cong Wang.

5) Remove some unused defines.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 23, 2013
2 parents 4c133c3 + 02bfd8e commit 93b9c1d
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 176 deletions.
37 changes: 0 additions & 37 deletions arch/x86/crypto/aesni-intel_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@
#include <linux/workqueue.h>
#include <linux/spinlock.h>

#if defined(CONFIG_CRYPTO_CTR) || defined(CONFIG_CRYPTO_CTR_MODULE)
#define HAS_CTR
#endif

#if defined(CONFIG_CRYPTO_PCBC) || defined(CONFIG_CRYPTO_PCBC_MODULE)
#define HAS_PCBC
#endif
Expand Down Expand Up @@ -395,12 +391,6 @@ static int ablk_ctr_init(struct crypto_tfm *tfm)
return ablk_init_common(tfm, "__driver-ctr-aes-aesni");
}

#ifdef HAS_CTR
static int ablk_rfc3686_ctr_init(struct crypto_tfm *tfm)
{
return ablk_init_common(tfm, "rfc3686(__driver-ctr-aes-aesni)");
}
#endif
#endif

#ifdef HAS_PCBC
Expand Down Expand Up @@ -1158,33 +1148,6 @@ static struct crypto_alg aesni_algs[] = { {
.maxauthsize = 16,
},
},
#ifdef HAS_CTR
}, {
.cra_name = "rfc3686(ctr(aes))",
.cra_driver_name = "rfc3686-ctr-aes-aesni",
.cra_priority = 400,
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize = 1,
.cra_ctxsize = sizeof(struct async_helper_ctx),
.cra_alignmask = 0,
.cra_type = &crypto_ablkcipher_type,
.cra_module = THIS_MODULE,
.cra_init = ablk_rfc3686_ctr_init,
.cra_exit = ablk_exit,
.cra_u = {
.ablkcipher = {
.min_keysize = AES_MIN_KEY_SIZE +
CTR_RFC3686_NONCE_SIZE,
.max_keysize = AES_MAX_KEY_SIZE +
CTR_RFC3686_NONCE_SIZE,
.ivsize = CTR_RFC3686_IV_SIZE,
.setkey = ablk_set_key,
.encrypt = ablk_encrypt,
.decrypt = ablk_decrypt,
.geniv = "seqiv",
},
},
#endif
#endif
#ifdef HAS_PCBC
}, {
Expand Down
173 changes: 110 additions & 63 deletions crypto/ctr.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <crypto/algapi.h>
#include <crypto/ctr.h>
#include <crypto/internal/skcipher.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
Expand All @@ -25,10 +26,15 @@ struct crypto_ctr_ctx {
};

struct crypto_rfc3686_ctx {
struct crypto_blkcipher *child;
struct crypto_ablkcipher *child;
u8 nonce[CTR_RFC3686_NONCE_SIZE];
};

struct crypto_rfc3686_req_ctx {
u8 iv[CTR_RFC3686_BLOCK_SIZE];
struct ablkcipher_request subreq CRYPTO_MINALIGN_ATTR;
};

static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key,
unsigned int keylen)
{
Expand Down Expand Up @@ -243,11 +249,11 @@ static struct crypto_template crypto_ctr_tmpl = {
.module = THIS_MODULE,
};

static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,
unsigned int keylen)
static int crypto_rfc3686_setkey(struct crypto_ablkcipher *parent,
const u8 *key, unsigned int keylen)
{
struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(parent);
struct crypto_blkcipher *child = ctx->child;
struct crypto_rfc3686_ctx *ctx = crypto_ablkcipher_ctx(parent);
struct crypto_ablkcipher *child = ctx->child;
int err;

/* the nonce is stored in bytes at end of key */
Expand All @@ -259,134 +265,175 @@ static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,

keylen -= CTR_RFC3686_NONCE_SIZE;

crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
CRYPTO_TFM_REQ_MASK);
err = crypto_blkcipher_setkey(child, key, keylen);
crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
CRYPTO_TFM_RES_MASK);
crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(parent) &
CRYPTO_TFM_REQ_MASK);
err = crypto_ablkcipher_setkey(child, key, keylen);
crypto_ablkcipher_set_flags(parent, crypto_ablkcipher_get_flags(child) &
CRYPTO_TFM_RES_MASK);

return err;
}

static int crypto_rfc3686_crypt(struct blkcipher_desc *desc,
struct scatterlist *dst,
struct scatterlist *src, unsigned int nbytes)
static int crypto_rfc3686_crypt(struct ablkcipher_request *req)
{
struct crypto_blkcipher *tfm = desc->tfm;
struct crypto_rfc3686_ctx *ctx = crypto_blkcipher_ctx(tfm);
struct crypto_blkcipher *child = ctx->child;
unsigned long alignmask = crypto_blkcipher_alignmask(tfm);
u8 ivblk[CTR_RFC3686_BLOCK_SIZE + alignmask];
u8 *iv = PTR_ALIGN(ivblk + 0, alignmask + 1);
u8 *info = desc->info;
int err;
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
struct crypto_rfc3686_ctx *ctx = crypto_ablkcipher_ctx(tfm);
struct crypto_ablkcipher *child = ctx->child;
unsigned long align = crypto_ablkcipher_alignmask(tfm);
struct crypto_rfc3686_req_ctx *rctx =
(void *)PTR_ALIGN((u8 *)ablkcipher_request_ctx(req), align + 1);
struct ablkcipher_request *subreq = &rctx->subreq;
u8 *iv = rctx->iv;

/* set up counter block */
memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE);
memcpy(iv + CTR_RFC3686_NONCE_SIZE, info, CTR_RFC3686_IV_SIZE);
memcpy(iv + CTR_RFC3686_NONCE_SIZE, req->info, CTR_RFC3686_IV_SIZE);

/* initialize counter portion of counter block */
*(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) =
cpu_to_be32(1);

desc->tfm = child;
desc->info = iv;
err = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
desc->tfm = tfm;
desc->info = info;
ablkcipher_request_set_tfm(subreq, child);
ablkcipher_request_set_callback(subreq, req->base.flags,
req->base.complete, req->base.data);
ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes,
iv);

return err;
return crypto_ablkcipher_encrypt(subreq);
}

static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm)
{
struct crypto_instance *inst = (void *)tfm->__crt_alg;
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
struct crypto_skcipher_spawn *spawn = crypto_instance_ctx(inst);
struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
struct crypto_blkcipher *cipher;
struct crypto_ablkcipher *cipher;
unsigned long align;

cipher = crypto_spawn_blkcipher(spawn);
cipher = crypto_spawn_skcipher(spawn);
if (IS_ERR(cipher))
return PTR_ERR(cipher);

ctx->child = cipher;

align = crypto_tfm_alg_alignmask(tfm);
align &= ~(crypto_tfm_ctx_alignment() - 1);
tfm->crt_ablkcipher.reqsize = align +
sizeof(struct crypto_rfc3686_req_ctx) +
crypto_ablkcipher_reqsize(cipher);

return 0;
}

static void crypto_rfc3686_exit_tfm(struct crypto_tfm *tfm)
{
struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);

crypto_free_blkcipher(ctx->child);
crypto_free_ablkcipher(ctx->child);
}

static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb)
{
struct crypto_attr_type *algt;
struct crypto_instance *inst;
struct crypto_alg *alg;
struct crypto_skcipher_spawn *spawn;
const char *cipher_name;
int err;

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

alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
CRYPTO_ALG_TYPE_MASK);
err = PTR_ERR(alg);
if (IS_ERR(alg))
if ((algt->type ^ CRYPTO_ALG_TYPE_BLKCIPHER) & algt->mask)
return ERR_PTR(-EINVAL);

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

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

spawn = crypto_instance_ctx(inst);

crypto_set_skcipher_spawn(spawn, inst);
err = crypto_grab_skcipher(spawn, cipher_name, 0,
crypto_requires_sync(algt->type,
algt->mask));
if (err)
goto err_free_inst;

alg = crypto_skcipher_spawn_alg(spawn);

/* We only support 16-byte blocks. */
err = -EINVAL;
if (alg->cra_blkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
goto out_put_alg;
if (alg->cra_ablkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
goto err_drop_spawn;

/* Not a stream cipher? */
if (alg->cra_blocksize != 1)
goto out_put_alg;
goto err_drop_spawn;

inst = crypto_alloc_instance("rfc3686", alg);
if (IS_ERR(inst))
goto out;
err = -ENAMETOOLONG;
if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "rfc3686(%s)",
alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
goto err_drop_spawn;
if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
"rfc3686(%s)", alg->cra_driver_name) >=
CRYPTO_MAX_ALG_NAME)
goto err_drop_spawn;

inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
inst->alg.cra_priority = alg->cra_priority;
inst->alg.cra_blocksize = 1;
inst->alg.cra_alignmask = alg->cra_alignmask;
inst->alg.cra_type = &crypto_blkcipher_type;

inst->alg.cra_blkcipher.ivsize = CTR_RFC3686_IV_SIZE;
inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize
+ CTR_RFC3686_NONCE_SIZE;
inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize
+ CTR_RFC3686_NONCE_SIZE;
inst->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
(alg->cra_flags & CRYPTO_ALG_ASYNC);
inst->alg.cra_type = &crypto_ablkcipher_type;

inst->alg.cra_ablkcipher.ivsize = CTR_RFC3686_IV_SIZE;
inst->alg.cra_ablkcipher.min_keysize =
alg->cra_ablkcipher.min_keysize + CTR_RFC3686_NONCE_SIZE;
inst->alg.cra_ablkcipher.max_keysize =
alg->cra_ablkcipher.max_keysize + CTR_RFC3686_NONCE_SIZE;

inst->alg.cra_blkcipher.geniv = "seqiv";
inst->alg.cra_ablkcipher.geniv = "seqiv";

inst->alg.cra_ablkcipher.setkey = crypto_rfc3686_setkey;
inst->alg.cra_ablkcipher.encrypt = crypto_rfc3686_crypt;
inst->alg.cra_ablkcipher.decrypt = crypto_rfc3686_crypt;

inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx);

inst->alg.cra_init = crypto_rfc3686_init_tfm;
inst->alg.cra_exit = crypto_rfc3686_exit_tfm;

inst->alg.cra_blkcipher.setkey = crypto_rfc3686_setkey;
inst->alg.cra_blkcipher.encrypt = crypto_rfc3686_crypt;
inst->alg.cra_blkcipher.decrypt = crypto_rfc3686_crypt;

out:
crypto_mod_put(alg);
return inst;

out_put_alg:
inst = ERR_PTR(err);
goto out;
err_drop_spawn:
crypto_drop_skcipher(spawn);
err_free_inst:
kfree(inst);
return ERR_PTR(err);
}

static void crypto_rfc3686_free(struct crypto_instance *inst)
{
struct crypto_skcipher_spawn *spawn = crypto_instance_ctx(inst);

crypto_drop_skcipher(spawn);
kfree(inst);
}

static struct crypto_template crypto_rfc3686_tmpl = {
.name = "rfc3686",
.alloc = crypto_rfc3686_alloc,
.free = crypto_ctr_free,
.free = crypto_rfc3686_free,
.module = THIS_MODULE,
};

Expand Down
4 changes: 4 additions & 0 deletions crypto/tcrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1591,6 +1591,10 @@ static int do_test(int m)
speed_template_16_24_32);
test_acipher_speed("ofb(aes)", DECRYPT, sec, NULL, 0,
speed_template_16_24_32);
test_acipher_speed("rfc3686(ctr(aes))", ENCRYPT, sec, NULL, 0,
speed_template_20_28_36);
test_acipher_speed("rfc3686(ctr(aes))", DECRYPT, sec, NULL, 0,
speed_template_20_28_36);
break;

case 501:
Expand Down
1 change: 1 addition & 0 deletions crypto/tcrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ static u8 speed_template_8_16[] = {8, 16, 0};
static u8 speed_template_8_32[] = {8, 32, 0};
static u8 speed_template_16_32[] = {16, 32, 0};
static u8 speed_template_16_24_32[] = {16, 24, 32, 0};
static u8 speed_template_20_28_36[] = {20, 28, 36, 0};
static u8 speed_template_32_40_48[] = {32, 40, 48, 0};
static u8 speed_template_32_48[] = {32, 48, 0};
static u8 speed_template_32_48_64[] = {32, 48, 64, 0};
Expand Down
4 changes: 0 additions & 4 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -557,10 +557,6 @@ struct xfrm_migrate {
};

#define XFRM_KM_TIMEOUT 30
/* which seqno */
#define XFRM_REPLAY_SEQ 1
#define XFRM_REPLAY_OSEQ 2
#define XFRM_REPLAY_SEQ_MASK 3
/* what happened */
#define XFRM_REPLAY_UPDATE XFRM_AE_CR
#define XFRM_REPLAY_TIMEOUT XFRM_AE_CE
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/snmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ enum
LINUX_MIB_XFRMOUTPOLDEAD, /* XfrmOutPolDead */
LINUX_MIB_XFRMOUTPOLERROR, /* XfrmOutPolError */
LINUX_MIB_XFRMFWDHDRERROR, /* XfrmFwdHdrError*/
LINUX_MIB_XFRMOUTSTATEINVALID, /* XfrmOutStateInvalid */
__LINUX_MIB_XFRMMAX
};

Expand Down
3 changes: 1 addition & 2 deletions net/xfrm/xfrm_algo.c
Original file line number Diff line number Diff line change
Expand Up @@ -700,8 +700,7 @@ void xfrm_probe_algs(void)
}

for (i = 0; i < ealg_entries(); i++) {
status = crypto_has_blkcipher(ealg_list[i].name, 0,
CRYPTO_ALG_ASYNC);
status = crypto_has_ablkcipher(ealg_list[i].name, 0, 0);
if (ealg_list[i].available != status)
ealg_list[i].available = status;
}
Expand Down
6 changes: 6 additions & 0 deletions net/xfrm/xfrm_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
}

spin_lock_bh(&x->lock);

if (unlikely(x->km.state != XFRM_STATE_VALID)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEINVALID);
goto error_nolock;
}

err = xfrm_state_check_expire(x);
if (err) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEEXPIRED);
Expand Down
Loading

0 comments on commit 93b9c1d

Please sign in to comment.