xref: /openbsd-src/sys/crypto/xform_ipcomp.c (revision 319dd5c3f6a33d939bbe52127a8bb6f14d12b2cf)
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