diff options
Diffstat (limited to 'linux/crypto')
-rw-r--r-- | linux/crypto/api.c | 216 | ||||
-rw-r--r-- | linux/crypto/blkcipher.c | 47 | ||||
-rw-r--r-- | linux/crypto/chacha20_generic.c | 43 | ||||
-rw-r--r-- | linux/crypto/internal.h | 23 | ||||
-rw-r--r-- | linux/crypto/poly1305_generic.c | 30 | ||||
-rw-r--r-- | linux/crypto/sha256_generic.c | 28 | ||||
-rw-r--r-- | linux/crypto/shash.c | 72 |
7 files changed, 116 insertions, 343 deletions
diff --git a/linux/crypto/api.c b/linux/crypto/api.c index 63efee30..2f3ab2b5 100644 --- a/linux/crypto/api.c +++ b/linux/crypto/api.c @@ -20,217 +20,95 @@ #include <linux/string.h> #include <crypto/algapi.h> -#include "internal.h" static LIST_HEAD(crypto_alg_list); static DECLARE_RWSEM(crypto_alg_sem); -static unsigned crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask) -{ - return alg->cra_type->ctxsize(alg, type, mask); -} +struct crypto_type { +}; -unsigned crypto_alg_extsize(struct crypto_alg *alg) +int crypto_register_alg(struct crypto_alg *alg) { - return alg->cra_ctxsize; + down_write(&crypto_alg_sem); + list_add(&alg->cra_list, &crypto_alg_list); + up_write(&crypto_alg_sem); + + return 0; } -struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) +static void *crypto_alloc_tfm(const char *name, + const struct crypto_type *type) { struct crypto_alg *alg; down_read(&crypto_alg_sem); list_for_each_entry(alg, &crypto_alg_list, cra_list) - if (!((alg->cra_flags ^ type) & mask) && - !strcmp(alg->cra_name, name)) + if (alg->cra_type == type && !strcmp(alg->cra_name, name)) goto found; alg = ERR_PTR(-ENOENT); found: up_read(&crypto_alg_sem); - return alg; -} + if (IS_ERR(alg)) + return ERR_CAST(alg); -static void crypto_exit_ops(struct crypto_tfm *tfm) -{ - if (tfm->exit) - tfm->exit(tfm); + return alg->alloc_tfm() ?: ERR_PTR(-ENOMEM); } -static struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, - u32 type, u32 mask) -{ - struct crypto_tfm *tfm = NULL; - unsigned tfm_size; - int err = -ENOMEM; - - tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask); - tfm = kzalloc(tfm_size, GFP_KERNEL); - if (tfm == NULL) - return ERR_PTR(-ENOMEM); - - tfm->__crt_alg = alg; - - err = alg->cra_type->init(tfm, type, mask); - if (err) - goto out_free_tfm; - - if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm))) - goto cra_init_failed; - - return tfm; +/* skcipher: */ -cra_init_failed: - crypto_exit_ops(tfm); -out_free_tfm: - kfree(tfm); - return ERR_PTR(err); -} +static const struct crypto_type crypto_skcipher_type2 = { +}; -struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask) +struct crypto_skcipher *crypto_alloc_skcipher(const char *name, + u32 type, u32 mask) { - struct crypto_alg *alg; - struct crypto_tfm *tfm; - - alg = crypto_alg_mod_lookup(alg_name, type, mask); - if (IS_ERR(alg)) { - fprintf(stderr, "unknown cipher %s\n", alg_name); - return ERR_CAST(alg); - } - - tfm = __crypto_alloc_tfm(alg, type, mask); - if (IS_ERR(tfm)) - return tfm; - - return tfm; + return crypto_alloc_tfm(name, &crypto_skcipher_type2); } -static void *crypto_create_tfm(struct crypto_alg *alg, - const struct crypto_type *frontend) +int crypto_register_skcipher(struct skcipher_alg *alg) { - struct crypto_tfm *tfm = NULL; - unsigned tfmsize; - unsigned total; - void *mem; - int err = -ENOMEM; - - tfmsize = frontend->tfmsize; - total = tfmsize + sizeof(*tfm) + frontend->extsize(alg); - - mem = kzalloc(total, GFP_KERNEL); - if (!mem) - goto out_err; - - tfm = mem + tfmsize; - tfm->__crt_alg = alg; - - err = frontend->init_tfm(tfm); - if (err) - goto out_free_tfm; - - if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm))) - goto cra_init_failed; - - goto out; - -cra_init_failed: - crypto_exit_ops(tfm); -out_free_tfm: - kfree(mem); -out_err: - mem = ERR_PTR(err); -out: - return mem; -} + alg->base.cra_type = &crypto_skcipher_type2; -static struct crypto_alg *crypto_find_alg(const char *alg_name, - const struct crypto_type *frontend, - u32 type, u32 mask) -{ - if (frontend) { - type &= frontend->maskclear; - mask &= frontend->maskclear; - type |= frontend->type; - mask |= frontend->maskset; - } - - return crypto_alg_mod_lookup(alg_name, type, mask); + return crypto_register_alg(&alg->base); } -void *crypto_alloc_tfm(const char *alg_name, - const struct crypto_type *frontend, - u32 type, u32 mask) -{ - struct crypto_alg *alg; - void *tfm; - - alg = crypto_find_alg(alg_name, frontend, type, mask); - if (IS_ERR(alg)) - return ERR_CAST(alg); - - tfm = crypto_create_tfm(alg, frontend); - if (IS_ERR(tfm)) - return tfm; +/* shash: */ - return tfm; -} +#include <crypto/hash.h> -void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm) +static int shash_finup(struct shash_desc *desc, const u8 *data, + unsigned len, u8 *out) { - struct crypto_alg *alg; - - if (unlikely(!mem)) - return; - - alg = tfm->__crt_alg; - - if (!tfm->exit && alg->cra_exit) - alg->cra_exit(tfm); - crypto_exit_ops(tfm); - kzfree(mem); + return crypto_shash_update(desc, data, len) ?: + crypto_shash_final(desc, out); } -int crypto_register_alg(struct crypto_alg *alg) +static int shash_digest(struct shash_desc *desc, const u8 *data, + unsigned len, u8 *out) { - INIT_LIST_HEAD(&alg->cra_users); - - down_write(&crypto_alg_sem); - list_add(&alg->cra_list, &crypto_alg_list); - up_write(&crypto_alg_sem); - - return 0; + return crypto_shash_init(desc) ?: + crypto_shash_finup(desc, data, len, out); } -/* skcipher: */ +static const struct crypto_type crypto_shash_type = { +}; -static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) +struct crypto_shash *crypto_alloc_shash(const char *name, + u32 type, u32 mask) { - struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); - struct skcipher_alg *alg = crypto_skcipher_alg(skcipher); - - skcipher->setkey = alg->setkey; - skcipher->encrypt = alg->encrypt; - skcipher->decrypt = alg->decrypt; - skcipher->ivsize = alg->ivsize; - skcipher->keysize = alg->max_keysize; - - if (alg->init) - return alg->init(skcipher); - - return 0; + return crypto_alloc_tfm(name, &crypto_shash_type); } -static const struct crypto_type crypto_skcipher_type2 = { - .extsize = crypto_alg_extsize, - .init_tfm = crypto_skcipher_init_tfm, - .maskclear = ~CRYPTO_ALG_TYPE_MASK, - .maskset = CRYPTO_ALG_TYPE_BLKCIPHER_MASK, - .tfmsize = offsetof(struct crypto_skcipher, base), -}; - -struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, - u32 type, u32 mask) +int crypto_register_shash(struct shash_alg *alg) { - return crypto_alloc_tfm(alg_name, &crypto_skcipher_type2, type, mask); + alg->base.cra_type = &crypto_shash_type; + + if (!alg->finup) + alg->finup = shash_finup; + if (!alg->digest) + alg->digest = shash_digest; + + return crypto_register_alg(&alg->base); } diff --git a/linux/crypto/blkcipher.c b/linux/crypto/blkcipher.c deleted file mode 100644 index 31f91418..00000000 --- a/linux/crypto/blkcipher.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Block chaining cipher operations. - * - * Generic encrypt/decrypt wrapper for ciphers, handles operations across - * multiple page boundaries by using temporary blocks. In user context, - * the kernel is given a chance to schedule us once per page. - * - * Copyright (c) 2006 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 <linux/errno.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/string.h> - -#include <crypto/algapi.h> -#include "internal.h" - -static unsigned crypto_blkcipher_ctxsize(struct crypto_alg *alg, - u32 type, u32 mask) -{ - return alg->cra_ctxsize; -} - -static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask) -{ - struct blkcipher_tfm *crt = &tfm->crt_blkcipher; - struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; - - BUG_ON((mask & CRYPTO_ALG_TYPE_MASK) != CRYPTO_ALG_TYPE_MASK); - - crt->setkey = alg->setkey; - crt->encrypt = alg->encrypt; - crt->decrypt = alg->decrypt; - return 0; -} - -const struct crypto_type crypto_blkcipher_type = { - .ctxsize = crypto_blkcipher_ctxsize, - .init = crypto_init_blkcipher_ops, -}; diff --git a/linux/crypto/chacha20_generic.c b/linux/crypto/chacha20_generic.c index df4c0e04..c6f14945 100644 --- a/linux/crypto/chacha20_generic.c +++ b/linux/crypto/chacha20_generic.c @@ -22,14 +22,18 @@ #include <sodium/crypto_stream_chacha20.h> -struct chacha20_ctx { - u32 key[8]; +static struct skcipher_alg alg; + +struct chacha20_tfm { + struct crypto_skcipher tfm; + u32 key[8]; }; static int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keysize) { - struct chacha20_ctx *ctx = crypto_skcipher_ctx(tfm); + struct chacha20_tfm *ctx = + container_of(tfm, struct chacha20_tfm, tfm); int i; if (keysize != CHACHA20_KEY_SIZE) @@ -43,8 +47,8 @@ static int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key, static int crypto_chacha20_crypt(struct skcipher_request *req) { - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - struct chacha20_ctx *ctx = crypto_skcipher_ctx(tfm); + struct chacha20_tfm *ctx = + container_of(req->tfm, struct chacha20_tfm, tfm.base); struct scatterlist *sg = req->src; unsigned nbytes = req->cryptlen; u32 iv[4]; @@ -78,21 +82,30 @@ static int crypto_chacha20_crypt(struct skcipher_request *req) return 0; } +static void *crypto_chacha20_alloc_tfm(void) +{ + struct chacha20_tfm *tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); + + if (!tfm) + return NULL; + + tfm->tfm.base.alg = &alg.base; + tfm->tfm.setkey = crypto_chacha20_setkey; + tfm->tfm.encrypt = crypto_chacha20_crypt; + tfm->tfm.decrypt = crypto_chacha20_crypt; + tfm->tfm.ivsize = CHACHA20_IV_SIZE; + tfm->tfm.keysize = CHACHA20_KEY_SIZE; + + return tfm; +} + static struct skcipher_alg alg = { .base.cra_name = "chacha20", - .base.cra_ctxsize = sizeof(struct chacha20_ctx), - - .min_keysize = CHACHA20_KEY_SIZE, - .max_keysize = CHACHA20_KEY_SIZE, - .ivsize = CHACHA20_IV_SIZE, - .chunksize = CHACHA20_BLOCK_SIZE, - .setkey = crypto_chacha20_setkey, - .encrypt = crypto_chacha20_crypt, - .decrypt = crypto_chacha20_crypt, + .base.alloc_tfm = crypto_chacha20_alloc_tfm, }; __attribute__((constructor(110))) static int chacha20_generic_mod_init(void) { - return crypto_register_alg(&alg.base); + return crypto_register_skcipher(&alg); } diff --git a/linux/crypto/internal.h b/linux/crypto/internal.h deleted file mode 100644 index 5b21f836..00000000 --- a/linux/crypto/internal.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Cryptographic API. - * - * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> - * Copyright (c) 2005 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_H -#define _CRYPTO_INTERNAL_H - -struct crypto_type; -struct crypto_alg; - -void *crypto_alloc_tfm(const char *, const struct crypto_type *, u32, u32); -unsigned int crypto_alg_extsize(struct crypto_alg *); - -#endif /* _CRYPTO_INTERNAL_H */ - diff --git a/linux/crypto/poly1305_generic.c b/linux/crypto/poly1305_generic.c index 5d385d54..acb554c0 100644 --- a/linux/crypto/poly1305_generic.c +++ b/linux/crypto/poly1305_generic.c @@ -18,18 +18,19 @@ #include <linux/crypto.h> #include <crypto/algapi.h> -#include <crypto/internal/hash.h> +#include <crypto/hash.h> #include <crypto/poly1305.h> +static struct shash_alg poly1305_alg; + struct poly1305_desc_ctx { bool key_done; crypto_onetimeauth_poly1305_state s; }; - static int poly1305_init(struct shash_desc *desc) { - struct poly1305_desc_ctx *state = shash_desc_ctx(desc); + struct poly1305_desc_ctx *state = (void *) desc->ctx; state->key_done = false; return 0; @@ -38,7 +39,7 @@ static int poly1305_init(struct shash_desc *desc) static int poly1305_update(struct shash_desc *desc, const u8 *src, unsigned len) { - struct poly1305_desc_ctx *state = shash_desc_ctx(desc); + struct poly1305_desc_ctx *state = (void *) desc->ctx; if (!state->key_done) { BUG_ON(len != crypto_onetimeauth_poly1305_KEYBYTES); @@ -52,21 +53,32 @@ static int poly1305_update(struct shash_desc *desc, static int poly1305_final(struct shash_desc *desc, u8 *out) { - struct poly1305_desc_ctx *state = shash_desc_ctx(desc); + struct poly1305_desc_ctx *state = (void *) desc->ctx; return crypto_onetimeauth_poly1305_final(&state->s, out); } +static void *poly1305_alloc_tfm(void) +{ + struct crypto_shash *tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); + + if (!tfm) + return NULL; + + tfm->base.alg = &poly1305_alg.base; + tfm->descsize = sizeof(struct poly1305_desc_ctx); + return tfm; +} + static struct shash_alg poly1305_alg = { .digestsize = crypto_onetimeauth_poly1305_BYTES, .init = poly1305_init, .update = poly1305_update, .final = poly1305_final, .descsize = sizeof(struct poly1305_desc_ctx), - .base = { - .cra_name = "poly1305", - .cra_flags = CRYPTO_ALG_TYPE_SHASH, - }, + + .base.cra_name = "poly1305", + .base.alloc_tfm = poly1305_alloc_tfm, }; __attribute__((constructor(110))) diff --git a/linux/crypto/sha256_generic.c b/linux/crypto/sha256_generic.c index 0bd272f0..9326bfe7 100644 --- a/linux/crypto/sha256_generic.c +++ b/linux/crypto/sha256_generic.c @@ -24,13 +24,15 @@ #include <asm/unaligned.h> #include <linux/crypto.h> -#include <crypto/internal/hash.h> +#include <crypto/hash.h> #include <sodium/crypto_hash_sha256.h> +static struct shash_alg sha256_alg; + static int sha256_init(struct shash_desc *desc) { - crypto_hash_sha256_state *state = shash_desc_ctx(desc); + crypto_hash_sha256_state *state = (void *) desc->ctx; return crypto_hash_sha256_init(state); } @@ -38,28 +40,38 @@ static int sha256_init(struct shash_desc *desc) static int sha256_update(struct shash_desc *desc, const u8 *data, unsigned int len) { - crypto_hash_sha256_state *state = shash_desc_ctx(desc); + crypto_hash_sha256_state *state = (void *) desc->ctx; return crypto_hash_sha256_update(state, data, len); } static int sha256_final(struct shash_desc *desc, u8 *out) { - crypto_hash_sha256_state *state = shash_desc_ctx(desc); + crypto_hash_sha256_state *state = (void *) desc->ctx; return crypto_hash_sha256_final(state, out); } +static void *sha256_alloc_tfm(void) +{ + struct crypto_shash *tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); + + if (!tfm) + return NULL; + + tfm->base.alg = &sha256_alg.base; + tfm->descsize = sizeof(crypto_hash_sha256_state); + return tfm; +} + static struct shash_alg sha256_alg = { .digestsize = crypto_hash_sha256_BYTES, .init = sha256_init, .update = sha256_update, .final = sha256_final, .descsize = sizeof(crypto_hash_sha256_state), - .base = { - .cra_name = "sha256", - .cra_flags = CRYPTO_ALG_TYPE_SHASH, - } + .base.cra_name = "sha256", + .base.alloc_tfm = sha256_alloc_tfm, }; __attribute__((constructor(110))) diff --git a/linux/crypto/shash.c b/linux/crypto/shash.c deleted file mode 100644 index 4f07a8b8..00000000 --- a/linux/crypto/shash.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Synchronous Cryptographic Hash operations. - * - * Copyright (c) 2008 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/hash.h> -#include <linux/err.h> -#include <linux/kernel.h> -#include <linux/printk.h> -#include <linux/slab.h> - -#include "internal.h" - -static int shash_finup(struct shash_desc *desc, const u8 *data, - unsigned len, u8 *out) -{ - return crypto_shash_update(desc, data, len) ?: - crypto_shash_final(desc, out); -} - -static int shash_digest(struct shash_desc *desc, const u8 *data, - unsigned len, u8 *out) -{ - return crypto_shash_init(desc) ?: - crypto_shash_finup(desc, data, len, out); -} - -static int crypto_shash_init_tfm(struct crypto_tfm *tfm) -{ - struct crypto_shash *hash = __crypto_shash_cast(tfm); - - hash->descsize = crypto_shash_alg(hash)->descsize; - return 0; -} - -static const struct crypto_type crypto_shash_type = { - .extsize = crypto_alg_extsize, - .init_tfm = crypto_shash_init_tfm, - .maskclear = ~CRYPTO_ALG_TYPE_MASK, - .maskset = CRYPTO_ALG_TYPE_MASK, - .type = CRYPTO_ALG_TYPE_SHASH, - .tfmsize = offsetof(struct crypto_shash, base), -}; - -struct crypto_shash *crypto_alloc_shash(const char *alg_name, - u32 type, u32 mask) -{ - return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask); -} - -int crypto_register_shash(struct shash_alg *alg) -{ - struct crypto_alg *base = &alg->base; - - base->cra_type = &crypto_shash_type; - base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; - base->cra_flags |= CRYPTO_ALG_TYPE_SHASH; - - if (!alg->finup) - alg->finup = shash_finup; - if (!alg->digest) - alg->digest = shash_digest; - - return crypto_register_alg(base); -} |