The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/crypto/deflate.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Cryptographic API.
    3  *
    4  * Deflate algorithm (RFC 1951), implemented here primarily for use
    5  * by IPCOMP (RFC 3173 & RFC 2394).
    6  *
    7  * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
    8  *
    9  * This program is free software; you can redistribute it and/or modify it
   10  * under the terms of the GNU General Public License as published by the Free
   11  * Software Foundation; either version 2 of the License, or (at your option)
   12  * any later version.
   13  *
   14  * FIXME: deflate transforms will require up to a total of about 436k of kernel
   15  * memory on i386 (390k for compression, the rest for decompression), as the
   16  * current zlib kernel code uses a worst case pre-allocation system by default.
   17  * This needs to be fixed so that the amount of memory required is properly
   18  * related to the  winbits and memlevel parameters.
   19  *
   20  * The default winbits of 11 should suit most packets, and it may be something
   21  * to configure on a per-tfm basis in the future.
   22  *
   23  * Currently, compression history is not maintained between tfm calls, as
   24  * it is not needed for IPCOMP and keeps the code simpler.  It can be
   25  * implemented if someone wants it.
   26  */
   27 #include <linux/init.h>
   28 #include <linux/module.h>
   29 #include <linux/crypto.h>
   30 #include <linux/zlib.h>
   31 #include <linux/vmalloc.h>
   32 #include <linux/interrupt.h>
   33 #include <linux/mm.h>
   34 #include <linux/net.h>
   35 
   36 #define DEFLATE_DEF_LEVEL               Z_DEFAULT_COMPRESSION
   37 #define DEFLATE_DEF_WINBITS             11
   38 #define DEFLATE_DEF_MEMLEVEL            MAX_MEM_LEVEL
   39 
   40 struct deflate_ctx {
   41         struct z_stream_s comp_stream;
   42         struct z_stream_s decomp_stream;
   43 };
   44 
   45 static int deflate_comp_init(struct deflate_ctx *ctx)
   46 {
   47         int ret = 0;
   48         struct z_stream_s *stream = &ctx->comp_stream;
   49 
   50         stream->workspace = vzalloc(zlib_deflate_workspacesize(
   51                                 -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL));
   52         if (!stream->workspace) {
   53                 ret = -ENOMEM;
   54                 goto out;
   55         }
   56         ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
   57                                 -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
   58                                 Z_DEFAULT_STRATEGY);
   59         if (ret != Z_OK) {
   60                 ret = -EINVAL;
   61                 goto out_free;
   62         }
   63 out:
   64         return ret;
   65 out_free:
   66         vfree(stream->workspace);
   67         goto out;
   68 }
   69 
   70 static int deflate_decomp_init(struct deflate_ctx *ctx)
   71 {
   72         int ret = 0;
   73         struct z_stream_s *stream = &ctx->decomp_stream;
   74 
   75         stream->workspace = vzalloc(zlib_inflate_workspacesize());
   76         if (!stream->workspace) {
   77                 ret = -ENOMEM;
   78                 goto out;
   79         }
   80         ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
   81         if (ret != Z_OK) {
   82                 ret = -EINVAL;
   83                 goto out_free;
   84         }
   85 out:
   86         return ret;
   87 out_free:
   88         vfree(stream->workspace);
   89         goto out;
   90 }
   91 
   92 static void deflate_comp_exit(struct deflate_ctx *ctx)
   93 {
   94         zlib_deflateEnd(&ctx->comp_stream);
   95         vfree(ctx->comp_stream.workspace);
   96 }
   97 
   98 static void deflate_decomp_exit(struct deflate_ctx *ctx)
   99 {
  100         zlib_inflateEnd(&ctx->decomp_stream);
  101         vfree(ctx->decomp_stream.workspace);
  102 }
  103 
  104 static int deflate_init(struct crypto_tfm *tfm)
  105 {
  106         struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
  107         int ret;
  108 
  109         ret = deflate_comp_init(ctx);
  110         if (ret)
  111                 goto out;
  112         ret = deflate_decomp_init(ctx);
  113         if (ret)
  114                 deflate_comp_exit(ctx);
  115 out:
  116         return ret;
  117 }
  118 
  119 static void deflate_exit(struct crypto_tfm *tfm)
  120 {
  121         struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
  122 
  123         deflate_comp_exit(ctx);
  124         deflate_decomp_exit(ctx);
  125 }
  126 
  127 static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
  128                             unsigned int slen, u8 *dst, unsigned int *dlen)
  129 {
  130         int ret = 0;
  131         struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
  132         struct z_stream_s *stream = &dctx->comp_stream;
  133 
  134         ret = zlib_deflateReset(stream);
  135         if (ret != Z_OK) {
  136                 ret = -EINVAL;
  137                 goto out;
  138         }
  139 
  140         stream->next_in = (u8 *)src;
  141         stream->avail_in = slen;
  142         stream->next_out = (u8 *)dst;
  143         stream->avail_out = *dlen;
  144 
  145         ret = zlib_deflate(stream, Z_FINISH);
  146         if (ret != Z_STREAM_END) {
  147                 ret = -EINVAL;
  148                 goto out;
  149         }
  150         ret = 0;
  151         *dlen = stream->total_out;
  152 out:
  153         return ret;
  154 }
  155 
  156 static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
  157                               unsigned int slen, u8 *dst, unsigned int *dlen)
  158 {
  159 
  160         int ret = 0;
  161         struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
  162         struct z_stream_s *stream = &dctx->decomp_stream;
  163 
  164         ret = zlib_inflateReset(stream);
  165         if (ret != Z_OK) {
  166                 ret = -EINVAL;
  167                 goto out;
  168         }
  169 
  170         stream->next_in = (u8 *)src;
  171         stream->avail_in = slen;
  172         stream->next_out = (u8 *)dst;
  173         stream->avail_out = *dlen;
  174 
  175         ret = zlib_inflate(stream, Z_SYNC_FLUSH);
  176         /*
  177          * Work around a bug in zlib, which sometimes wants to taste an extra
  178          * byte when being used in the (undocumented) raw deflate mode.
  179          * (From USAGI).
  180          */
  181         if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
  182                 u8 zerostuff = 0;
  183                 stream->next_in = &zerostuff;
  184                 stream->avail_in = 1;
  185                 ret = zlib_inflate(stream, Z_FINISH);
  186         }
  187         if (ret != Z_STREAM_END) {
  188                 ret = -EINVAL;
  189                 goto out;
  190         }
  191         ret = 0;
  192         *dlen = stream->total_out;
  193 out:
  194         return ret;
  195 }
  196 
  197 static struct crypto_alg alg = {
  198         .cra_name               = "deflate",
  199         .cra_flags              = CRYPTO_ALG_TYPE_COMPRESS,
  200         .cra_ctxsize            = sizeof(struct deflate_ctx),
  201         .cra_module             = THIS_MODULE,
  202         .cra_init               = deflate_init,
  203         .cra_exit               = deflate_exit,
  204         .cra_u                  = { .compress = {
  205         .coa_compress           = deflate_compress,
  206         .coa_decompress         = deflate_decompress } }
  207 };
  208 
  209 static int __init deflate_mod_init(void)
  210 {
  211         return crypto_register_alg(&alg);
  212 }
  213 
  214 static void __exit deflate_mod_fini(void)
  215 {
  216         crypto_unregister_alg(&alg);
  217 }
  218 
  219 module_init(deflate_mod_init);
  220 module_exit(deflate_mod_fini);
  221 
  222 MODULE_LICENSE("GPL");
  223 MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
  224 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
  225 

Cache object: ecf45b4a3b822956611d802277786648


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.