1 /*	$NetBSD: deflate.c,v 1.22 2015/03/26 17:40:16 prlw1 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.22 2015/03/26 17:40:16 prlw1 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 *
ocf_zalloc(void * nil,u_int type,u_int size)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
ocf_zfree(void * nil,void * ptr)74 ocf_zfree(void *nil, void *ptr)
75 {
76 	free(ptr, M_CRYPTO_DATA);
77 }
78 
79 u_int32_t
deflate_global(u_int8_t * data,u_int32_t size,int decomp,u_int8_t ** out,int size_hint)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(("deflate_global: 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
gzip_global(u_int8_t * data,u_int32_t size,int decomp,u_int8_t ** out,int size_hint)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(("gzip_global: 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(("gzip_global: 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(("gzip_compress: 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(("gzip_global: not enough data (%u)\n",
263 					size));
264 			return 0;
265 		}
266 
267 		/* XXX this is pretty basic,
268 		 * needs to be expanded to ignore MTIME, OS,
269 		 * but still ensure flags are 0.
270 		 * Q. Do we need to support the flags and
271 		 * optional header fields? Likely.
272 		 * XXX add flag and field support too.
273 		 */
274 		if (memcmp(data, gzip_header, sizeof(gzip_header)) != 0) {
275 			DPRINTF(("gzip_global: unsupported gzip header (%02x%02x)\n",
276 					data[0], data[1]));
277 			return 0;
278 		} else {
279 			DPRINTF(("gzip_global.%d: gzip header ok\n",__LINE__));
280 		}
281 
282 		memcpy(&isize, &data[size-sizeof(uint32_t)], sizeof(uint32_t));
283 		LE32TOH(isize);
284 		memcpy(&icrc, &data[size-2*sizeof(uint32_t)], sizeof(uint32_t));
285 		LE32TOH(icrc);
286 
287 		DPRINTF(("gzip_global: isize = %u (%02x %02x %02x %02x)\n",
288 				isize,
289 				data[size-4],
290 				data[size-3],
291 				data[size-2],
292 				data[size-1]));
293 
294 		buf[0].size = isize;
295 		crc = crc32(0, NULL, 0);	/* get initial crc value */
296 
297 		/* skip over the gzip header */
298 		zbuf.next_in = data + sizeof(gzip_header);
299 
300 		/* actual payload size stripped of gzip header and tail */
301 		zbuf.avail_in = size - sizeof(gzip_header) - GZIP_TAIL_SIZE;
302 	}
303 
304 	buf[0].out = malloc(buf[0].size, M_CRYPTO_DATA, M_NOWAIT);
305 	if (buf[0].out == NULL)
306 		return 0;
307 	zbuf.next_out = buf[0].out;
308 	zbuf.avail_out = buf[0].size;
309 	DPRINTF(("zbuf avail_in %u, avail_out %u\n",
310 			zbuf.avail_in, zbuf.avail_out));
311 	i = 1;
312 
313 	error = decomp ? inflateInit2(&zbuf, window_inflate) :
314 	    deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
315 		    window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
316 
317 	if (error != Z_OK) {
318 		printf("deflateInit2() failed\n");
319 		goto bad2;
320 	}
321 	for (;;) {
322 		DPRINTF(("pre: %s in:%u out:%u\n", decomp ? "deflate()" : "inflate()",
323 				zbuf.avail_in, zbuf.avail_out));
324 		error = decomp ? inflate(&zbuf, Z_SYNC_FLUSH) :
325 				 deflate(&zbuf, Z_FINISH);
326 		DPRINTF(("post: %s in:%u out:%u\n", decomp ? "deflate()" : "inflate()",
327 				zbuf.avail_in, zbuf.avail_out));
328 		if (error == Z_STREAM_END) /* success */
329 			break;
330 		/*
331 		 * XXX compensate for a zlib problem:
332 		 * -sys/net/zlib.c has a bug which makes that Z_BUF_ERROR is
333 		 *  set after successful decompression under rare conditions.
334 		 */
335 		else if (decomp && error == Z_BUF_ERROR
336 			 && zbuf.avail_in == 0 && zbuf.avail_out != 0)
337 				break;
338 		else if (error != Z_OK)
339 			goto bad;
340 		else if (zbuf.avail_out == 0) {
341 			/* we need more output space, allocate size */
342 			int nextsize = buf[i-1].size * 2;
343 			if (i == ZBUF || nextsize > 1000000)
344 				goto bad;
345 			buf[i].out = malloc(nextsize, M_CRYPTO_DATA, M_NOWAIT);
346 			if (buf[i].out == NULL)
347 				goto bad;
348 			zbuf.next_out = buf[i].out;
349 			zbuf.avail_out = buf[i].size = nextsize;
350 			i++;
351 		}
352 	}
353 
354 	if (decomp) {
355 		count = result = zbuf.total_out;
356 	} else {
357 		/* need room for header, CRC, and ISIZE */
358 		result = zbuf.total_out + sizeof(gzip_header) + GZIP_TAIL_SIZE;
359 		count = zbuf.total_out;
360 	}
361 
362 	DPRINTF(("gzip_global: in %u -> out %u\n", size, result));
363 
364 	*out = malloc(result, M_CRYPTO_DATA, M_NOWAIT);
365 	if (*out == NULL)
366 		goto bad;
367 	output = *out;
368 	if (decomp)
369 		inflateEnd(&zbuf);
370 	else {
371 		deflateEnd(&zbuf);
372 
373 		/* fill in gzip header */
374 		memcpy(output, gzip_header, sizeof(gzip_header));
375 		output += sizeof(gzip_header);
376 	}
377 	for (j = 0; j < i; j++) {
378 		if (decomp) {
379 			/* update crc for decompressed data */
380 			crc = crc32(crc, buf[j].out, MIN(count, buf[j].size));
381 		}
382 		if (count > buf[j].size) {
383 			memcpy(output, buf[j].out, buf[j].size);
384 			output += buf[j].size;
385 			free(buf[j].out, M_CRYPTO_DATA);
386 			count -= buf[j].size;
387 		} else {
388 			/* it should be the last buffer */
389 			memcpy(output, buf[j].out, count);
390 			output += count;
391 			free(buf[j].out, M_CRYPTO_DATA);
392 			count = 0;
393 		}
394 	}
395 
396 	if (!decomp) {
397 		/* fill in CRC and ISIZE */
398 		HTOLE32(crc);
399 		memcpy(output, &crc, sizeof(uint32_t));
400 		HTOLE32(size);
401 		memcpy(output + sizeof(uint32_t), &size, sizeof(uint32_t));
402 
403 		DPRINTF(("gzip_global: size = 0x%x (%02x %02x %02x %02x)\n",
404 				size,
405 				output[7],
406 				output[3],
407 				output[5],
408 				output[4]));
409 	} else {
410 		if (crc != icrc || result != isize) {
411 			DPRINTF(("gzip_global: crc/size mismatch\n"));
412 			free(*out, M_CRYPTO_DATA);
413 			*out = NULL;
414 			return 0;
415 		}
416 	}
417 
418 	return result;
419 
420 bad:
421 	if (decomp)
422 		inflateEnd(&zbuf);
423 	else
424 		deflateEnd(&zbuf);
425 bad2:
426 	*out = NULL;
427 	for (j = 0; j < i; j++)
428 		free(buf[j].out, M_CRYPTO_DATA);
429 	return 0;
430 }
431