1*319dd5c3Smpi /* $OpenBSD: xform_ipcomp.c,v 1.8 2019/01/09 12:11:38 mpi Exp $ */
26141cf33Sderaadt
36141cf33Sderaadt /*
46141cf33Sderaadt * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
56141cf33Sderaadt *
66141cf33Sderaadt * Redistribution and use in source and binary forms, with or without
76141cf33Sderaadt * modification, are permitted provided that the following conditions
86141cf33Sderaadt * are met:
96141cf33Sderaadt *
106141cf33Sderaadt * 1. Redistributions of source code must retain the above copyright
116141cf33Sderaadt * notice, this list of conditions and the following disclaimer.
126141cf33Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
136141cf33Sderaadt * notice, this list of conditions and the following disclaimer in the
146141cf33Sderaadt * documentation and/or other materials provided with the distribution.
156141cf33Sderaadt * 3. The name of the author may not be used to endorse or promote products
166141cf33Sderaadt * derived from this software without specific prior written permission.
176141cf33Sderaadt *
186141cf33Sderaadt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
196141cf33Sderaadt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
206141cf33Sderaadt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
216141cf33Sderaadt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
226141cf33Sderaadt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
236141cf33Sderaadt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
246141cf33Sderaadt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
256141cf33Sderaadt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
266141cf33Sderaadt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
276141cf33Sderaadt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
286141cf33Sderaadt */
296141cf33Sderaadt
306141cf33Sderaadt /*
316141cf33Sderaadt * This file contains a wrapper around the deflate algo compression
3297537951Slogan * functions using the zlib library
336141cf33Sderaadt */
346141cf33Sderaadt
35f1bb3c4bSmiod #include <sys/param.h>
366141cf33Sderaadt #include <sys/malloc.h>
376141cf33Sderaadt #include <sys/systm.h>
386141cf33Sderaadt #include <lib/libz/zutil.h>
396141cf33Sderaadt
406141cf33Sderaadt #define Z_METHOD 8
416141cf33Sderaadt #define Z_MEMLEVEL 8
426141cf33Sderaadt #define ZBUF 10
436141cf33Sderaadt
446141cf33Sderaadt u_int32_t deflate_global(u_int8_t *, u_int32_t, int, u_int8_t **);
456141cf33Sderaadt
466141cf33Sderaadt struct deflate_buf {
476141cf33Sderaadt u_int8_t *out;
486141cf33Sderaadt u_int32_t size;
496141cf33Sderaadt int flag;
506141cf33Sderaadt };
516141cf33Sderaadt
526141cf33Sderaadt int window_inflate = -1 * MAX_WBITS;
536141cf33Sderaadt int window_deflate = -12;
546141cf33Sderaadt
556141cf33Sderaadt /*
566141cf33Sderaadt * This function takes a block of data and (de)compress it using the deflate
576141cf33Sderaadt * algorithm
586141cf33Sderaadt */
596141cf33Sderaadt
606141cf33Sderaadt u_int32_t
deflate_global(u_int8_t * data,u_int32_t size,int decomp,u_int8_t ** out)610471bdd7Smarkus deflate_global(u_int8_t *data, u_int32_t size, int decomp, u_int8_t **out)
626141cf33Sderaadt {
636141cf33Sderaadt z_stream zbuf;
646141cf33Sderaadt u_int8_t *output;
656141cf33Sderaadt u_int32_t count, result;
666141cf33Sderaadt int error, i = 0, j;
676141cf33Sderaadt struct deflate_buf buf[ZBUF];
686141cf33Sderaadt
696141cf33Sderaadt bzero(&zbuf, sizeof(z_stream));
706141cf33Sderaadt for (j = 0; j < ZBUF; j++)
716141cf33Sderaadt buf[j].flag = 0;
726141cf33Sderaadt
736141cf33Sderaadt zbuf.next_in = data; /* data that is going to be processed */
746141cf33Sderaadt zbuf.zalloc = zcalloc;
756141cf33Sderaadt zbuf.zfree = zcfree;
766141cf33Sderaadt zbuf.opaque = Z_NULL;
776141cf33Sderaadt zbuf.avail_in = size; /* Total length of data to be processed */
786141cf33Sderaadt
790471bdd7Smarkus if (decomp) {
806141cf33Sderaadt /*
816141cf33Sderaadt * Choose a buffer with 4x the size of the input buffer
826141cf33Sderaadt * for the size of the output buffer in the case of
836141cf33Sderaadt * decompression. If it's not sufficient, it will need to be
846141cf33Sderaadt * updated while the decompression is going on
856141cf33Sderaadt */
862d8a3fe6Smarkus if (size < 32 * 1024)
872d8a3fe6Smarkus size *= 4;
882d8a3fe6Smarkus }
892d8a3fe6Smarkus buf[i].out = malloc((u_long)size, M_CRYPTO_DATA, M_NOWAIT);
906141cf33Sderaadt if (buf[i].out == NULL)
916141cf33Sderaadt goto bad;
922d8a3fe6Smarkus buf[i].size = size;
936141cf33Sderaadt buf[i].flag = 1;
946141cf33Sderaadt i++;
956141cf33Sderaadt
966141cf33Sderaadt zbuf.next_out = buf[0].out;
976141cf33Sderaadt zbuf.avail_out = buf[0].size;
986141cf33Sderaadt
990471bdd7Smarkus error = decomp ?
1000471bdd7Smarkus inflateInit2(&zbuf, window_inflate) :
1016141cf33Sderaadt deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
1026141cf33Sderaadt window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
1036141cf33Sderaadt
1046141cf33Sderaadt if (error != Z_OK)
1056141cf33Sderaadt goto bad;
1066141cf33Sderaadt for (;;) {
1070471bdd7Smarkus error = decomp ?
1080471bdd7Smarkus inflate(&zbuf, Z_PARTIAL_FLUSH) :
1090471bdd7Smarkus deflate(&zbuf, Z_FINISH);
1100471bdd7Smarkus if (error == Z_STREAM_END)
1110471bdd7Smarkus break;
1120471bdd7Smarkus if (error != Z_OK)
1136141cf33Sderaadt goto bad;
1140471bdd7Smarkus if (zbuf.avail_out == 0 && i < (ZBUF - 1)) {
1156141cf33Sderaadt /* we need more output space, allocate size */
1162d8a3fe6Smarkus if (size < 32 * 1024)
1172d8a3fe6Smarkus size *= 2;
1186141cf33Sderaadt buf[i].out = malloc((u_long)size, M_CRYPTO_DATA,
1196141cf33Sderaadt M_NOWAIT);
1206141cf33Sderaadt if (buf[i].out == NULL)
1216141cf33Sderaadt goto bad;
1226141cf33Sderaadt zbuf.next_out = buf[i].out;
1236141cf33Sderaadt buf[i].size = size;
1246141cf33Sderaadt buf[i].flag = 1;
1256141cf33Sderaadt zbuf.avail_out = buf[i].size;
1266141cf33Sderaadt i++;
1276141cf33Sderaadt } else
1280471bdd7Smarkus goto bad; /* out of buffers */
1296141cf33Sderaadt }
1306141cf33Sderaadt result = count = zbuf.total_out;
1316141cf33Sderaadt
1326141cf33Sderaadt *out = malloc((u_long)result, M_CRYPTO_DATA, M_NOWAIT);
1336141cf33Sderaadt if (*out == NULL)
1346141cf33Sderaadt goto bad;
1350471bdd7Smarkus if (decomp)
1366141cf33Sderaadt inflateEnd(&zbuf);
1376141cf33Sderaadt else
1386141cf33Sderaadt deflateEnd(&zbuf);
1396141cf33Sderaadt output = *out;
1406141cf33Sderaadt for (j = 0; buf[j].flag != 0; j++) {
1416141cf33Sderaadt if (count > buf[j].size) {
1426141cf33Sderaadt bcopy(buf[j].out, *out, buf[j].size);
1436141cf33Sderaadt *out += buf[j].size;
144*319dd5c3Smpi free(buf[j].out, M_CRYPTO_DATA, buf[j].size);
1456141cf33Sderaadt count -= buf[j].size;
1466141cf33Sderaadt } else {
1476141cf33Sderaadt /* it should be the last buffer */
1486141cf33Sderaadt bcopy(buf[j].out, *out, count);
1496141cf33Sderaadt *out += count;
150*319dd5c3Smpi free(buf[j].out, M_CRYPTO_DATA, buf[j].size);
1516141cf33Sderaadt count = 0;
1526141cf33Sderaadt }
1536141cf33Sderaadt }
1546141cf33Sderaadt *out = output;
1556141cf33Sderaadt return result;
1566141cf33Sderaadt
1576141cf33Sderaadt bad:
1586141cf33Sderaadt *out = NULL;
1596141cf33Sderaadt for (j = 0; buf[j].flag != 0; j++)
160*319dd5c3Smpi free(buf[j].out, M_CRYPTO_DATA, buf[j].size);
1610471bdd7Smarkus if (decomp)
1626141cf33Sderaadt inflateEnd(&zbuf);
1636141cf33Sderaadt else
1646141cf33Sderaadt deflateEnd(&zbuf);
1656141cf33Sderaadt return 0;
1666141cf33Sderaadt }
167