Back to home page

LXR

 
 

    


0001 /*
0002  * Cryptographic API.
0003  *
0004  * Deflate algorithm (RFC 1951), implemented here primarily for use
0005  * by IPCOMP (RFC 3173 & RFC 2394).
0006  *
0007  * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
0008  *
0009  * This program is free software; you can redistribute it and/or modify it
0010  * under the terms of the GNU General Public License as published by the Free
0011  * Software Foundation; either version 2 of the License, or (at your option)
0012  * any later version.
0013  *
0014  * FIXME: deflate transforms will require up to a total of about 436k of kernel
0015  * memory on i386 (390k for compression, the rest for decompression), as the
0016  * current zlib kernel code uses a worst case pre-allocation system by default.
0017  * This needs to be fixed so that the amount of memory required is properly
0018  * related to the  winbits and memlevel parameters.
0019  *
0020  * The default winbits of 11 should suit most packets, and it may be something
0021  * to configure on a per-tfm basis in the future.
0022  *
0023  * Currently, compression history is not maintained between tfm calls, as
0024  * it is not needed for IPCOMP and keeps the code simpler.  It can be
0025  * implemented if someone wants it.
0026  */
0027 #include <linux/init.h>
0028 #include <linux/module.h>
0029 #include <linux/crypto.h>
0030 #include <linux/zlib.h>
0031 #include <linux/vmalloc.h>
0032 #include <linux/interrupt.h>
0033 #include <linux/mm.h>
0034 #include <linux/net.h>
0035 #include <crypto/internal/scompress.h>
0036 
0037 #define DEFLATE_DEF_LEVEL       Z_DEFAULT_COMPRESSION
0038 #define DEFLATE_DEF_WINBITS     11
0039 #define DEFLATE_DEF_MEMLEVEL        MAX_MEM_LEVEL
0040 
0041 struct deflate_ctx {
0042     struct z_stream_s comp_stream;
0043     struct z_stream_s decomp_stream;
0044 };
0045 
0046 static int deflate_comp_init(struct deflate_ctx *ctx)
0047 {
0048     int ret = 0;
0049     struct z_stream_s *stream = &ctx->comp_stream;
0050 
0051     stream->workspace = vzalloc(zlib_deflate_workspacesize(
0052                 -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL));
0053     if (!stream->workspace) {
0054         ret = -ENOMEM;
0055         goto out;
0056     }
0057     ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
0058                             -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
0059                             Z_DEFAULT_STRATEGY);
0060     if (ret != Z_OK) {
0061         ret = -EINVAL;
0062         goto out_free;
0063     }
0064 out:
0065     return ret;
0066 out_free:
0067     vfree(stream->workspace);
0068     goto out;
0069 }
0070 
0071 static int deflate_decomp_init(struct deflate_ctx *ctx)
0072 {
0073     int ret = 0;
0074     struct z_stream_s *stream = &ctx->decomp_stream;
0075 
0076     stream->workspace = vzalloc(zlib_inflate_workspacesize());
0077     if (!stream->workspace) {
0078         ret = -ENOMEM;
0079         goto out;
0080     }
0081     ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
0082     if (ret != Z_OK) {
0083         ret = -EINVAL;
0084         goto out_free;
0085     }
0086 out:
0087     return ret;
0088 out_free:
0089     vfree(stream->workspace);
0090     goto out;
0091 }
0092 
0093 static void deflate_comp_exit(struct deflate_ctx *ctx)
0094 {
0095     zlib_deflateEnd(&ctx->comp_stream);
0096     vfree(ctx->comp_stream.workspace);
0097 }
0098 
0099 static void deflate_decomp_exit(struct deflate_ctx *ctx)
0100 {
0101     zlib_inflateEnd(&ctx->decomp_stream);
0102     vfree(ctx->decomp_stream.workspace);
0103 }
0104 
0105 static int __deflate_init(void *ctx)
0106 {
0107     int ret;
0108 
0109     ret = deflate_comp_init(ctx);
0110     if (ret)
0111         goto out;
0112     ret = deflate_decomp_init(ctx);
0113     if (ret)
0114         deflate_comp_exit(ctx);
0115 out:
0116     return ret;
0117 }
0118 
0119 static void *deflate_alloc_ctx(struct crypto_scomp *tfm)
0120 {
0121     struct deflate_ctx *ctx;
0122     int ret;
0123 
0124     ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
0125     if (!ctx)
0126         return ERR_PTR(-ENOMEM);
0127 
0128     ret = __deflate_init(ctx);
0129     if (ret) {
0130         kfree(ctx);
0131         return ERR_PTR(ret);
0132     }
0133 
0134     return ctx;
0135 }
0136 
0137 static int deflate_init(struct crypto_tfm *tfm)
0138 {
0139     struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
0140 
0141     return __deflate_init(ctx);
0142 }
0143 
0144 static void __deflate_exit(void *ctx)
0145 {
0146     deflate_comp_exit(ctx);
0147     deflate_decomp_exit(ctx);
0148 }
0149 
0150 static void deflate_free_ctx(struct crypto_scomp *tfm, void *ctx)
0151 {
0152     __deflate_exit(ctx);
0153     kzfree(ctx);
0154 }
0155 
0156 static void deflate_exit(struct crypto_tfm *tfm)
0157 {
0158     struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
0159 
0160     __deflate_exit(ctx);
0161 }
0162 
0163 static int __deflate_compress(const u8 *src, unsigned int slen,
0164                   u8 *dst, unsigned int *dlen, void *ctx)
0165 {
0166     int ret = 0;
0167     struct deflate_ctx *dctx = ctx;
0168     struct z_stream_s *stream = &dctx->comp_stream;
0169 
0170     ret = zlib_deflateReset(stream);
0171     if (ret != Z_OK) {
0172         ret = -EINVAL;
0173         goto out;
0174     }
0175 
0176     stream->next_in = (u8 *)src;
0177     stream->avail_in = slen;
0178     stream->next_out = (u8 *)dst;
0179     stream->avail_out = *dlen;
0180 
0181     ret = zlib_deflate(stream, Z_FINISH);
0182     if (ret != Z_STREAM_END) {
0183         ret = -EINVAL;
0184         goto out;
0185     }
0186     ret = 0;
0187     *dlen = stream->total_out;
0188 out:
0189     return ret;
0190 }
0191 
0192 static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
0193                 unsigned int slen, u8 *dst, unsigned int *dlen)
0194 {
0195     struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
0196 
0197     return __deflate_compress(src, slen, dst, dlen, dctx);
0198 }
0199 
0200 static int deflate_scompress(struct crypto_scomp *tfm, const u8 *src,
0201                  unsigned int slen, u8 *dst, unsigned int *dlen,
0202                  void *ctx)
0203 {
0204     return __deflate_compress(src, slen, dst, dlen, ctx);
0205 }
0206 
0207 static int __deflate_decompress(const u8 *src, unsigned int slen,
0208                 u8 *dst, unsigned int *dlen, void *ctx)
0209 {
0210 
0211     int ret = 0;
0212     struct deflate_ctx *dctx = ctx;
0213     struct z_stream_s *stream = &dctx->decomp_stream;
0214 
0215     ret = zlib_inflateReset(stream);
0216     if (ret != Z_OK) {
0217         ret = -EINVAL;
0218         goto out;
0219     }
0220 
0221     stream->next_in = (u8 *)src;
0222     stream->avail_in = slen;
0223     stream->next_out = (u8 *)dst;
0224     stream->avail_out = *dlen;
0225 
0226     ret = zlib_inflate(stream, Z_SYNC_FLUSH);
0227     /*
0228      * Work around a bug in zlib, which sometimes wants to taste an extra
0229      * byte when being used in the (undocumented) raw deflate mode.
0230      * (From USAGI).
0231      */
0232     if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
0233         u8 zerostuff = 0;
0234         stream->next_in = &zerostuff;
0235         stream->avail_in = 1;
0236         ret = zlib_inflate(stream, Z_FINISH);
0237     }
0238     if (ret != Z_STREAM_END) {
0239         ret = -EINVAL;
0240         goto out;
0241     }
0242     ret = 0;
0243     *dlen = stream->total_out;
0244 out:
0245     return ret;
0246 }
0247 
0248 static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
0249                   unsigned int slen, u8 *dst, unsigned int *dlen)
0250 {
0251     struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
0252 
0253     return __deflate_decompress(src, slen, dst, dlen, dctx);
0254 }
0255 
0256 static int deflate_sdecompress(struct crypto_scomp *tfm, const u8 *src,
0257                    unsigned int slen, u8 *dst, unsigned int *dlen,
0258                    void *ctx)
0259 {
0260     return __deflate_decompress(src, slen, dst, dlen, ctx);
0261 }
0262 
0263 static struct crypto_alg alg = {
0264     .cra_name       = "deflate",
0265     .cra_flags      = CRYPTO_ALG_TYPE_COMPRESS,
0266     .cra_ctxsize        = sizeof(struct deflate_ctx),
0267     .cra_module     = THIS_MODULE,
0268     .cra_init       = deflate_init,
0269     .cra_exit       = deflate_exit,
0270     .cra_u          = { .compress = {
0271     .coa_compress       = deflate_compress,
0272     .coa_decompress     = deflate_decompress } }
0273 };
0274 
0275 static struct scomp_alg scomp = {
0276     .alloc_ctx      = deflate_alloc_ctx,
0277     .free_ctx       = deflate_free_ctx,
0278     .compress       = deflate_scompress,
0279     .decompress     = deflate_sdecompress,
0280     .base           = {
0281         .cra_name   = "deflate",
0282         .cra_driver_name = "deflate-scomp",
0283         .cra_module  = THIS_MODULE,
0284     }
0285 };
0286 
0287 static int __init deflate_mod_init(void)
0288 {
0289     int ret;
0290 
0291     ret = crypto_register_alg(&alg);
0292     if (ret)
0293         return ret;
0294 
0295     ret = crypto_register_scomp(&scomp);
0296     if (ret) {
0297         crypto_unregister_alg(&alg);
0298         return ret;
0299     }
0300 
0301     return ret;
0302 }
0303 
0304 static void __exit deflate_mod_fini(void)
0305 {
0306     crypto_unregister_alg(&alg);
0307     crypto_unregister_scomp(&scomp);
0308 }
0309 
0310 module_init(deflate_mod_init);
0311 module_exit(deflate_mod_fini);
0312 
0313 MODULE_LICENSE("GPL");
0314 MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
0315 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
0316 MODULE_ALIAS_CRYPTO("deflate");