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/opencrypto/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 /*      $NetBSD: deflate.c,v 1.23 2017/05/17 06:33:04 knakahara Exp $ */
    2 /*      $FreeBSD: src/sys/opencrypto/deflate.c,v 1.1.2.1 2002/11/21 23:34:23 sam Exp $  */
    3 /* $OpenBSD: deflate.c,v 1.3 2001/08/20 02:45:22 hugh Exp $ */
    4 
    5 /*
    6  * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  *
   12  * 1. Redistributions of source code must retain the above copyright
   13  *   notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *   notice, this list of conditions and the following disclaimer in the
   16  *   documentation and/or other materials provided with the distribution.
   17  * 3. The name of the author may not be used to endorse or promote products
   18  *   derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * This file contains a wrapper around the deflate algo compression
   34  * functions using the zlib library (see net/zlib.{c,h})
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: deflate.c,v 1.23 2017/05/17 06:33:04 knakahara Exp $");
   39 
   40 #include <sys/types.h>
   41 #include <sys/malloc.h>
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <net/zlib.h>
   45 
   46 #include <opencrypto/cryptodev.h>
   47 #include <opencrypto/deflate.h>
   48 
   49 #define ZBUF 10
   50 
   51 struct deflate_buf {
   52         u_int8_t *out;
   53         u_int32_t size;
   54 };
   55 
   56 int window_inflate = -1 * MAX_WBITS;
   57 int window_deflate = -12;
   58 
   59 /*
   60  * This function takes a block of data and (de)compress it using the deflate
   61  * algorithm
   62  */
   63 
   64 static void *
   65 ocf_zalloc(void *nil, u_int type, u_int size)
   66 {
   67         void *ptr;
   68 
   69         ptr = malloc(type *size, M_CRYPTO_DATA, M_NOWAIT);
   70         return ptr;
   71 }
   72 
   73 static void
   74 ocf_zfree(void *nil, void *ptr)
   75 {
   76         free(ptr, M_CRYPTO_DATA);
   77 }
   78 
   79 u_int32_t
   80 deflate_global(u_int8_t *data, u_int32_t size, int decomp, u_int8_t **out,
   81                int size_hint)
   82 {
   83         /* decomp indicates whether we compress (0) or decompress (1) */
   84 
   85         z_stream zbuf;
   86         u_int8_t *output;
   87         u_int32_t count, result, tocopy;
   88         int error, i, j;
   89         struct deflate_buf buf[ZBUF];
   90 
   91         DPRINTF("size %u\n", size);
   92 
   93         memset(&zbuf, 0, sizeof(z_stream));
   94         zbuf.next_in = data;    /* data that is going to be processed */
   95         zbuf.zalloc = ocf_zalloc;
   96         zbuf.zfree = ocf_zfree;
   97         zbuf.opaque = Z_NULL;
   98         zbuf.avail_in = size;   /* Total length of data to be processed */
   99 
  100         if (!decomp) {
  101                 buf[0].size = size;
  102         } else {
  103                 /*
  104                  * Choose a buffer with 4x the size of the input buffer
  105                  * for the size of the output buffer in the case of
  106                  * decompression. If it's not sufficient, it will need to be
  107                  * updated while the decompression is going on
  108                  */
  109 
  110                 buf[0].size = MAX(size * 4, size_hint);
  111         }
  112         buf[0].out = malloc(buf[0].size, M_CRYPTO_DATA, M_NOWAIT);
  113         if (buf[0].out == NULL)
  114                 return 0;
  115         i = 1;
  116 
  117         zbuf.next_out = buf[0].out;
  118         zbuf.avail_out = buf[0].size;
  119 
  120         error = decomp ? inflateInit2(&zbuf, window_inflate) :
  121             deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
  122                     window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
  123 
  124         if (error != Z_OK)
  125                 goto bad2;
  126         for (;;) {
  127                 error = decomp ? inflate(&zbuf, Z_SYNC_FLUSH) :
  128                                  deflate(&zbuf, Z_FINISH);
  129                 if (error == Z_STREAM_END) /* success */
  130                         break;
  131                 /*
  132                  * XXX compensate for two problems:
  133                  * -Former versions of this code didn't set Z_FINISH
  134                  *  on compression, so the compressed data are not correctly
  135                  *  terminated and the decompressor doesn't get Z_STREAM_END.
  136                  *  Accept such packets for interoperability.
  137                  * -sys/net/zlib.c has a bug which makes that Z_BUF_ERROR is
  138                  *  set after successful decompression under rare conditions.
  139                  */
  140                 else if (decomp && (error == Z_OK || error == Z_BUF_ERROR)
  141                          && zbuf.avail_in == 0 && zbuf.avail_out != 0)
  142                                 break;
  143                 else if (error != Z_OK)
  144                         goto bad;
  145                 else if (zbuf.avail_out == 0) {
  146                         /* we need more output space, allocate size */
  147                         int nextsize = buf[i-1].size * 2;
  148                         if (i == ZBUF || nextsize > 1000000)
  149                                 goto bad;
  150                         buf[i].out = malloc(nextsize, M_CRYPTO_DATA, M_NOWAIT);
  151                         if (buf[i].out == NULL)
  152                                 goto bad;
  153                         zbuf.next_out = buf[i].out;
  154                         zbuf.avail_out = buf[i].size = nextsize;
  155                         i++;
  156                 }
  157         }
  158 
  159         result = count = zbuf.total_out;
  160 
  161         if (i != 1) { /* copy everything into one buffer */
  162                 output = malloc(result, M_CRYPTO_DATA, M_NOWAIT);
  163                 if (output == NULL)
  164                         goto bad;
  165                 *out = output;
  166                 for (j = 0; j < i; j++) {
  167                         tocopy = MIN(count, buf[j].size);
  168                         /* XXX the last buf can be empty */
  169                         KASSERT(tocopy || j == (i - 1));
  170                         memcpy(output, buf[j].out, tocopy);
  171                         output += tocopy;
  172                         free(buf[j].out, M_CRYPTO_DATA);
  173                         count -= tocopy;
  174                 }
  175                 KASSERT(count == 0);
  176         } else {
  177                 *out = buf[0].out;
  178         }
  179         if (decomp)
  180                 inflateEnd(&zbuf);
  181         else
  182                 deflateEnd(&zbuf);
  183         return result;
  184 
  185 bad:
  186         if (decomp)
  187                 inflateEnd(&zbuf);
  188         else
  189                 deflateEnd(&zbuf);
  190 bad2:
  191         for (j = 0; j < i; j++)
  192                 free(buf[j].out, M_CRYPTO_DATA);
  193         return 0;
  194 }
  195 
  196 /*
  197  * Initial version will perform a single gzip encapsulation,
  198  * filling in the header,
  199  * and appending the crc and uncompressed length.
  200  *
  201  * Later version will support multiple buffers with 
  202  * a flag indication final buffer.  The crc is maintained
  203  * over all buffers and appended to the output along with 
  204  * the uncompressed length after the final data buffer
  205  * has been compressed and output.
  206  *
  207  * Ditto for uncompress - CRC is extracted from the final packed
  208  * and compared against CRC of uncompressed data.
  209  *
  210  */
  211 
  212 /* constant header for the gzip */
  213 static const char gzip_header[10] = {
  214         0x1f, 0x8b,     /* ID1 ID2      */
  215         Z_DEFLATED,     /* CM           */
  216         0,              /* FLG          */
  217         0, 0, 0, 0,     /* MTIME        */
  218         0,              /* XFL          */
  219         0x03            /* OS (Unix)    */
  220 };
  221 
  222 /* Followed by compressed payload */
  223 /* Followed by uint32_t CRC32 and uint32_t ISIZE */
  224 #define GZIP_TAIL_SIZE  8
  225 
  226 u_int32_t
  227 gzip_global(u_int8_t *data, u_int32_t size,
  228         int decomp, u_int8_t **out, int size_hint)
  229 {
  230         /* decomp indicates whether we compress (0) or decompress (1) */
  231         z_stream zbuf;
  232         u_int8_t *output;
  233         u_int32_t count, result;
  234         int error, i, j;
  235         struct deflate_buf buf[ZBUF];
  236         u_int32_t crc;
  237         u_int32_t isize = 0, icrc = 0;
  238 
  239         DPRINTF("decomp %d, size %u\n", decomp, size);
  240 
  241         memset(&zbuf, 0, sizeof(z_stream));
  242         zbuf.zalloc = ocf_zalloc;
  243         zbuf.zfree = ocf_zfree;
  244         zbuf.opaque = Z_NULL;
  245 
  246         if (!decomp) {
  247                 /* compress */
  248                 DPRINTF("compress malloc %u + %zu + %u = %zu\n",
  249                                 size, sizeof(gzip_header), GZIP_TAIL_SIZE,
  250                                 size + sizeof(gzip_header) + GZIP_TAIL_SIZE);
  251 
  252                 buf[0].size = size;
  253                 crc = crc32(0, data, size);
  254                 DPRINTF("size %u, crc 0x%x\n", size, crc);
  255                 zbuf.avail_in = size;   /* Total length of data to be processed */
  256                 zbuf.next_in = data;    /* data that is going to be processed */
  257         } else {
  258                 /* decompress */
  259                 /* check the gzip header */
  260                 if (size <= sizeof(gzip_header) + GZIP_TAIL_SIZE) {
  261                         /* Not enough data for the header & tail */
  262                         DPRINTF("not enough data (%u)\n", size);
  263                         return 0;
  264                 }
  265 
  266                 /* XXX this is pretty basic,
  267                  * needs to be expanded to ignore MTIME, OS, 
  268                  * but still ensure flags are 0.
  269                  * Q. Do we need to support the flags and 
  270                  * optional header fields? Likely.
  271                  * XXX add flag and field support too.
  272                  */
  273                 if (memcmp(data, gzip_header, sizeof(gzip_header)) != 0) {
  274                         DPRINTF("unsupported gzip header (%02x%02x)\n",
  275                                         data[0], data[1]);
  276                         return 0;
  277                 } else {
  278                         DPRINTF("%d: gzip header ok\n",__LINE__);
  279                 }
  280 
  281                 memcpy(&isize, &data[size-sizeof(uint32_t)], sizeof(uint32_t));
  282                 LE32TOH(isize);
  283                 memcpy(&icrc, &data[size-2*sizeof(uint32_t)], sizeof(uint32_t));
  284                 LE32TOH(icrc);
  285 
  286                 DPRINTF("isize = %u (%02x %02x %02x %02x)\n",
  287                                 isize,
  288                                 data[size-4],
  289                                 data[size-3],
  290                                 data[size-2],
  291                                 data[size-1]);
  292 
  293                 buf[0].size = isize;
  294                 crc = crc32(0, NULL, 0);        /* get initial crc value */
  295 
  296                 /* skip over the gzip header */
  297                 zbuf.next_in = data + sizeof(gzip_header);
  298 
  299                 /* actual payload size stripped of gzip header and tail */
  300                 zbuf.avail_in = size - sizeof(gzip_header) - GZIP_TAIL_SIZE;
  301         }
  302 
  303         buf[0].out = malloc(buf[0].size, M_CRYPTO_DATA, M_NOWAIT);
  304         if (buf[0].out == NULL)
  305                 return 0;
  306         zbuf.next_out = buf[0].out;
  307         zbuf.avail_out = buf[0].size;
  308         DPRINTF("zbuf avail_in %u, avail_out %u\n",
  309                         zbuf.avail_in, zbuf.avail_out);
  310         i = 1;
  311 
  312         error = decomp ? inflateInit2(&zbuf, window_inflate) :
  313             deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
  314                     window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
  315 
  316         if (error != Z_OK) {
  317                 printf("deflateInit2() failed\n");
  318                 goto bad2;
  319         }
  320         for (;;) {
  321                 DPRINTF("pre: %s in:%u out:%u\n", decomp ? "deflate()" : "inflate()", 
  322                                 zbuf.avail_in, zbuf.avail_out);
  323                 error = decomp ? inflate(&zbuf, Z_SYNC_FLUSH) :
  324                                  deflate(&zbuf, Z_FINISH);
  325                 DPRINTF("post: %s in:%u out:%u\n", decomp ? "deflate()" : "inflate()", 
  326                                 zbuf.avail_in, zbuf.avail_out);
  327                 if (error == Z_STREAM_END) /* success */
  328                         break;
  329                 /*
  330                  * XXX compensate for a zlib problem:
  331                  * -sys/net/zlib.c has a bug which makes that Z_BUF_ERROR is
  332                  *  set after successful decompression under rare conditions.
  333                  */
  334                 else if (decomp && error == Z_BUF_ERROR
  335                          && zbuf.avail_in == 0 && zbuf.avail_out != 0)
  336                                 break;
  337                 else if (error != Z_OK)
  338                         goto bad;
  339                 else if (zbuf.avail_out == 0) {
  340                         /* we need more output space, allocate size */
  341                         int nextsize = buf[i-1].size * 2;
  342                         if (i == ZBUF || nextsize > 1000000)
  343                                 goto bad;
  344                         buf[i].out = malloc(nextsize, M_CRYPTO_DATA, M_NOWAIT);
  345                         if (buf[i].out == NULL)
  346                                 goto bad;
  347                         zbuf.next_out = buf[i].out;
  348                         zbuf.avail_out = buf[i].size = nextsize;
  349                         i++;
  350                 }
  351         }
  352 
  353         if (decomp) {
  354                 count = result = zbuf.total_out;
  355         } else {
  356                 /* need room for header, CRC, and ISIZE */
  357                 result = zbuf.total_out + sizeof(gzip_header) + GZIP_TAIL_SIZE;
  358                 count = zbuf.total_out;
  359         }
  360 
  361         DPRINTF("in %u -> out %u\n", size, result);
  362 
  363         *out = malloc(result, M_CRYPTO_DATA, M_NOWAIT);
  364         if (*out == NULL)
  365                 goto bad;
  366         output = *out;
  367         if (decomp)
  368                 inflateEnd(&zbuf);
  369         else {
  370                 deflateEnd(&zbuf);
  371 
  372                 /* fill in gzip header */
  373                 memcpy(output, gzip_header, sizeof(gzip_header));
  374                 output += sizeof(gzip_header);
  375         }
  376         for (j = 0; j < i; j++) {
  377                 if (decomp) {
  378                         /* update crc for decompressed data */
  379                         crc = crc32(crc, buf[j].out, MIN(count, buf[j].size));
  380                 }
  381                 if (count > buf[j].size) {
  382                         memcpy(output, buf[j].out, buf[j].size);
  383                         output += buf[j].size;
  384                         free(buf[j].out, M_CRYPTO_DATA);
  385                         count -= buf[j].size;
  386                 } else {
  387                         /* it should be the last buffer */
  388                         memcpy(output, buf[j].out, count);
  389                         output += count;
  390                         free(buf[j].out, M_CRYPTO_DATA);
  391                         count = 0;
  392                 }
  393         }
  394 
  395         if (!decomp) {
  396                 /* fill in CRC and ISIZE */
  397                 HTOLE32(crc);
  398                 memcpy(output, &crc, sizeof(uint32_t));
  399                 HTOLE32(size);
  400                 memcpy(output + sizeof(uint32_t), &size, sizeof(uint32_t));
  401 
  402                 DPRINTF("size = 0x%x (%02x %02x %02x %02x)\n",
  403                                 size,
  404                                 output[7],
  405                                 output[3],
  406                                 output[5],
  407                                 output[4]);
  408         } else {
  409                 if (crc != icrc || result != isize) {
  410                         DPRINTF("crc/size mismatch\n");
  411                         free(*out, M_CRYPTO_DATA);
  412                         *out = NULL;
  413                         return 0;
  414                 }
  415         }
  416 
  417         return result;
  418 
  419 bad:
  420         if (decomp)
  421                 inflateEnd(&zbuf);
  422         else
  423                 deflateEnd(&zbuf);
  424 bad2:
  425         *out = NULL;
  426         for (j = 0; j < i; j++)
  427                 free(buf[j].out, M_CRYPTO_DATA);
  428         return 0;
  429 }

Cache object: ef9be62e069424e5d8a3afc49c8f13cd


[ 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.