From: Geert Uytterhoeven <[email protected]>
Allow "pcomp" algorithms to be used through the old "comp" interface, by
implementing one-shot (de)compression on top of the partial (de)compression
interface.
As the old "comp" interface doesn't support the configuration of
(de)compression parameters by the user, each algorithm must provide a set of
default parameters through pcompress_alg.coa_default_params.
Signed-off-by: Geert Uytterhoeven <[email protected]>
---
crypto/api.c | 6 ++
crypto/internal.h | 1
crypto/pcompress.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/crypto.h | 9 ++--
4 files changed, 118 insertions(+), 4 deletions(-)
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -288,7 +288,11 @@ static int crypto_init_ops(struct crypto
return crypto_init_compress_ops(tfm);
case CRYPTO_ALG_TYPE_PCOMPRESS:
- return crypto_init_pcompress_ops(tfm);
+ if ((type & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_COMPRESS)
+ return crypto_init_pcompress_ops_compat(tfm);
+ else
+ return crypto_init_pcompress_ops(tfm);
default:
break;
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -101,6 +101,7 @@ int crypto_init_digest_ops_async(struct
int crypto_init_cipher_ops(struct crypto_tfm *tfm);
int crypto_init_compress_ops(struct crypto_tfm *tfm);
int crypto_init_pcompress_ops(struct crypto_tfm *tfm);
+int crypto_init_pcompress_ops_compat(struct crypto_tfm *tfm);
void crypto_exit_digest_ops(struct crypto_tfm *tfm);
void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
--- a/crypto/pcompress.c
+++ b/crypto/pcompress.c
@@ -79,3 +79,109 @@ int crypto_init_pcompress_ops(struct cry
void crypto_exit_pcompress_ops(struct crypto_tfm *tfm)
{
}
+
+
+static int crypto_init_compat(struct crypto_tfm *tfm)
+{
+ struct crypto_alg *alg = tfm->__crt_alg;
+ int error;
+
+ error = alg->cra_init(tfm);
+ if (error)
+ return error;
+
+ error = crypto_compress_setup(tfm,
+ alg->cra_pcompress.coa_default_params);
+ if (error)
+ pr_debug("crypto_compress_setup failed %d\n", error);
+
+ return error;
+}
+
+static int crypto_compress_compat(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst,
+ unsigned int *dlen)
+{
+ struct comp_request req;
+ int error;
+
+ pr_debug("src = %p, slen = %u, dst = %p, dlen = %u\n", src, slen, dst,
+ *dlen);
+
+ req.next_in = src;
+ req.avail_in = slen;
+ req.next_out = dst;
+ req.avail_out = *dlen;
+
+ error = crypto_compress_init(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_debug("crypto_compress_init failed %d\n", error);
+ return error;
+ }
+
+ error = crypto_compress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_debug("crypto_compress_update failed %d\n", error);
+ return error;
+ }
+
+ error = crypto_compress_final(tfm, &req);
+ if (error) {
+ pr_debug("crypto_compress_final failed %d\n", error);
+ return error;
+ }
+
+ *dlen -= req.avail_out;
+
+ return 0;
+}
+
+static int crypto_decompress_compat(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst,
+ unsigned int *dlen)
+{
+ struct comp_request req;
+ int error;
+
+ pr_debug("src = %p, slen = %u, dst = %p, dlen = %u\n", src, slen, dst,
+ *dlen);
+
+ req.next_in = src;
+ req.avail_in = slen;
+ req.next_out = dst;
+ req.avail_out = *dlen;
+
+ error = crypto_decompress_init(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_debug("crypto_decompress_init failed %d\n", error);
+ return error;
+ }
+
+ error = crypto_decompress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_debug("crypto_decompress_update failed %d\n", error);
+ return error;
+ }
+
+ error = crypto_decompress_final(tfm, &req);
+ if (error) {
+ pr_debug("crypto_decompress_final failed %d\n", error);
+ return error;
+ }
+
+ *dlen -= req.avail_out;
+
+ return 0;
+}
+
+int crypto_init_pcompress_ops_compat(struct crypto_tfm *tfm)
+{
+ struct compress_tfm *ops = &tfm->crt_compress;
+
+ tfm->init = crypto_init_compat;
+
+ ops->cot_compress = crypto_compress_compat;
+ ops->cot_decompress = crypto_decompress_compat;
+
+ return 0;
+}
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -30,7 +30,6 @@
*/
#define CRYPTO_ALG_TYPE_MASK 0x0000000f
#define CRYPTO_ALG_TYPE_CIPHER 0x00000001
-#define CRYPTO_ALG_TYPE_COMPRESS 0x00000002
#define CRYPTO_ALG_TYPE_AEAD 0x00000003
#define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004
#define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005
@@ -40,11 +39,13 @@
#define CRYPTO_ALG_TYPE_SHASH 0x00000009
#define CRYPTO_ALG_TYPE_AHASH 0x0000000a
#define CRYPTO_ALG_TYPE_RNG 0x0000000c
+#define CRYPTO_ALG_TYPE_COMPRESS 0x0000000e
#define CRYPTO_ALG_TYPE_PCOMPRESS 0x0000000f
#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c
#define CRYPTO_ALG_TYPE_BLKCIPHER_MASK 0x0000000c
+#define CRYPTO_ALG_TYPE_COMPRESS_MASK 0x0000000e
#define CRYPTO_ALG_LARVAL 0x00000010
#define CRYPTO_ALG_DEAD 0x00000020
@@ -324,6 +325,8 @@ struct pcompress_alg {
struct comp_request *req);
int (*coa_decompress_final)(struct crypto_tfm *tfm,
struct comp_request *req);
+ /* for backwards-compatibility with compress_alg only */
+ const void *coa_default_params;
};
struct rng_alg {
@@ -1344,7 +1347,7 @@ static inline struct crypto_comp *crypto
{
type &= ~CRYPTO_ALG_TYPE_MASK;
type |= CRYPTO_ALG_TYPE_COMPRESS;
- mask |= CRYPTO_ALG_TYPE_MASK;
+ mask |= CRYPTO_ALG_TYPE_COMPRESS_MASK;
return __crypto_comp_cast(crypto_alloc_base(alg_name, type, mask));
}
@@ -1363,7 +1366,7 @@ static inline int crypto_has_comp(const
{
type &= ~CRYPTO_ALG_TYPE_MASK;
type |= CRYPTO_ALG_TYPE_COMPRESS;
- mask |= CRYPTO_ALG_TYPE_MASK;
+ mask |= CRYPTO_ALG_TYPE_COMPRESS_MASK;
return crypto_has_alg(alg_name, type, mask);
}
--
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: [email protected]
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