Loading crypto/shash.c +143 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ * */ #include <crypto/scatterwalk.h> #include <crypto/internal/hash.h> #include <linux/err.h> #include <linux/kernel.h> Loading @@ -17,11 +18,15 @@ #include <linux/slab.h> #include <linux/seq_file.h> static const struct crypto_type crypto_shash_type; static inline struct crypto_shash *__crypto_shash_cast(struct crypto_tfm *tfm) { return container_of(tfm, struct crypto_shash, base); } #include "internal.h" static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, unsigned int keylen) { Loading Loading @@ -167,6 +172,142 @@ int crypto_shash_digest(struct shash_desc *desc, const u8 *data, } EXPORT_SYMBOL_GPL(crypto_shash_digest); static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen) { struct crypto_shash **ctx = crypto_ahash_ctx(tfm); return crypto_shash_setkey(*ctx, key, keylen); } static int shash_async_init(struct ahash_request *req) { struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct shash_desc *desc = ahash_request_ctx(req); desc->tfm = *ctx; desc->flags = req->base.flags; return crypto_shash_init(desc); } static int shash_async_update(struct ahash_request *req) { struct shash_desc *desc = ahash_request_ctx(req); struct crypto_hash_walk walk; int nbytes; for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0; nbytes = crypto_hash_walk_done(&walk, nbytes)) nbytes = crypto_shash_update(desc, walk.data, nbytes); return nbytes; } static int shash_async_final(struct ahash_request *req) { return crypto_shash_final(ahash_request_ctx(req), req->result); } static int shash_async_digest(struct ahash_request *req) { struct scatterlist *sg = req->src; unsigned int offset = sg->offset; unsigned int nbytes = req->nbytes; int err; if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct shash_desc *desc = ahash_request_ctx(req); void *data; desc->tfm = *ctx; desc->flags = req->base.flags; data = crypto_kmap(sg_page(sg), 0); err = crypto_shash_digest(desc, data + offset, nbytes, req->result); crypto_kunmap(data, 0); crypto_yield(desc->flags); goto out; } err = shash_async_init(req); if (err) goto out; err = shash_async_update(req); if (err) goto out; err = shash_async_final(req); out: return err; } static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm) { struct crypto_shash **ctx = crypto_tfm_ctx(tfm); crypto_free_shash(*ctx); } static int crypto_init_shash_ops_async(struct crypto_tfm *tfm) { struct crypto_alg *calg = tfm->__crt_alg; struct shash_alg *alg = __crypto_shash_alg(calg); struct ahash_tfm *crt = &tfm->crt_ahash; struct crypto_shash **ctx = crypto_tfm_ctx(tfm); struct crypto_shash *shash; if (!crypto_mod_get(calg)) return -EAGAIN; shash = __crypto_shash_cast(crypto_create_tfm( calg, &crypto_shash_type)); if (IS_ERR(shash)) { crypto_mod_put(calg); return PTR_ERR(shash); } *ctx = shash; tfm->exit = crypto_exit_shash_ops_async; crt->init = shash_async_init; crt->update = shash_async_update; crt->final = shash_async_final; crt->digest = shash_async_digest; crt->setkey = shash_async_setkey; crt->digestsize = alg->digestsize; crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash); return 0; } static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) { switch (mask & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_AHASH_MASK: return crypto_init_shash_ops_async(tfm); } return -EINVAL; } static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type, u32 mask) { switch (mask & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_AHASH_MASK: return sizeof(struct crypto_shash *); } return 0; } static int crypto_shash_init_tfm(struct crypto_tfm *tfm, const struct crypto_type *frontend) { Loading Loading @@ -194,7 +335,9 @@ static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) } static const struct crypto_type crypto_shash_type = { .ctxsize = crypto_shash_ctxsize, .extsize = crypto_shash_extsize, .init = crypto_init_shash_ops, .init_tfm = crypto_shash_init_tfm, #ifdef CONFIG_PROC_FS .show = crypto_shash_show, Loading include/linux/crypto.h +1 −1 Original line number Diff line number Diff line Loading @@ -38,8 +38,8 @@ #define CRYPTO_ALG_TYPE_DIGEST 0x00000008 #define CRYPTO_ALG_TYPE_HASH 0x00000009 #define CRYPTO_ALG_TYPE_AHASH 0x0000000a #define CRYPTO_ALG_TYPE_SHASH 0x0000000b #define CRYPTO_ALG_TYPE_RNG 0x0000000c #define CRYPTO_ALG_TYPE_SHASH 0x0000000d #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e #define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c Loading Loading
crypto/shash.c +143 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ * */ #include <crypto/scatterwalk.h> #include <crypto/internal/hash.h> #include <linux/err.h> #include <linux/kernel.h> Loading @@ -17,11 +18,15 @@ #include <linux/slab.h> #include <linux/seq_file.h> static const struct crypto_type crypto_shash_type; static inline struct crypto_shash *__crypto_shash_cast(struct crypto_tfm *tfm) { return container_of(tfm, struct crypto_shash, base); } #include "internal.h" static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, unsigned int keylen) { Loading Loading @@ -167,6 +172,142 @@ int crypto_shash_digest(struct shash_desc *desc, const u8 *data, } EXPORT_SYMBOL_GPL(crypto_shash_digest); static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen) { struct crypto_shash **ctx = crypto_ahash_ctx(tfm); return crypto_shash_setkey(*ctx, key, keylen); } static int shash_async_init(struct ahash_request *req) { struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct shash_desc *desc = ahash_request_ctx(req); desc->tfm = *ctx; desc->flags = req->base.flags; return crypto_shash_init(desc); } static int shash_async_update(struct ahash_request *req) { struct shash_desc *desc = ahash_request_ctx(req); struct crypto_hash_walk walk; int nbytes; for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0; nbytes = crypto_hash_walk_done(&walk, nbytes)) nbytes = crypto_shash_update(desc, walk.data, nbytes); return nbytes; } static int shash_async_final(struct ahash_request *req) { return crypto_shash_final(ahash_request_ctx(req), req->result); } static int shash_async_digest(struct ahash_request *req) { struct scatterlist *sg = req->src; unsigned int offset = sg->offset; unsigned int nbytes = req->nbytes; int err; if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct shash_desc *desc = ahash_request_ctx(req); void *data; desc->tfm = *ctx; desc->flags = req->base.flags; data = crypto_kmap(sg_page(sg), 0); err = crypto_shash_digest(desc, data + offset, nbytes, req->result); crypto_kunmap(data, 0); crypto_yield(desc->flags); goto out; } err = shash_async_init(req); if (err) goto out; err = shash_async_update(req); if (err) goto out; err = shash_async_final(req); out: return err; } static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm) { struct crypto_shash **ctx = crypto_tfm_ctx(tfm); crypto_free_shash(*ctx); } static int crypto_init_shash_ops_async(struct crypto_tfm *tfm) { struct crypto_alg *calg = tfm->__crt_alg; struct shash_alg *alg = __crypto_shash_alg(calg); struct ahash_tfm *crt = &tfm->crt_ahash; struct crypto_shash **ctx = crypto_tfm_ctx(tfm); struct crypto_shash *shash; if (!crypto_mod_get(calg)) return -EAGAIN; shash = __crypto_shash_cast(crypto_create_tfm( calg, &crypto_shash_type)); if (IS_ERR(shash)) { crypto_mod_put(calg); return PTR_ERR(shash); } *ctx = shash; tfm->exit = crypto_exit_shash_ops_async; crt->init = shash_async_init; crt->update = shash_async_update; crt->final = shash_async_final; crt->digest = shash_async_digest; crt->setkey = shash_async_setkey; crt->digestsize = alg->digestsize; crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash); return 0; } static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) { switch (mask & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_AHASH_MASK: return crypto_init_shash_ops_async(tfm); } return -EINVAL; } static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type, u32 mask) { switch (mask & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_AHASH_MASK: return sizeof(struct crypto_shash *); } return 0; } static int crypto_shash_init_tfm(struct crypto_tfm *tfm, const struct crypto_type *frontend) { Loading Loading @@ -194,7 +335,9 @@ static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) } static const struct crypto_type crypto_shash_type = { .ctxsize = crypto_shash_ctxsize, .extsize = crypto_shash_extsize, .init = crypto_init_shash_ops, .init_tfm = crypto_shash_init_tfm, #ifdef CONFIG_PROC_FS .show = crypto_shash_show, Loading
include/linux/crypto.h +1 −1 Original line number Diff line number Diff line Loading @@ -38,8 +38,8 @@ #define CRYPTO_ALG_TYPE_DIGEST 0x00000008 #define CRYPTO_ALG_TYPE_HASH 0x00000009 #define CRYPTO_ALG_TYPE_AHASH 0x0000000a #define CRYPTO_ALG_TYPE_SHASH 0x0000000b #define CRYPTO_ALG_TYPE_RNG 0x0000000c #define CRYPTO_ALG_TYPE_SHASH 0x0000000d #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e #define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c Loading