lkml.org 
[lkml]   [2004]   [Feb]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH/proposal] dm-crypt: add digest-based iv generation mode
    Hi,

    I just hacked together what I wrote. Compiles but untested.

    diff -Nur linux.orig/crypto/api.c linux/crypto/api.c
    --- linux.orig/crypto/api.c 2004-02-27 19:25:58.445326056 +0100
    +++ linux/crypto/api.c 2004-02-27 19:26:44.451332080 +0100
    @@ -96,6 +96,26 @@
    return -EINVAL;
    }

    +static int crypto_copy_ops(struct crypto_tfm *tfm)
    +{
    + switch (crypto_tfm_alg_type(tfm)) {
    + case CRYPTO_ALG_TYPE_CIPHER:
    + return crypto_copy_cipher_ops(tfm);
    +
    + case CRYPTO_ALG_TYPE_DIGEST:
    + return crypto_copy_digest_ops(tfm);
    +
    + case CRYPTO_ALG_TYPE_COMPRESS:
    + return crypto_copy_compress_ops(tfm);
    +
    + default:
    + break;
    + }
    +
    + BUG();
    + return -EINVAL;
    +}
    +
    static void crypto_exit_ops(struct crypto_tfm *tfm)
    {
    switch (crypto_tfm_alg_type(tfm)) {
    @@ -117,6 +137,62 @@
    }
    }

    +static int __crypto_init_tfm(struct crypto_tfm *tfm, struct crypto_alg *alg,
    + u32 flags)
    +{
    + memset(tfm, 0, crypto_alg_tfm_size(alg));
    +
    + tfm->__crt_alg = alg;
    +
    + if (crypto_init_flags(tfm, flags))
    + return -EINVAL;
    +
    + if (crypto_init_ops(tfm)) {
    + crypto_exit_ops(tfm);
    + return -EINVAL;
    + }
    +
    + return 0;
    +}
    +
    +unsigned int crypto_lookup_alg_tfm_size(const char *name, u32 flags)
    +{
    + struct crypto_alg *alg;
    + unsigned int size;
    +
    + alg = crypto_alg_mod_lookup(name);
    + if (alg == NULL)
    + return 0;
    +
    + size = crypto_alg_tfm_size(alg);
    +
    + crypto_alg_put(alg);
    + /* hmm, there's a window to race between here and crypto_init_tfm */
    +
    + return size;
    +}
    +
    +int crypto_init_tfm(struct crypto_tfm *tfm, const char *name, u32 flags)
    +{
    + struct crypto_alg *alg;
    + int ret = -EINVAL;
    +
    + alg = crypto_alg_mod_lookup(name);
    + if (alg == NULL)
    + goto out;
    +
    + ret = __crypto_init_tfm(tfm, alg, flags);
    + if (ret < 0)
    + goto out_put;
    +
    + goto out;
    +
    +out_put:
    + crypto_alg_put(alg);
    +out:
    + return ret;
    +}
    +
    struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
    {
    struct crypto_tfm *tfm = NULL;
    @@ -126,21 +202,12 @@
    if (alg == NULL)
    goto out;

    - tfm = kmalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL);
    + tfm = kmalloc(crypto_alg_tfm_size(alg), GFP_KERNEL);
    if (tfm == NULL)
    goto out_put;

    - memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize);
    -
    - tfm->__crt_alg = alg;
    -
    - if (crypto_init_flags(tfm, flags))
    + if (__crypto_init_tfm(tfm, alg, flags) < 0)
    goto out_free_tfm;
    -
    - if (crypto_init_ops(tfm)) {
    - crypto_exit_ops(tfm);
    - goto out_free_tfm;
    - }

    goto out;

    @@ -153,13 +220,52 @@
    return tfm;
    }

    -void crypto_free_tfm(struct crypto_tfm *tfm)
    +void crypto_exit_tfm(struct crypto_tfm *tfm)
    {
    crypto_exit_ops(tfm);
    crypto_alg_put(tfm->__crt_alg);
    +}
    +
    +void crypto_free_tfm(struct crypto_tfm *tfm)
    +{
    + crypto_exit_tfm(tfm);
    kfree(tfm);
    }

    +int crypto_copy_tfm(struct crypto_tfm *dst, struct crypto_tfm *src)
    +{
    + int ret;
    +
    + memcpy(dst, src, crypto_tfm_size(src));
    + crypto_alg_get(dst->__crt_alg);
    +
    + ret = crypto_copy_ops(dst);
    + if (ret < 0)
    + crypto_alg_put(dst->__crt_alg);
    +
    + return ret;
    +}
    +
    +struct crypto_tfm *crypto_clone_tfm(struct crypto_tfm *orig)
    +{
    + struct crypto_tfm *clone = NULL;
    +
    + clone = kmalloc(crypto_tfm_size(orig), GFP_KERNEL);
    + if (clone == NULL)
    + goto out;
    +
    + if (crypto_copy_tfm(clone, orig) < 0)
    + goto out_free_tfm;
    +
    + goto out;
    +
    +out_free_tfm:
    + kfree(clone);
    + clone = NULL;
    +out:
    + return clone;
    +}
    +
    int crypto_register_alg(struct crypto_alg *alg)
    {
    int ret = 0;
    diff -Nur linux.orig/crypto/cipher.c linux/crypto/cipher.c
    --- linux.orig/crypto/cipher.c 2004-02-27 19:25:58.513315720 +0100
    +++ linux/crypto/cipher.c 2004-02-27 19:26:44.457331168 +0100
    @@ -281,7 +281,7 @@
    }

    ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm);
    - ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL);
    + ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL);
    if (ops->cit_iv == NULL)
    ret = -ENOMEM;
    }
    @@ -290,6 +290,24 @@
    return ret;
    }

    +int crypto_copy_cipher_ops(struct crypto_tfm *tfm)
    +{
    + struct cipher_tfm *ops = &tfm->crt_cipher;
    +
    + if (tfm->crt_cipher.cit_iv) {
    + void *new_cit_iv;
    +
    + new_cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL);
    + if (new_cit_iv == NULL)
    + return -ENOMEM;
    +
    + memcpy(new_cit_iv, ops->cit_iv, ops->cit_ivsize);
    + ops->cit_iv = new_cit_iv;
    + }
    +
    + return 0;
    +}
    +
    void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
    {
    if (tfm->crt_cipher.cit_iv)
    diff -Nur linux.orig/crypto/compress.c linux/crypto/compress.c
    --- linux.orig/crypto/compress.c 2004-02-27 19:25:58.514315568 +0100
    +++ linux/crypto/compress.c 2004-02-27 19:26:44.457331168 +0100
    @@ -57,6 +57,11 @@
    return ret;
    }

    +int crypto_copy_compress_ops(struct crypto_tfm *tfm)
    +{
    + return tfm->__crt_alg->cra_compress.coa_copy(crypto_tfm_ctx(tfm));
    +}
    +
    void crypto_exit_compress_ops(struct crypto_tfm *tfm)
    {
    tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm));
    diff -Nur linux.orig/crypto/deflate.c linux/crypto/deflate.c
    --- linux.orig/crypto/deflate.c 2004-02-27 19:25:58.515315416 +0100
    +++ linux/crypto/deflate.c 2004-02-27 19:26:44.458331016 +0100
    @@ -55,6 +55,40 @@
    return 0;
    }

    +static int deflate_copy(void *ctx)
    +{
    + struct deflate_ctx *dctx = ctx;
    + struct z_stream_s *stream = &dctx->comp_stream;
    + unsigned int size;
    + void *new_workspace;
    +
    + if (dctx->comp_initialized) {
    + new_workspace = __vmalloc(size = zlib_deflate_workspacesize(),
    + deflate_gfp()|__GFP_HIGHMEM,
    + PAGE_KERNEL);
    + if (!new_workspace)
    + return -ENOMEM;
    +
    + memcpy(new_workspace, stream->workspace, size);
    + stream->workspace = new_workspace;
    + }
    + if (dctx->decomp_initialized) {
    + new_workspace = kmalloc(size = zlib_inflate_workspacesize(),
    + deflate_gfp());
    + if (!new_workspace) {
    + if (dctx->comp_initialized)
    + vfree(stream->workspace);
    +
    + return -ENOMEM;
    + }
    +
    + memcpy(new_workspace, stream->workspace, size);
    + stream->workspace = new_workspace;
    + }
    +
    + return 0;
    +}
    +
    static void deflate_exit(void *ctx)
    {
    struct deflate_ctx *dctx = ctx;
    @@ -77,7 +111,7 @@
    stream->workspace = __vmalloc(zlib_deflate_workspacesize(),
    deflate_gfp()|__GFP_HIGHMEM,
    PAGE_KERNEL);
    - if (!stream->workspace ) {
    + if (!stream->workspace) {
    ret = -ENOMEM;
    goto out;
    }
    @@ -212,6 +246,7 @@
    .cra_list = LIST_HEAD_INIT(alg.cra_list),
    .cra_u = { .compress = {
    .coa_init = deflate_init,
    + .coa_copy = deflate_copy,
    .coa_exit = deflate_exit,
    .coa_compress = deflate_compress,
    .coa_decompress = deflate_decompress } }
    diff -Nur linux.orig/crypto/digest.c linux/crypto/digest.c
    --- linux.orig/crypto/digest.c 2004-02-27 19:25:58.517315112 +0100
    +++ linux/crypto/digest.c 2004-02-27 19:26:44.459330864 +0100
    @@ -76,6 +76,11 @@
    return crypto_alloc_hmac_block(tfm);
    }

    +int crypto_copy_digest_ops(struct crypto_tfm *tfm)
    +{
    + return crypto_clone_hmac_block(tfm);
    +}
    +
    void crypto_exit_digest_ops(struct crypto_tfm *tfm)
    {
    crypto_free_hmac_block(tfm);
    diff -Nur linux.orig/crypto/hmac.c linux/crypto/hmac.c
    --- linux.orig/crypto/hmac.c 2004-02-27 19:25:58.517315112 +0100
    +++ linux/crypto/hmac.c 2004-02-27 19:26:44.459330864 +0100
    @@ -44,7 +44,24 @@
    ret = -ENOMEM;

    return ret;
    -
    +}
    +
    +int crypto_clone_hmac_block(struct crypto_tfm *tfm)
    +{
    + void *new_hmac_block;
    + int ret = 0;
    +
    + BUG_ON(!crypto_tfm_alg_blocksize(tfm));
    +
    + new_hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), GFP_KERNEL);
    + if (new_hmac_block != NULL) {
    + memcpy(new_hmac_block, tfm->crt_digest.dit_hmac_block,
    + crypto_tfm_alg_blocksize(tfm));
    + tfm->crt_digest.dit_hmac_block = new_hmac_block;
    + } else
    + ret = -ENOMEM;
    +
    + return ret;
    }

    void crypto_free_hmac_block(struct crypto_tfm *tfm)
    diff -Nur linux.orig/crypto/internal.h linux/crypto/internal.h
    --- linux.orig/crypto/internal.h 2004-02-27 19:25:58.518314960 +0100
    +++ linux/crypto/internal.h 2004-02-27 19:26:44.459330864 +0100
    @@ -59,6 +59,7 @@

    #ifdef CONFIG_CRYPTO_HMAC
    int crypto_alloc_hmac_block(struct crypto_tfm *tfm);
    +int crypto_copy_hmac_block(struct crypto_tfm *tfm);
    void crypto_free_hmac_block(struct crypto_tfm *tfm);
    #else
    static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm)
    @@ -85,6 +86,10 @@
    int crypto_init_cipher_ops(struct crypto_tfm *tfm);
    int crypto_init_compress_ops(struct crypto_tfm *tfm);

    +int crypto_copy_digest_ops(struct crypto_tfm *tfm);
    +int crypto_copy_cipher_ops(struct crypto_tfm *tfm);
    +int crypto_copy_compress_ops(struct crypto_tfm *tfm);
    +
    void crypto_exit_digest_ops(struct crypto_tfm *tfm);
    void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
    void crypto_exit_compress_ops(struct crypto_tfm *tfm);
    diff -Nur linux.orig/include/linux/crypto.h linux/include/linux/crypto.h
    --- linux.orig/include/linux/crypto.h 2004-02-27 19:25:51.934315880 +0100
    +++ linux/include/linux/crypto.h 2004-02-27 19:26:32.639127808 +0100
    @@ -80,6 +80,7 @@

    struct compress_alg {
    int (*coa_init)(void *ctx);
    + int (*coa_copy)(void *ctx);
    void (*coa_exit)(void *ctx);
    int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
    u8 *dst, unsigned int *dlen);
    @@ -191,7 +192,13 @@
    /*
    * Transform user interface.
    */
    -
    +
    +#define crypto_alg_tfm_size(alg) (sizeof(struct crypto_tfm) + \
    + (alg)->cra_ctxsize)
    +#define crypto_tfm_size(tfm) crypto_alg_tfm_size((tfm)->__crt_alg)
    +
    +unsigned int crypto_lookup_alg_tfm_size(const char *alg_name, u32 tfm_flags);
    +
    /*
    * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm.
    * If that fails and the kernel supports dynamically loadable modules, it
    @@ -200,10 +207,20 @@
    *
    * crypto_free_tfm() frees up the transform and any associated resources,
    * then drops the refcount on the associated algorithm.
    + *
    + * crypto_init_tfm() and crypto_exit_tfm() do the same except that the user
    + * has to do the memory allocation.
    */
    +int crypto_init_tfm(struct crypto_tfm *tfm, const char *alg_name,
    + u32 tfm_flags);
    struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
    +
    +void crypto_exit_tfm(struct crypto_tfm *tfm);
    void crypto_free_tfm(struct crypto_tfm *tfm);

    +int crypto_copy_tfm(struct crypto_tfm *dst_tfm, struct crypto_tfm *src_tfm);
    +struct crypto_tfm *crypto_clone_tfm(struct crypto_tfm *orig_tfm);
    +
    /*
    * Transform helpers which query the underlying algorithm.
    */
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-03-22 14:01    [W:0.045 / U:1.532 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site