Add LZO1X compression support to the crypto interface, including a couple of tests.
Also convert test_deflate into a more generic test_compress() and avoid duplicating the data for compression and decompression tests since this can always work both ways in the compression case. Signed-off-by: Richard Purdie <[EMAIL PROTECTED]> --- crypto/Kconfig | 8 +++ crypto/Makefile | 1 + crypto/crypto_lzo.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ crypto/tcrypt.c | 43 ++++++++---------- crypto/tcrypt.h | 75 ++++++++++++++++++-------------- 5 files changed, 191 insertions(+), 57 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 086fcec..8a479d5 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -406,6 +406,14 @@ config CRYPTO_DEFLATE You will most probably want this if using IPSec. +config CRYPTO_LZO + tristate "LZO compression algorithm" + depends on CRYPTO + select LZO + help + Enable use of the LZO compression algorithm through the crypto + subsystem. + config CRYPTO_MICHAEL_MIC tristate "Michael MIC keyed digest algorithm" select CRYPTO_ALGAPI diff --git a/crypto/Makefile b/crypto/Makefile index 12f93f5..b4bc7ca 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_CRYPTO_TEA) += tea.o obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o +obj-$(CONFIG_CRYPTO_LZO) += crypto_lzo.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o diff --git a/crypto/crypto_lzo.c b/crypto/crypto_lzo.c new file mode 100644 index 0000000..a99c42a --- /dev/null +++ b/crypto/crypto_lzo.c @@ -0,0 +1,121 @@ +/* + * Cryptographic API for LZO compression. + * + * Copyright (C) 2007 Nokia Corporation. All rights reserved. + * + * Author: Richard Purdie <[EMAIL PROTECTED]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/crypto.h> +#include <linux/vmalloc.h> +#include <linux/interrupt.h> +#include <linux/mm.h> +#include <linux/lzo.h> + +struct lzo_ctx { + void *lzo_mem; +}; + +static int lzo_init(struct crypto_tfm *tfm) +{ + struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->lzo_mem = vmalloc(LZO1X_MEM_COMPRESS); + + if (!ctx->lzo_mem) + return -ENOMEM; + + return 0; +} + +static void lzo_exit(struct crypto_tfm *tfm) +{ + struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); + + vfree(ctx->lzo_mem); +} + +static int lzo_compress(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) +{ + struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); + unsigned long compress_size; + int ret; + + /* Check if enough space in dst buffer for worst case expansion */ + if (*dlen < lzo1x_worst_compress(slen)) + return -EINVAL; + + ret = lzo1x_1_compress(src, slen, dst, &compress_size, ctx->lzo_mem); + + if (ret != LZO_E_OK) + return -EINVAL; + + *dlen = compress_size; + + return 0; +} + +static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) +{ + int ret; + unsigned long dest_len = *dlen; + + ret = lzo1x_decompress_safe(src, slen, dst, &dest_len, NULL); + + *dlen = dest_len; + + if (ret != LZO_E_OK) + return -EINVAL; + + return 0; +} + +static struct crypto_alg alg = { + .cra_name = "lzo1x", + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, + .cra_ctxsize = sizeof(struct lzo_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_init = lzo_init, + .cra_exit = lzo_exit, + .cra_u = { .compress = { + .coa_compress = lzo_compress, + .coa_decompress = lzo_decompress } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LZO Compression Algorithm"); +MODULE_AUTHOR("Richard Purdie <[EMAIL PROTECTED]>"); + diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 8eaa5aa..5eb97dd 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -747,7 +747,7 @@ out: crypto_free_hash(tfm); } -static void test_deflate(void) +static void test_compress(char *algo, struct comp_testvec *testvec, int num_tests) { unsigned int i; char result[COMP_BUF_SIZE]; @@ -755,25 +755,25 @@ static void test_deflate(void) struct comp_testvec *tv; unsigned int tsize; - printk("\ntesting deflate compression\n"); + printk("\ntesting %s compression\n", algo); - tsize = sizeof (deflate_comp_tv_template); + tsize = sizeof(struct comp_testvec) * num_tests; if (tsize > TVMEMSIZE) { printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE); return; } - memcpy(tvmem, deflate_comp_tv_template, tsize); + memcpy(tvmem, testvec, tsize); tv = (void *)tvmem; - tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { - printk("failed to load transform for deflate\n"); + printk("failed to load transform for %s\n", algo); return; } - for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) { + for (i = 0; i < num_tests; i++) { int ilen, ret, dlen = COMP_BUF_SIZE; printk("test %u:\n", i + 1); @@ -792,26 +792,16 @@ static void test_deflate(void) ilen, dlen); } - printk("\ntesting deflate decompression\n"); + printk("\ntesting %s decompression\n", algo); - tsize = sizeof (deflate_decomp_tv_template); - if (tsize > TVMEMSIZE) { - printk("template (%u) too big for tvmem (%u)\n", tsize, - TVMEMSIZE); - goto out; - } - - memcpy(tvmem, deflate_decomp_tv_template, tsize); - tv = (void *)tvmem; - - for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) { + for (i = 0; i < num_tests; i++) { int ilen, ret, dlen = COMP_BUF_SIZE; printk("test %u:\n", i + 1); memset(result, 0, sizeof (result)); - ilen = tv[i].inlen; - ret = crypto_comp_decompress(tfm, tv[i].input, + ilen = tv[i].outlen; + ret = crypto_comp_decompress(tfm, tv[i].output, ilen, result, &dlen); if (ret) { printk("fail: ret=%d\n", ret); @@ -819,7 +809,7 @@ static void test_deflate(void) } hexdump(result, dlen); printk("%s (ratio %d:%d)\n", - memcmp(result, tv[i].output, dlen) ? "fail" : "pass", + memcmp(result, tv[i].input, dlen) ? "fail" : "pass", ilen, dlen); } out: @@ -994,7 +984,8 @@ static void do_test(void) test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS); test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS); test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS); - test_deflate(); + test_compress("deflate", deflate_tv_template, DEFLATE_TEST_VECTORS); + test_compress("lzo1x", lzo1x_tv_template, LZO1X_TEST_VECTORS); test_hash("crc32c", crc32c_tv_template, CRC32C_TEST_VECTORS); test_hash("hmac(md5)", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); @@ -1100,7 +1091,7 @@ static void do_test(void) break; case 13: - test_deflate(); + test_compress("deflate", deflate_tv_template, DEFLATE_TEST_VECTORS); break; case 14: @@ -1225,6 +1216,10 @@ static void do_test(void) CAMELLIA_CBC_DEC_TEST_VECTORS); break; + case 33: + test_compress("lzo1x", lzo1x_tv_template, LZO1X_TEST_VECTORS); + break; + case 100: test_hash("hmac(md5)", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h index 887527b..01eb33c 100644 --- a/crypto/tcrypt.h +++ b/crypto/tcrypt.h @@ -3846,10 +3846,9 @@ struct comp_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 +#define DEFLATE_TEST_VECTORS 2 -static struct comp_testvec deflate_comp_tv_template[] = { +static struct comp_testvec deflate_tv_template[] = { { .inlen = 70, .outlen = 38, @@ -3885,39 +3884,49 @@ static struct comp_testvec deflate_comp_tv_template[] = { }, }; -static struct comp_testvec deflate_decomp_tv_template[] = { +/* + * LZO test vectors + */ +#define LZO1X_TEST_VECTORS 2 + +static struct comp_testvec lzo1x_tv_template[] = { { - .inlen = 122, - .outlen = 191, - .input = { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04, - 0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09, - 0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8, - 0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49, - 0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27, - 0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2, - 0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad, - 0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4, - 0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b, - 0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f, - 0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf, - 0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02, - 0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98, - 0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a, - 0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79, - 0xfa, 0x02 }, - .output = "This document describes a compression method based on the DEFLATE" + .inlen = 70, + .outlen = 46, + .input = "Join us now and share the software " + "Join us now and share the software ", + .output = { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75, + 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74, + 0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e, + 0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 }, + }, { + .inlen = 191, + .outlen = 153, + .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.", - }, { - .inlen = 38, - .outlen = 70, - .input = { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56, - 0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51, - 0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9, - 0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07, - 0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 }, - .output = "Join us now and share the software " - "Join us now and share the software ", + .output = { 0x00, 0x2f, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64, + 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, + 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, + 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62, + 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x44, 0x45, 0x46, 0x4c, + 0x41, 0x54, 0x45, 0x2a, 0x98, 0x00, 0x0d, 0x61, + 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, + 0x2e, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x2a, + 0x60, 0x01, 0x02, 0x66, 0x69, 0x6e, 0x65, 0x73, + 0x80, 0x07, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x62, 0x0b, 0x6f, 0x66, 0x88, + 0x02, 0xcd, 0x09, 0x20, 0x27, 0x03, 0x01, 0x20, + 0x74, 0x6f, 0x80, 0x03, 0x09, 0x49, 0x50, 0x20, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, + 0x43, 0x29, 0x3c, 0x02, 0x06, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x11, 0x00, + 0x00 }, }, }; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/