diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-04 09:06:34 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-04 09:06:34 -0700 |
commit | d66e6737d454553e1e62109d8298ede5351178a4 (patch) | |
tree | c28b205045935b111527f461d2b114daa26e4fb8 /crypto/842.c | |
parent | 612a9aab56a93533e76e3ad91642db7033e03b69 (diff) | |
parent | c9f97a27ceee84998999bf3341e6d5d207b05539 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto update from Herbert Xu:
- Optimised AES/SHA1 for ARM.
- IPsec ESN support in talitos and caam.
- x86_64/avx implementation of cast5/cast6.
- Add/use multi-algorithm registration helpers where possible.
- Added IBM Power7+ in-Nest support.
- Misc fixes.
Fix up trivial conflicts in crypto/Kconfig due to the sparc64 crypto
config options being added next to the new ARM ones.
[ Side note: cut-and-paste duplicate help texts make those conflicts
harder to read than necessary, thanks to git being smart about
minimizing conflicts and maximizing the common parts... ]
* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (71 commits)
crypto: x86/glue_helper - fix storing of new IV in CBC encryption
crypto: cast5/avx - fix storing of new IV in CBC encryption
crypto: tcrypt - add missing tests for camellia and ghash
crypto: testmgr - make test_aead also test 'dst != src' code paths
crypto: testmgr - make test_skcipher also test 'dst != src' code paths
crypto: testmgr - add test vectors for CTR mode IV increasement
crypto: testmgr - add test vectors for partial ctr(cast5) and ctr(cast6)
crypto: testmgr - allow non-multi page and multi page skcipher tests from same test template
crypto: caam - increase TRNG clocks per sample
crypto, tcrypt: remove local_bh_disable/enable() around local_irq_disable/enable()
crypto: tegra-aes - fix error return code
crypto: crypto4xx - fix error return code
crypto: hifn_795x - fix error return code
crypto: ux500 - fix error return code
crypto: caam - fix error IDs for SEC v5.x RNG4
hwrng: mxc-rnga - Access data via structure
hwrng: mxc-rnga - Adapt clocks to new i.mx clock framework
crypto: caam - add IPsec ESN support
crypto: 842 - remove .cra_list initialization
Revert "[CRYPTO] cast6: inline bloat--"
...
Diffstat (limited to 'crypto/842.c')
-rw-r--r-- | crypto/842.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/crypto/842.c b/crypto/842.c new file mode 100644 index 000000000000..65c7a89cfa09 --- /dev/null +++ b/crypto/842.c @@ -0,0 +1,182 @@ +/* + * Cryptographic API for the 842 compression algorithm. + * + * 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. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (C) IBM Corporation, 2011 + * + * Authors: Robert Jennings <rcj@linux.vnet.ibm.com> + * Seth Jennings <sjenning@linux.vnet.ibm.com> + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/crypto.h> +#include <linux/vmalloc.h> +#include <linux/nx842.h> +#include <linux/lzo.h> +#include <linux/timer.h> + +static int nx842_uselzo; + +struct nx842_ctx { + void *nx842_wmem; /* working memory for 842/lzo */ +}; + +enum nx842_crypto_type { + NX842_CRYPTO_TYPE_842, + NX842_CRYPTO_TYPE_LZO +}; + +#define NX842_SENTINEL 0xdeadbeef + +struct nx842_crypto_header { + unsigned int sentinel; /* debug */ + enum nx842_crypto_type type; +}; + +static int nx842_init(struct crypto_tfm *tfm) +{ + struct nx842_ctx *ctx = crypto_tfm_ctx(tfm); + int wmemsize; + + wmemsize = max_t(int, nx842_get_workmem_size(), LZO1X_MEM_COMPRESS); + ctx->nx842_wmem = kmalloc(wmemsize, GFP_NOFS); + if (!ctx->nx842_wmem) + return -ENOMEM; + + return 0; +} + +static void nx842_exit(struct crypto_tfm *tfm) +{ + struct nx842_ctx *ctx = crypto_tfm_ctx(tfm); + + kfree(ctx->nx842_wmem); +} + +static void nx842_reset_uselzo(unsigned long data) +{ + nx842_uselzo = 0; +} + +static DEFINE_TIMER(failover_timer, nx842_reset_uselzo, 0, 0); + +static int nx842_crypto_compress(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) +{ + struct nx842_ctx *ctx = crypto_tfm_ctx(tfm); + struct nx842_crypto_header *hdr; + unsigned int tmp_len = *dlen; + size_t lzodlen; /* needed for lzo */ + int err; + + *dlen = 0; + hdr = (struct nx842_crypto_header *)dst; + hdr->sentinel = NX842_SENTINEL; /* debug */ + dst += sizeof(struct nx842_crypto_header); + tmp_len -= sizeof(struct nx842_crypto_header); + lzodlen = tmp_len; + + if (likely(!nx842_uselzo)) { + err = nx842_compress(src, slen, dst, &tmp_len, ctx->nx842_wmem); + + if (likely(!err)) { + hdr->type = NX842_CRYPTO_TYPE_842; + *dlen = tmp_len + sizeof(struct nx842_crypto_header); + return 0; + } + + /* hardware failed */ + nx842_uselzo = 1; + + /* set timer to check for hardware again in 1 second */ + mod_timer(&failover_timer, jiffies + msecs_to_jiffies(1000)); + } + + /* no hardware, use lzo */ + err = lzo1x_1_compress(src, slen, dst, &lzodlen, ctx->nx842_wmem); + if (err != LZO_E_OK) + return -EINVAL; + + hdr->type = NX842_CRYPTO_TYPE_LZO; + *dlen = lzodlen + sizeof(struct nx842_crypto_header); + return 0; +} + +static int nx842_crypto_decompress(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) +{ + struct nx842_ctx *ctx = crypto_tfm_ctx(tfm); + struct nx842_crypto_header *hdr; + unsigned int tmp_len = *dlen; + size_t lzodlen; /* needed for lzo */ + int err; + + *dlen = 0; + hdr = (struct nx842_crypto_header *)src; + + if (unlikely(hdr->sentinel != NX842_SENTINEL)) + return -EINVAL; + + src += sizeof(struct nx842_crypto_header); + slen -= sizeof(struct nx842_crypto_header); + + if (likely(hdr->type == NX842_CRYPTO_TYPE_842)) { + err = nx842_decompress(src, slen, dst, &tmp_len, + ctx->nx842_wmem); + if (err) + return -EINVAL; + *dlen = tmp_len; + } else if (hdr->type == NX842_CRYPTO_TYPE_LZO) { + lzodlen = tmp_len; + err = lzo1x_decompress_safe(src, slen, dst, &lzodlen); + if (err != LZO_E_OK) + return -EINVAL; + *dlen = lzodlen; + } else + return -EINVAL; + + return 0; +} + +static struct crypto_alg alg = { + .cra_name = "842", + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, + .cra_ctxsize = sizeof(struct nx842_ctx), + .cra_module = THIS_MODULE, + .cra_init = nx842_init, + .cra_exit = nx842_exit, + .cra_u = { .compress = { + .coa_compress = nx842_crypto_compress, + .coa_decompress = nx842_crypto_decompress } } +}; + +static int __init nx842_mod_init(void) +{ + del_timer(&failover_timer); + return crypto_register_alg(&alg); +} + +static void __exit nx842_mod_exit(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(nx842_mod_init); +module_exit(nx842_mod_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("842 Compression Algorithm"); |