* [PATCH 0/5] Partial (de)compression Crypto API
@ 2009-02-18 15:53 Geert Uytterhoeven
2009-02-18 15:53 ` [PATCH 1/5] crypto: compress - Add pcomp interface Geert Uytterhoeven
0 siblings, 1 reply; 10+ messages in thread
From: Geert Uytterhoeven @ 2009-02-18 15:53 UTC (permalink / raw)
To: Herbert Xu; +Cc: linux-crypto, linux-kernel
The following patch series adds support for partial (de)compression to the
CRYPTO API, and modifies SquashFS 4 to use this:
[1] crypto: compress - Add pcomp interface
[2] crypto: testmgr - Add support for the pcomp interface
[3] crypto: new zlib crypto module, using pcomp
[4] crypto: testmgr - add zlib test
[5] squashfs: Make SquashFS 4 use the new pcomp crypto interface
The patches are based on:
linux-2.6.git + cryptodev-2.6.git + commit 3f683d61 ("crypto: api - Fix
crypto_alloc_tfm/create_create_tfm return convention")
Changes since last version (2009-02-13):
- Convert crypto_pcomp to a new-style crypto module, using crypto_alloc_tfm()
instead of crypto_alloc_base()
- Pass crypto_pcomp pointers instead of crypto_tfm pointers where appropriate
- Use crypto_destroy_tfm() instead of crypto_free_tfm(), to take into account
the offset info the slab object
- Remove redundant check for CRYPTO_ALG_TYPE_PCOMPRESS in
crypto_pcomp_init_tfm()
- Use separate setup functions for compression and decompression
- Sanitize naming to crypto_{,de}compress_{setup,init,update,final}()
- Remove backwards-compatibility layer (export pcomp through comp), as
requested by Herbert Xu
- Create a new "zlib" pcomp module instead of modifying the existing
"deflate" comp module
- Readd accidentally removed ".cra_module = THIS_MODULE", which allowed the
zlib module to be rmmoded while it was in use
- Fix the pcomp/testmgr dependency
With kind regards,
Geert Uytterhoeven
Software Architect
Sony Techsoft Centre Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: Geert.Uytterhoeven@sonycom.com
Internet: http://www.sony-europe.com/
A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 · RPR Brussels
Fortis · BIC GEBABEBB · IBAN BE41293037680010
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 1/5] crypto: compress - Add pcomp interface 2009-02-18 15:53 [PATCH 0/5] Partial (de)compression Crypto API Geert Uytterhoeven @ 2009-02-18 15:53 ` Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 2/5] crypto: testmgr - Add support for the " Geert Uytterhoeven 2009-02-19 4:14 ` [PATCH 1/5] crypto: compress - Add pcomp interface Herbert Xu 0 siblings, 2 replies; 10+ messages in thread From: Geert Uytterhoeven @ 2009-02-18 15:53 UTC (permalink / raw) To: Herbert Xu; +Cc: linux-crypto, linux-kernel, Geert Uytterhoeven The current "comp" crypto interface supports one-shot (de)compression only, i.e. the whole data buffer to be (de)compressed must be passed at once, and the whole (de)compressed data buffer will be received at once. In several use-cases (e.g. compressed file systems that store files in big compressed blocks), this workflow is not suitable. Furthermore, the "comp" type doesn't provide for the configuration of (de)compression parameters, and always allocates workspace memory for both compression and decompression, which may waste memory. To solve this, add a "pcomp" partial (de)compression interface that provides the following operations: - crypto_compress_{init,update,final}() for compression, - crypto_decompress_{init,update,final}() for decompression, - crypto_{,de}compress_setup(), to configure (de)compression parameters (incl. allocating workspace memory). The (de)compression methods take a struct comp_request, which was mimicked after the z_stream object in zlib, and contains buffer pointer and length pairs for input and output. The setup methods take an opaque parameter pointer, whose meaning depends on the actual (name of the) (de)compression algorithm. Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> --- crypto/Kconfig | 4 + crypto/Makefile | 2 + crypto/pcompress.c | 97 ++++++++++++++++++++++++++++ include/crypto/compress.h | 123 ++++++++++++++++++++++++++++++++++++ include/crypto/internal/compress.h | 28 ++++++++ include/linux/crypto.h | 1 + 6 files changed, 255 insertions(+), 0 deletions(-) create mode 100644 crypto/pcompress.c create mode 100644 include/crypto/compress.h create mode 100644 include/crypto/internal/compress.h diff --git a/crypto/Kconfig b/crypto/Kconfig index a83ce04..c00c985 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -75,6 +75,10 @@ config CRYPTO_RNG2 tristate select CRYPTO_ALGAPI2 +config CRYPTO_PCOMP + tristate + select CRYPTO_ALGAPI2 + config CRYPTO_MANAGER tristate "Cryptographic algorithm manager" select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 46b08bf..8de194f 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -25,6 +25,8 @@ crypto_hash-objs += ahash.o crypto_hash-objs += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o +obj-$(CONFIG_CRYPTO_PCOMP) += pcompress.o + cryptomgr-objs := algboss.o testmgr.o obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o diff --git a/crypto/pcompress.c b/crypto/pcompress.c new file mode 100644 index 0000000..ca9a4af --- /dev/null +++ b/crypto/pcompress.c @@ -0,0 +1,97 @@ +/* + * Cryptographic API. + * + * Partial (de)compression operations. + * + * Copyright 2008 Sony Corporation + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + * If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/crypto.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/seq_file.h> +#include <linux/string.h> + +#include <crypto/compress.h> + +#include "internal.h" + + +static int crypto_pcomp_init(struct crypto_tfm *tfm, u32 type, u32 mask) +{ + return 0; +} + +static unsigned int crypto_pcomp_extsize(struct crypto_alg *alg, + const struct crypto_type *frontend) +{ + return alg->cra_ctxsize; +} + +static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm, + const struct crypto_type *frontend) +{ + return 0; +} + +static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); +static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg) +{ + seq_printf(m, "type : pcomp\n"); +} + +static const struct crypto_type crypto_pcomp_type = { + .extsize = crypto_pcomp_extsize, + .init = crypto_pcomp_init, + .init_tfm = crypto_pcomp_init_tfm, +#ifdef CONFIG_PROC_FS + .show = crypto_pcomp_show, +#endif + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_MASK, + .type = CRYPTO_ALG_TYPE_PCOMPRESS, + .tfmsize = offsetof(struct crypto_pcomp, base), +}; + +struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name, u32 type, + u32 mask) +{ + return crypto_alloc_tfm(alg_name, &crypto_pcomp_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_alloc_pcomp); + +int crypto_register_pcomp(struct pcomp_alg *alg) +{ + struct crypto_alg *base = &alg->base; + + base->cra_type = &crypto_pcomp_type; + base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; + base->cra_flags |= CRYPTO_ALG_TYPE_PCOMPRESS; + + return crypto_register_alg(base); +} +EXPORT_SYMBOL_GPL(crypto_register_pcomp); + +int crypto_unregister_pcomp(struct pcomp_alg *alg) +{ + return crypto_unregister_alg(&alg->base); +} +EXPORT_SYMBOL_GPL(crypto_unregister_pcomp); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Partial (de)compression type"); +MODULE_AUTHOR("Sony Corporation"); diff --git a/include/crypto/compress.h b/include/crypto/compress.h new file mode 100644 index 0000000..bcf1ff5 --- /dev/null +++ b/include/crypto/compress.h @@ -0,0 +1,123 @@ +/* + * Compress: Compression algorithms under the cryptographic API. + * + * Copyright 2008 Sony Corporation + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + * If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _CRYPTO_COMPRESS_H +#define _CRYPTO_COMPRESS_H + +#include <linux/crypto.h> + + +struct comp_request { + const void *next_in; /* next input byte */ + void *next_out; /* next output byte */ + unsigned int avail_in; /* bytes available at next_in */ + unsigned int avail_out; /* bytes available at next_out */ +}; + +struct crypto_pcomp { + struct crypto_tfm base; +}; + +struct pcomp_alg { + int (*compress_setup)(struct crypto_pcomp *tfm, const void *params); + int (*compress_init)(struct crypto_pcomp *tfm); + int (*compress_update)(struct crypto_pcomp *tfm, + struct comp_request *req); + int (*compress_final)(struct crypto_pcomp *tfm, + struct comp_request *req); + int (*decompress_setup)(struct crypto_pcomp *tfm, const void *params); + int (*decompress_init)(struct crypto_pcomp *tfm); + int (*decompress_update)(struct crypto_pcomp *tfm, + struct comp_request *req); + int (*decompress_final)(struct crypto_pcomp *tfm, + struct comp_request *req); + + struct crypto_alg base; +}; + +extern struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name, u32 type, + u32 mask); + +static inline struct crypto_tfm *crypto_pcomp_tfm(struct crypto_pcomp *tfm) +{ + return &tfm->base; +} + +static inline void crypto_free_pcomp(struct crypto_pcomp *tfm) +{ + crypto_destroy_tfm(tfm, crypto_pcomp_tfm(tfm)); +} + +static inline struct pcomp_alg *__crypto_pcomp_alg(struct crypto_alg *alg) +{ + return container_of(alg, struct pcomp_alg, base); +} + +static inline struct pcomp_alg *crypto_pcomp_alg(struct crypto_pcomp *tfm) +{ + return __crypto_pcomp_alg(crypto_pcomp_tfm(tfm)->__crt_alg); +} + +static inline int crypto_compress_setup(struct crypto_pcomp *tfm, + const void *params) +{ + return crypto_pcomp_alg(tfm)->compress_setup(tfm, params); +} + +static inline int crypto_compress_init(struct crypto_pcomp *tfm) +{ + return crypto_pcomp_alg(tfm)->compress_init(tfm); +} + +static inline int crypto_compress_update(struct crypto_pcomp *tfm, + struct comp_request *req) +{ + return crypto_pcomp_alg(tfm)->compress_update(tfm, req); +} + +static inline int crypto_compress_final(struct crypto_pcomp *tfm, + struct comp_request *req) +{ + return crypto_pcomp_alg(tfm)->compress_final(tfm, req); +} + +static inline int crypto_decompress_setup(struct crypto_pcomp *tfm, + const void *params) +{ + return crypto_pcomp_alg(tfm)->decompress_setup(tfm, params); +} + +static inline int crypto_decompress_init(struct crypto_pcomp *tfm) +{ + return crypto_pcomp_alg(tfm)->decompress_init(tfm); +} + +static inline int crypto_decompress_update(struct crypto_pcomp *tfm, + struct comp_request *req) +{ + return crypto_pcomp_alg(tfm)->decompress_update(tfm, req); +} + +static inline int crypto_decompress_final(struct crypto_pcomp *tfm, + struct comp_request *req) +{ + return crypto_pcomp_alg(tfm)->decompress_final(tfm, req); +} + +#endif /* _CRYPTO_COMPRESS_H */ diff --git a/include/crypto/internal/compress.h b/include/crypto/internal/compress.h new file mode 100644 index 0000000..178a888 --- /dev/null +++ b/include/crypto/internal/compress.h @@ -0,0 +1,28 @@ +/* + * Compress: Compression algorithms under the cryptographic API. + * + * Copyright 2008 Sony Corporation + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + * If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _CRYPTO_INTERNAL_COMPRESS_H +#define _CRYPTO_INTERNAL_COMPRESS_H + +#include <crypto/compress.h> + +extern int crypto_register_pcomp(struct pcomp_alg *alg); +extern int crypto_unregister_pcomp(struct pcomp_alg *alg); + +#endif /* _CRYPTO_INTERNAL_COMPRESS_H */ diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 29729b8..ec29fa2 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -40,6 +40,7 @@ #define CRYPTO_ALG_TYPE_SHASH 0x00000009 #define CRYPTO_ALG_TYPE_AHASH 0x0000000a #define CRYPTO_ALG_TYPE_RNG 0x0000000c +#define CRYPTO_ALG_TYPE_PCOMPRESS 0x0000000f #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e #define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c -- 1.6.0.4 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/5] crypto: testmgr - Add support for the pcomp interface 2009-02-18 15:53 ` [PATCH 1/5] crypto: compress - Add pcomp interface Geert Uytterhoeven @ 2009-02-18 15:53 ` Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 3/5] crypto: new zlib crypto module, using pcomp Geert Uytterhoeven 2009-02-19 4:14 ` [PATCH 1/5] crypto: compress - Add pcomp interface Herbert Xu 1 sibling, 1 reply; 10+ messages in thread From: Geert Uytterhoeven @ 2009-02-18 15:53 UTC (permalink / raw) To: Herbert Xu; +Cc: linux-crypto, linux-kernel, Geert Uytterhoeven Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> --- crypto/testmgr.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ crypto/testmgr.h | 9 +++ 2 files changed, 190 insertions(+), 0 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index a75f11f..54b96ed 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -72,6 +72,13 @@ struct comp_test_suite { } comp, decomp; }; +struct pcomp_test_suite { + struct { + struct pcomp_testvec *vecs; + unsigned int count; + } comp, decomp; +}; + struct hash_test_suite { struct hash_testvec *vecs; unsigned int count; @@ -86,6 +93,7 @@ struct alg_test_desc { struct aead_test_suite aead; struct cipher_test_suite cipher; struct comp_test_suite comp; + struct pcomp_test_suite pcomp; struct hash_test_suite hash; } suite; }; @@ -898,6 +906,157 @@ out: return ret; } +static int test_pcomp(struct crypto_pcomp *tfm, + struct pcomp_testvec *ctemplate, + struct pcomp_testvec *dtemplate, int ctcount, + int dtcount) +{ + const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm)); + unsigned int i; + char result[COMP_BUF_SIZE]; + int error; + + for (i = 0; i < ctcount; i++) { + struct comp_request req; + + error = crypto_compress_setup(tfm, ctemplate[i].params); + if (error) { + pr_err("alg: pcomp: compression setup failed on test " + "%d for %s: error=%d\n", i + 1, algo, error); + return error; + } + + error = crypto_compress_init(tfm); + if (error) { + pr_err("alg: pcomp: compression init failed on test " + "%d for %s: error=%d\n", i + 1, algo, error); + return error; + } + + memset(result, 0, sizeof(result)); + + req.next_in = ctemplate[i].input; + req.avail_in = ctemplate[i].inlen / 2; + req.next_out = result; + req.avail_out = ctemplate[i].outlen / 2; + + error = crypto_compress_update(tfm, &req); + if (error && (error != -EAGAIN || req.avail_in)) { + pr_err("alg: pcomp: compression update failed on test " + "%d for %s: error=%d\n", i + 1, algo, error); + return error; + } + + /* Add remaining input data */ + req.avail_in += (ctemplate[i].inlen + 1) / 2; + + error = crypto_compress_update(tfm, &req); + if (error && (error != -EAGAIN || req.avail_in)) { + pr_err("alg: pcomp: compression update failed on test " + "%d for %s: error=%d\n", i + 1, algo, error); + return error; + } + + /* Provide remaining output space */ + req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2; + + error = crypto_compress_final(tfm, &req); + if (error) { + pr_err("alg: pcomp: compression final failed on test " + "%d for %s: error=%d\n", i + 1, algo, error); + return error; + } + + if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) { + pr_err("alg: comp: Compression test %d failed for %s: " + "output len = %d (expected %d)\n", i + 1, algo, + COMP_BUF_SIZE - req.avail_out, + ctemplate[i].outlen); + return -EINVAL; + } + + if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) { + pr_err("alg: pcomp: Compression test %d failed for " + "%s\n", i + 1, algo); + hexdump(result, ctemplate[i].outlen); + return -EINVAL; + } + } + + for (i = 0; i < dtcount; i++) { + struct comp_request req; + + error = crypto_decompress_setup(tfm, dtemplate[i].params); + if (error) { + pr_err("alg: pcomp: decompression setup failed on " + "test %d for %s: error=%d\n", i + 1, algo, + error); + return error; + } + + error = crypto_decompress_init(tfm); + if (error) { + pr_err("alg: pcomp: decompression init failed on test " + "%d for %s: error=%d\n", i + 1, algo, error); + return error; + } + + memset(result, 0, sizeof(result)); + + req.next_in = dtemplate[i].input; + req.avail_in = dtemplate[i].inlen / 2; + req.next_out = result; + req.avail_out = dtemplate[i].outlen / 2; + + error = crypto_decompress_update(tfm, &req); + if (error && (error != -EAGAIN || req.avail_in)) { + pr_err("alg: pcomp: decompression update failed on " + "test %d for %s: error=%d\n", i + 1, algo, + error); + return error; + } + + /* Add remaining input data */ + req.avail_in += (dtemplate[i].inlen + 1) / 2; + + error = crypto_decompress_update(tfm, &req); + if (error && (error != -EAGAIN || req.avail_in)) { + pr_err("alg: pcomp: decompression update failed on " + "test %d for %s: error=%d\n", i + 1, algo, + error); + return error; + } + + /* Provide remaining output space */ + req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2; + + error = crypto_decompress_final(tfm, &req); + if (error && (error != -EAGAIN || req.avail_in)) { + pr_err("alg: pcomp: decompression final failed on " + "test %d for %s: error=%d\n", i + 1, algo, + error); + return error; + } + + if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) { + pr_err("alg: comp: Decompression test %d failed for " + "%s: output len = %d (expected %d)\n", i + 1, + algo, COMP_BUF_SIZE - req.avail_out, + dtemplate[i].outlen); + return -EINVAL; + } + + if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) { + pr_err("alg: pcomp: Decompression test %d failed for " + "%s\n", i + 1, algo); + hexdump(result, dtemplate[i].outlen); + return -EINVAL; + } + } + + return 0; +} + static int alg_test_aead(const struct alg_test_desc *desc, const char *driver, u32 type, u32 mask) { @@ -1007,6 +1166,28 @@ static int alg_test_comp(const struct alg_test_desc *desc, const char *driver, return err; } +static int alg_test_pcomp(const struct alg_test_desc *desc, const char *driver, + u32 type, u32 mask) +{ + struct crypto_pcomp *tfm; + int err; + + tfm = crypto_alloc_pcomp(driver, type, mask); + if (IS_ERR(tfm)) { + pr_err("alg: pcomp: Failed to load transform for %s: %ld\n", + driver, PTR_ERR(tfm)); + return PTR_ERR(tfm); + } + + err = test_pcomp(tfm, desc->suite.pcomp.comp.vecs, + desc->suite.pcomp.decomp.vecs, + desc->suite.pcomp.comp.count, + desc->suite.pcomp.decomp.count); + + crypto_free_pcomp(tfm); + return err; +} + static int alg_test_hash(const struct alg_test_desc *desc, const char *driver, u32 type, u32 mask) { diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 132953e..81b7eb0 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -15,6 +15,8 @@ #ifndef _CRYPTO_TESTMGR_H #define _CRYPTO_TESTMGR_H +#include <crypto/compress.h> + #define MAX_DIGEST_SIZE 64 #define MAX_TAP 8 @@ -8347,6 +8349,13 @@ struct comp_testvec { char output[COMP_BUF_SIZE]; }; +struct pcomp_testvec { + const void *params; + int inlen, outlen; + char input[COMP_BUF_SIZE]; + char output[COMP_BUF_SIZE]; +}; + /* * Deflate test vectors (null-terminated strings). * Params: winbits=-11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL. -- 1.6.0.4 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/5] crypto: new zlib crypto module, using pcomp 2009-02-18 15:53 ` [PATCH 2/5] crypto: testmgr - Add support for the " Geert Uytterhoeven @ 2009-02-18 15:53 ` Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 4/5] crypto: testmgr - add zlib test Geert Uytterhoeven 0 siblings, 1 reply; 10+ messages in thread From: Geert Uytterhoeven @ 2009-02-18 15:53 UTC (permalink / raw) To: Herbert Xu; +Cc: linux-crypto, linux-kernel, Geert Uytterhoeven, James Morris Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> Cc: James Morris <jmorris@namei.org> --- crypto/Kconfig | 8 + crypto/Makefile | 1 + crypto/zlib.c | 351 +++++++++++++++++++++++++++++++++++++++++++++ include/crypto/compress.h | 12 ++ 4 files changed, 372 insertions(+), 0 deletions(-) create mode 100644 crypto/zlib.c diff --git a/crypto/Kconfig b/crypto/Kconfig index c00c985..85cc7fa 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -743,6 +743,14 @@ config CRYPTO_DEFLATE You will most probably want this if using IPSec. +config CRYPTO_ZLIB + tristate "Zlib compression algorithm" + select CRYPTO_PCOMP + select ZLIB_INFLATE + select ZLIB_DEFLATE + help + This is the zlib algorithm. + config CRYPTO_LZO tristate "LZO compression algorithm" select CRYPTO_ALGAPI diff --git a/crypto/Makefile b/crypto/Makefile index 8de194f..836a764 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -72,6 +72,7 @@ obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o obj-$(CONFIG_CRYPTO_SEED) += seed.o obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o +obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o diff --git a/crypto/zlib.c b/crypto/zlib.c new file mode 100644 index 0000000..77b865d --- /dev/null +++ b/crypto/zlib.c @@ -0,0 +1,351 @@ +/* + * Cryptographic API. + * + * Zlib algorithm + * + * Copyright 2008 Sony Corporation + * + * Based on deflate.c, which is + * Copyright (c) 2003 James Morris <jmorris@intercode.com.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. + * + * FIXME: deflate transforms will require up to a total of about 436k of kernel + * memory on i386 (390k for compression, the rest for decompression), as the + * current zlib kernel code uses a worst case pre-allocation system by default. + * This needs to be fixed so that the amount of memory required is properly + * related to the winbits and memlevel parameters. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/vmalloc.h> +#include <linux/interrupt.h> +#include <linux/mm.h> +#include <linux/net.h> +#include <linux/slab.h> + +#include <crypto/internal/compress.h> + + +struct zlib_ctx { + struct zlib_decomp_params decomp_params; + struct z_stream_s comp_stream; + struct z_stream_s decomp_stream; +}; + + +static void zlib_comp_exit(struct zlib_ctx *ctx) +{ + struct z_stream_s *stream = &ctx->comp_stream; + + if (stream->workspace) { + zlib_deflateEnd(stream); + vfree(stream->workspace); + stream->workspace = NULL; + } +} + +static void zlib_decomp_exit(struct zlib_ctx *ctx) +{ + struct z_stream_s *stream = &ctx->decomp_stream; + + if (stream->workspace) { + zlib_inflateEnd(stream); + kfree(stream->workspace); + stream->workspace = NULL; + } +} + +static int zlib_init(struct crypto_tfm *tfm) +{ + return 0; +} + +static void zlib_exit(struct crypto_tfm *tfm) +{ + struct zlib_ctx *ctx = crypto_tfm_ctx(tfm); + + zlib_comp_exit(ctx); + zlib_decomp_exit(ctx); +} + + +static int zlib_compress_setup(struct crypto_pcomp *tfm, const void *params) +{ + struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); + const struct zlib_comp_params *zparams = params; + struct z_stream_s *stream = &ctx->comp_stream; + size_t workspacesize; + int ret = 0; + + zlib_comp_exit(ctx); + + workspacesize = zlib_deflate_workspacesize(); + stream->workspace = vmalloc(workspacesize); + if (!stream->workspace) + return -ENOMEM; + + memset(stream->workspace, 0, workspacesize); + ret = zlib_deflateInit2(stream, zparams->level, zparams->method, + zparams->windowBits, zparams->memLevel, + zparams->strategy); + if (ret != Z_OK) { + vfree(stream->workspace); + stream->workspace = NULL; + return -EINVAL; + } + + return 0; +} + +static int zlib_compress_init(struct crypto_pcomp *tfm) +{ + int ret; + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); + struct z_stream_s *stream = &dctx->comp_stream; + + ret = zlib_deflateReset(stream); + if (ret != Z_OK) + return -EINVAL; + + return 0; +} + +static int zlib_compress_update(struct crypto_pcomp *tfm, + struct comp_request *req) +{ + int ret; + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); + struct z_stream_s *stream = &dctx->comp_stream; + + pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); + stream->next_in = req->next_in; + stream->avail_in = req->avail_in; + stream->next_out = req->next_out; + stream->avail_out = req->avail_out; + + ret = zlib_deflate(stream, Z_NO_FLUSH); + switch (ret) { + case Z_OK: + break; + + case Z_BUF_ERROR: + pr_debug("zlib_deflate could not make progress\n"); + return -EAGAIN; + + default: + pr_debug("zlib_deflate failed %d\n", ret); + return -EINVAL; + } + + pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", + stream->avail_in, stream->avail_out, + req->avail_in - stream->avail_in, + req->avail_out - stream->avail_out); + req->next_in = stream->next_in; + req->avail_in = stream->avail_in; + req->next_out = stream->next_out; + req->avail_out = stream->avail_out; + return 0; +} + +static int zlib_compress_final(struct crypto_pcomp *tfm, + struct comp_request *req) +{ + int ret; + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); + struct z_stream_s *stream = &dctx->comp_stream; + + pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); + stream->next_in = req->next_in; + stream->avail_in = req->avail_in; + stream->next_out = req->next_out; + stream->avail_out = req->avail_out; + + ret = zlib_deflate(stream, Z_FINISH); + if (ret != Z_STREAM_END) { + pr_debug("zlib_deflate failed %d\n", ret); + return -EINVAL; + } + + pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", + stream->avail_in, stream->avail_out, + req->avail_in - stream->avail_in, + req->avail_out - stream->avail_out); + req->next_in = stream->next_in; + req->avail_in = stream->avail_in; + req->next_out = stream->next_out; + req->avail_out = stream->avail_out; + return 0; +} + + +static int zlib_decompress_setup(struct crypto_pcomp *tfm, const void *params) +{ + struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); + const struct zlib_decomp_params *zparams = params; + struct z_stream_s *stream = &ctx->decomp_stream; + int ret = 0; + + zlib_decomp_exit(ctx); + + ctx->decomp_params = *zparams; + + stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL); + if (!stream->workspace) + return -ENOMEM; + + ret = zlib_inflateInit2(stream, zparams->windowBits); + if (ret != Z_OK) { + kfree(stream->workspace); + stream->workspace = NULL; + return -EINVAL; + } + + return 0; +} + +static int zlib_decompress_init(struct crypto_pcomp *tfm) +{ + int ret; + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); + struct z_stream_s *stream = &dctx->decomp_stream; + + ret = zlib_inflateReset(stream); + if (ret != Z_OK) + return -EINVAL; + + return 0; +} + +static int zlib_decompress_update(struct crypto_pcomp *tfm, + struct comp_request *req) +{ + int ret; + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); + struct z_stream_s *stream = &dctx->decomp_stream; + + pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); + stream->next_in = req->next_in; + stream->avail_in = req->avail_in; + stream->next_out = req->next_out; + stream->avail_out = req->avail_out; + + ret = zlib_inflate(stream, Z_SYNC_FLUSH); + switch (ret) { + case Z_OK: + case Z_STREAM_END: + break; + + case Z_BUF_ERROR: + pr_debug("zlib_inflate could not make progress\n"); + return -EAGAIN; + + default: + pr_debug("zlib_inflate failed %d\n", ret); + return -EINVAL; + } + + pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", + stream->avail_in, stream->avail_out, + req->avail_in - stream->avail_in, + req->avail_out - stream->avail_out); + req->next_in = stream->next_in; + req->avail_in = stream->avail_in; + req->next_out = stream->next_out; + req->avail_out = stream->avail_out; + return 0; +} + +static int zlib_decompress_final(struct crypto_pcomp *tfm, + struct comp_request *req) +{ + int ret; + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); + struct z_stream_s *stream = &dctx->decomp_stream; + + pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); + stream->next_in = req->next_in; + stream->avail_in = req->avail_in; + stream->next_out = req->next_out; + stream->avail_out = req->avail_out; + + if (dctx->decomp_params.windowBits < 0) { + ret = zlib_inflate(stream, Z_SYNC_FLUSH); + /* + * Work around a bug in zlib, which sometimes wants to taste an + * extra byte when being used in the (undocumented) raw deflate + * mode. (From USAGI). + */ + if (ret == Z_OK && !stream->avail_in && stream->avail_out) { + const void *saved_next_in = stream->next_in; + u8 zerostuff = 0; + + stream->next_in = &zerostuff; + stream->avail_in = 1; + ret = zlib_inflate(stream, Z_FINISH); + stream->next_in = saved_next_in; + stream->avail_in = 0; + } + } else + ret = zlib_inflate(stream, Z_FINISH); + if (ret != Z_STREAM_END) { + pr_debug("zlib_inflate failed %d\n", ret); + return -EINVAL; + } + + pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", + stream->avail_in, stream->avail_out, + req->avail_in - stream->avail_in, + req->avail_out - stream->avail_out); + req->next_in = stream->next_in; + req->avail_in = stream->avail_in; + req->next_out = stream->next_out; + req->avail_out = stream->avail_out; + return 0; +} + + +static struct pcomp_alg zlib_alg = { + .compress_setup = zlib_compress_setup, + .compress_init = zlib_compress_init, + .compress_update = zlib_compress_update, + .compress_final = zlib_compress_final, + .decompress_setup = zlib_decompress_setup, + .decompress_init = zlib_decompress_init, + .decompress_update = zlib_decompress_update, + .decompress_final = zlib_decompress_final, + + .base = { + .cra_name = "zlib", + .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS, + .cra_ctxsize = sizeof(struct zlib_ctx), + .cra_module = THIS_MODULE, + .cra_init = zlib_init, + .cra_exit = zlib_exit, + } +}; + +static int __init zlib_mod_init(void) +{ + return crypto_register_pcomp(&zlib_alg); +} + +static void __exit zlib_mod_fini(void) +{ + crypto_unregister_pcomp(&zlib_alg); +} + +module_init(zlib_mod_init); +module_exit(zlib_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Zlib Compression Algorithm"); +MODULE_AUTHOR("Sony Corporation"); diff --git a/include/crypto/compress.h b/include/crypto/compress.h index bcf1ff5..67ba57d 100644 --- a/include/crypto/compress.h +++ b/include/crypto/compress.h @@ -30,6 +30,18 @@ struct comp_request { unsigned int avail_out; /* bytes available at next_out */ }; +struct zlib_comp_params { + int level; /* e.g. Z_DEFAULT_COMPRESSION */ + int method; /* e.g. Z_DEFLATED */ + int windowBits; /* e.g. MAX_WBITS */ + int memLevel; /* e.g. DEF_MEM_LEVEL */ + int strategy; /* e.g. Z_DEFAULT_STRATEGY */ +}; + +struct zlib_decomp_params { + int windowBits; /* e.g. DEF_WBITS */ +}; + struct crypto_pcomp { struct crypto_tfm base; }; -- 1.6.0.4 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 4/5] crypto: testmgr - add zlib test 2009-02-18 15:53 ` [PATCH 3/5] crypto: new zlib crypto module, using pcomp Geert Uytterhoeven @ 2009-02-18 15:53 ` Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 5/5] squashfs: Make SquashFS 4 use the new pcomp crypto interface Geert Uytterhoeven 0 siblings, 1 reply; 10+ messages in thread From: Geert Uytterhoeven @ 2009-02-18 15:53 UTC (permalink / raw) To: Herbert Xu; +Cc: linux-crypto, linux-kernel, Geert Uytterhoeven Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> --- crypto/Kconfig | 1 + crypto/tcrypt.c | 6 +++- crypto/testmgr.c | 15 +++++++++ crypto/testmgr.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 1 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 85cc7fa..87c7530 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -91,6 +91,7 @@ config CRYPTO_MANAGER2 select CRYPTO_AEAD2 select CRYPTO_HASH2 select CRYPTO_BLKCIPHER2 + select CRYPTO_PCOMP config CRYPTO_GF128MUL tristate "GF(2^128) multiplication functions (EXPERIMENTAL)" diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 28a45a1..c3c9124 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -53,7 +53,7 @@ static char *check[] = { "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt", "camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320", - "lzo", "cts", NULL + "lzo", "cts", "zlib", NULL }; static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, @@ -661,6 +661,10 @@ static void do_test(int m) tcrypt_test("ecb(seed)"); break; + case 44: + tcrypt_test("zlib"); + break; + case 100: tcrypt_test("hmac(md5)"); break; diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 54b96ed..4703137 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -2016,6 +2016,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "zlib", + .test = alg_test_pcomp, + .suite = { + .pcomp = { + .comp = { + .vecs = zlib_comp_tv_template, + .count = ZLIB_COMP_TEST_VECTORS + }, + .decomp = { + .vecs = zlib_decomp_tv_template, + .count = ZLIB_DECOMP_TEST_VECTORS + } + } + } } }; diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 81b7eb0..098c033 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -15,6 +15,7 @@ #ifndef _CRYPTO_TESTMGR_H #define _CRYPTO_TESTMGR_H +#include <linux/zlib.h> #include <crypto/compress.h> #define MAX_DIGEST_SIZE 64 @@ -8360,6 +8361,7 @@ struct pcomp_testvec { * Deflate test vectors (null-terminated strings). * Params: winbits=-11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL. */ + #define DEFLATE_COMP_TEST_VECTORS 2 #define DEFLATE_DECOMP_TEST_VECTORS 2 @@ -8435,6 +8437,97 @@ static struct comp_testvec deflate_decomp_tv_template[] = { }, }; +#define ZLIB_COMP_TEST_VECTORS 2 +#define ZLIB_DECOMP_TEST_VECTORS 2 + +static const struct zlib_comp_params deflate_comp_params = { + .level = Z_DEFAULT_COMPRESSION, + .method = Z_DEFLATED, + .windowBits = -11, + .memLevel = MAX_MEM_LEVEL, + .strategy = Z_DEFAULT_STRATEGY +}; + +static const struct zlib_decomp_params deflate_decomp_params = { + .windowBits = -11, +}; + +static struct pcomp_testvec zlib_comp_tv_template[] = { + { + .params = &deflate_comp_params, + .inlen = 70, + .outlen = 38, + .input = "Join us now and share the software " + "Join us now and share the software ", + .output = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56" + "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51" + "\x28\xce\x48\x2c\x4a\x55\x28\xc9" + "\x48\x55\x28\xce\x4f\x2b\x29\x07" + "\x71\xbc\x08\x2b\x01\x00", + }, { + .params = &deflate_comp_params, + .inlen = 191, + .outlen = 122, + .input = "This document describes a compression method based on the DEFLATE" + "compression algorithm. This document defines the application of " + "the DEFLATE algorithm to the IP Payload Compression Protocol.", + .output = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04" + "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09" + "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8" + "\x24\xdb\x67\xd9\x47\xc1\xef\x49" + "\x68\x12\x51\xae\x76\x67\xd6\x27" + "\x19\x88\x1a\xde\x85\xab\x21\xf2" + "\x08\x5d\x16\x1e\x20\x04\x2d\xad" + "\xf3\x18\xa2\x15\x85\x2d\x69\xc4" + "\x42\x83\x23\xb6\x6c\x89\x71\x9b" + "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f" + "\xed\x62\xa9\x4c\x80\xff\x13\xaf" + "\x52\x37\xed\x0e\x52\x6b\x59\x02" + "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98" + "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a" + "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79" + "\xfa\x02", + }, +}; + +static struct pcomp_testvec zlib_decomp_tv_template[] = { + { + .params = &deflate_decomp_params, + .inlen = 122, + .outlen = 191, + .input = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04" + "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09" + "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8" + "\x24\xdb\x67\xd9\x47\xc1\xef\x49" + "\x68\x12\x51\xae\x76\x67\xd6\x27" + "\x19\x88\x1a\xde\x85\xab\x21\xf2" + "\x08\x5d\x16\x1e\x20\x04\x2d\xad" + "\xf3\x18\xa2\x15\x85\x2d\x69\xc4" + "\x42\x83\x23\xb6\x6c\x89\x71\x9b" + "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f" + "\xed\x62\xa9\x4c\x80\xff\x13\xaf" + "\x52\x37\xed\x0e\x52\x6b\x59\x02" + "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98" + "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a" + "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79" + "\xfa\x02", + .output = "This document describes a compression method based on the DEFLATE" + "compression algorithm. This document defines the application of " + "the DEFLATE algorithm to the IP Payload Compression Protocol.", + }, { + .params = &deflate_decomp_params, + .inlen = 38, + .outlen = 70, + .input = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56" + "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51" + "\x28\xce\x48\x2c\x4a\x55\x28\xc9" + "\x48\x55\x28\xce\x4f\x2b\x29\x07" + "\x71\xbc\x08\x2b\x01\x00", + .output = "Join us now and share the software " + "Join us now and share the software ", + }, +}; + /* * LZO test vectors (null-terminated strings). */ -- 1.6.0.4 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 5/5] squashfs: Make SquashFS 4 use the new pcomp crypto interface 2009-02-18 15:53 ` [PATCH 4/5] crypto: testmgr - add zlib test Geert Uytterhoeven @ 2009-02-18 15:53 ` Geert Uytterhoeven 2009-02-19 0:24 ` Jared Hulbert 0 siblings, 1 reply; 10+ messages in thread From: Geert Uytterhoeven @ 2009-02-18 15:53 UTC (permalink / raw) To: Herbert Xu Cc: linux-crypto, linux-kernel, Geert Uytterhoeven, Phillip Lougher Modify SquashFS 4 to use the new "pcomp" crypto interface for decompression, instead of calling the underlying zlib library directly. This simplifies e.g. the addition of support for hardware decompression and different decompression algorithms. Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> Cc: Phillip Lougher <phillip@lougher.demon.co.uk> --- fs/squashfs/Kconfig | 3 +- fs/squashfs/block.c | 80 +++++++++++++++++++++++------------------ fs/squashfs/squashfs_fs_sb.h | 2 +- fs/squashfs/super.c | 33 +++++++++++++---- 4 files changed, 73 insertions(+), 45 deletions(-) diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig index 25a00d1..18e33a6 100644 --- a/fs/squashfs/Kconfig +++ b/fs/squashfs/Kconfig @@ -1,7 +1,8 @@ config SQUASHFS tristate "SquashFS 4.0 - Squashed file system support" depends on BLOCK - select ZLIB_INFLATE + select CRYPTO + select CRYPTO_ZLIB help Saying Y here includes support for SquashFS 4.0 (a Compressed Read-Only File System). Squashfs is a highly compressed read-only diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index c837dfc..5a3e628 100644 --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c @@ -32,7 +32,8 @@ #include <linux/mutex.h> #include <linux/string.h> #include <linux/buffer_head.h> -#include <linux/zlib.h> + +#include <crypto/compress.h> #include "squashfs_fs.h" #include "squashfs_fs_sb.h" @@ -153,7 +154,9 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, } if (compressed) { - int zlib_err = 0, zlib_init = 0; + int error = 0, decomp_init = 0; + struct comp_request req; + unsigned int produced = 0; /* * Uncompress block. @@ -161,12 +164,13 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, mutex_lock(&msblk->read_data_mutex); - msblk->stream.avail_out = 0; - msblk->stream.avail_in = 0; + req.avail_out = 0; + req.avail_in = 0; bytes = length; + length = 0; do { - if (msblk->stream.avail_in == 0 && k < b) { + if (req.avail_in == 0 && k < b) { avail = min(bytes, msblk->devblksize - offset); bytes -= avail; wait_on_buffer(bh[k]); @@ -179,50 +183,56 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index, continue; } - msblk->stream.next_in = bh[k]->b_data + offset; - msblk->stream.avail_in = avail; + req.next_in = bh[k]->b_data + offset; + req.avail_in = avail; offset = 0; } - if (msblk->stream.avail_out == 0) { - msblk->stream.next_out = buffer[page++]; - msblk->stream.avail_out = PAGE_CACHE_SIZE; + if (req.avail_out == 0) { + req.next_out = buffer[page++]; + req.avail_out = PAGE_CACHE_SIZE; } - if (!zlib_init) { - zlib_err = zlib_inflateInit(&msblk->stream); - if (zlib_err != Z_OK) { - ERROR("zlib_inflateInit returned" - " unexpected result 0x%x," - " srclength %d\n", zlib_err, - srclength); + if (!decomp_init) { + error = crypto_decompress_init(msblk->tfm); + if (error) { + ERROR("crypto_decompress_init " + "returned %d, srclength %d\n", + error, srclength); goto release_mutex; } - zlib_init = 1; + decomp_init = 1; + } + + produced = req.avail_out; + error = crypto_decompress_update(msblk->tfm, &req); + if (error) { + ERROR("crypto_decompress_update returned %d, " + "srclength %d, avail_in %d, avail_out " + "%d\n", error, srclength, req.avail_in, + req.avail_out); + goto release_mutex; } + produced -= req.avail_out; - zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + length += produced; - if (msblk->stream.avail_in == 0 && k < b) + if (req.avail_in == 0 && k < b) put_bh(bh[k++]); - } while (zlib_err == Z_OK); - - if (zlib_err != Z_STREAM_END) { - ERROR("zlib_inflate returned unexpected result" - " 0x%x, srclength %d, avail_in %d," - " avail_out %d\n", zlib_err, srclength, - msblk->stream.avail_in, - msblk->stream.avail_out); - goto release_mutex; - } - zlib_err = zlib_inflateEnd(&msblk->stream); - if (zlib_err != Z_OK) { - ERROR("zlib_inflateEnd returned unexpected result 0x%x," - " srclength %d\n", zlib_err, srclength); + } while (bytes || produced); + + produced = req.avail_out; + error = crypto_decompress_final(msblk->tfm, &req); + if (error) { + ERROR("crypto_decompress_final returned %d, srclength " + "%d\n", error, srclength); goto release_mutex; } - length = msblk->stream.total_out; + produced -= req.avail_out; + + length += produced; + mutex_unlock(&msblk->read_data_mutex); } else { /* diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h index c8c6561..4eae75b 100644 --- a/fs/squashfs/squashfs_fs_sb.h +++ b/fs/squashfs/squashfs_fs_sb.h @@ -64,7 +64,7 @@ struct squashfs_sb_info { struct mutex read_data_mutex; struct mutex meta_index_mutex; struct meta_index *meta_index; - z_stream stream; + struct crypto_pcomp *tfm; __le64 *inode_lookup_table; u64 inode_table; u64 directory_table; diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 071df5b..12ed86d 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -37,11 +37,17 @@ #include <linux/zlib.h> #include <linux/magic.h> +#include <crypto/compress.h> + #include "squashfs_fs.h" #include "squashfs_fs_sb.h" #include "squashfs_fs_i.h" #include "squashfs.h" + +#define SQUASHFS_CRYPTO_ALG "zlib" + + static struct file_system_type squashfs_fs_type; static struct super_operations squashfs_super_ops; @@ -75,6 +81,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) unsigned short flags; unsigned int fragments; u64 lookup_table_start; + struct zlib_decomp_params params = { .windowBits = DEF_WBITS }; int err; TRACE("Entered squashfs_fill_superblock\n"); @@ -86,16 +93,25 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) } msblk = sb->s_fs_info; - msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(), - GFP_KERNEL); - if (msblk->stream.workspace == NULL) { - ERROR("Failed to allocate zlib workspace\n"); + msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(msblk->tfm)) { + ERROR("Failed to load %s crypto module\n", + SQUASHFS_CRYPTO_ALG); + err = PTR_ERR(msblk->tfm); + goto failed_pcomp; + } + + err = crypto_decompress_setup(msblk->tfm, ¶ms); + if (err) { + ERROR("Failed to set up decompression parameters\n"); goto failure; } sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); if (sblk == NULL) { ERROR("Failed to allocate squashfs_super_block\n"); + err = -ENOMEM; goto failure; } @@ -284,17 +300,18 @@ failed_mount: kfree(msblk->inode_lookup_table); kfree(msblk->fragment_index); kfree(msblk->id_table); - kfree(msblk->stream.workspace); + crypto_free_pcomp(msblk->tfm); kfree(sb->s_fs_info); sb->s_fs_info = NULL; kfree(sblk); return err; failure: - kfree(msblk->stream.workspace); + crypto_free_pcomp(msblk->tfm); +failed_pcomp: kfree(sb->s_fs_info); sb->s_fs_info = NULL; - return -ENOMEM; + return err; } @@ -333,7 +350,7 @@ static void squashfs_put_super(struct super_block *sb) kfree(sbi->id_table); kfree(sbi->fragment_index); kfree(sbi->meta_index); - kfree(sbi->stream.workspace); + crypto_free_pcomp(sbi->tfm); kfree(sb->s_fs_info); sb->s_fs_info = NULL; } -- 1.6.0.4 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 5/5] squashfs: Make SquashFS 4 use the new pcomp crypto interface 2009-02-18 15:53 ` [PATCH 5/5] squashfs: Make SquashFS 4 use the new pcomp crypto interface Geert Uytterhoeven @ 2009-02-19 0:24 ` Jared Hulbert 2009-02-19 13:42 ` Geert Uytterhoeven 0 siblings, 1 reply; 10+ messages in thread From: Jared Hulbert @ 2009-02-19 0:24 UTC (permalink / raw) To: Geert Uytterhoeven Cc: Herbert Xu, linux-crypto, linux-kernel, Phillip Lougher > Modify SquashFS 4 to use the new "pcomp" crypto interface for decompression, > instead of calling the underlying zlib library directly. This simplifies e.g. > the addition of support for hardware decompression and different decompression > algorithms. Geert, When did this become an option? I thought zlib in the crypto interface was not compatible with zlib. Is that not the case anymore? Have you looked at AXFS enough to judge if this would be as easy a job as it looks to convert? How do you get from here to supporting alternate compressors? ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 5/5] squashfs: Make SquashFS 4 use the new pcomp crypto interface 2009-02-19 0:24 ` Jared Hulbert @ 2009-02-19 13:42 ` Geert Uytterhoeven 2009-04-03 6:00 ` Jared Hulbert 0 siblings, 1 reply; 10+ messages in thread From: Geert Uytterhoeven @ 2009-02-19 13:42 UTC (permalink / raw) To: Jared Hulbert; +Cc: Herbert Xu, linux-crypto, linux-kernel, Phillip Lougher Hi Jared, How's AXFS going? On Wed, 18 Feb 2009, Jared Hulbert wrote: > > Modify SquashFS 4 to use the new "pcomp" crypto interface for decompression, > > instead of calling the underlying zlib library directly. This simplifies e.g. > > the addition of support for hardware decompression and different decompression > > algorithms. > > When did this become an option? I thought zlib in the crypto > interface was not compatible with zlib. Is that not the case anymore? The "deflate" crypto module uses hardcoded parameters for the raw deflate mode, that's why it's incompatible. However, the new "zlib" crypto module is compatible with zlib, as you can specify the all (de)compression parameters. BTW, you probably want to read the full patch series, including the introduction :-) > Have you looked at AXFS enough to judge if this would be as easy a > job as it looks to convert? I looked at the relevant code in AXFS before. Yes, I think it would be an easy job. > How do you get from here to supporting alternate compressors? Your file system code needs a mapping from compressor ID (as stored in your file system metadata) to crypto module name and (de)compression parameters. With kind regards, Geert Uytterhoeven Software Architect Sony Techsoft Centre Europe The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium Phone: +32 (0)2 700 8453 Fax: +32 (0)2 700 8622 E-mail: Geert.Uytterhoeven@sonycom.com Internet: http://www.sony-europe.com/ A division of Sony Europe (Belgium) N.V. VAT BE 0413.825.160 · RPR Brussels Fortis · BIC GEBABEBB · IBAN BE41293037680010 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 5/5] squashfs: Make SquashFS 4 use the new pcomp crypto interface 2009-02-19 13:42 ` Geert Uytterhoeven @ 2009-04-03 6:00 ` Jared Hulbert 0 siblings, 0 replies; 10+ messages in thread From: Jared Hulbert @ 2009-04-03 6:00 UTC (permalink / raw) To: Geert Uytterhoeven Cc: Herbert Xu, linux-crypto, linux-kernel, Phillip Lougher Sorry I just saw this email. My kernel hacking time has been rudely interrupted by other important work. > How's AXFS going? It's doing pretty well, we just haven't had time to push hard enough to get it out. It's been fairly stable for us for a while. Now I'm anxious to get it more widely tested. I've got two vexing bug reports. 1) a mips consumer platform where the main app can't operate in XIP, but everything else can. 2) Just yesterday we found Android APK's don't like to be XIP. These look more like flaws in the filemap_xip.c than AXFS bugs. Fortunately there was bug fix that went out just a couple days ago. I'm hoping it will fix our problems. We've automated a great deal of the busy work associated with testing and deploying it, so now I just need to find a couple days a week for a few weeks. Our flagship customer went a different direction, so it's been hard to justify time to work on it. > BTW, you probably want to read the full patch series, including the > introduction :-) Yes, I saw that shortly after I clicked "send". :) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/5] crypto: compress - Add pcomp interface 2009-02-18 15:53 ` [PATCH 1/5] crypto: compress - Add pcomp interface Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 2/5] crypto: testmgr - Add support for the " Geert Uytterhoeven @ 2009-02-19 4:14 ` Herbert Xu 1 sibling, 0 replies; 10+ messages in thread From: Herbert Xu @ 2009-02-19 4:14 UTC (permalink / raw) To: Geert Uytterhoeven; +Cc: linux-crypto, linux-kernel On Wed, Feb 18, 2009 at 04:53:18PM +0100, Geert Uytterhoeven wrote: > > + int (*compress_setup)(struct crypto_pcomp *tfm, const void *params); I think the lack of a length field is the only thing preventing me from applying this :) Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-04-03 6:00 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-02-18 15:53 [PATCH 0/5] Partial (de)compression Crypto API Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 1/5] crypto: compress - Add pcomp interface Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 2/5] crypto: testmgr - Add support for the " Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 3/5] crypto: new zlib crypto module, using pcomp Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 4/5] crypto: testmgr - add zlib test Geert Uytterhoeven 2009-02-18 15:53 ` [PATCH 5/5] squashfs: Make SquashFS 4 use the new pcomp crypto interface Geert Uytterhoeven 2009-02-19 0:24 ` Jared Hulbert 2009-02-19 13:42 ` Geert Uytterhoeven 2009-04-03 6:00 ` Jared Hulbert 2009-02-19 4:14 ` [PATCH 1/5] crypto: compress - Add pcomp interface Herbert Xu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®