1 /* $NetBSD: deflate.c,v 1.12 2009/03/14 15:36:24 dsl 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 $ */
6 * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
33 * This file contains a wrapper around the deflate algo compression
34 * functions using the zlib library (see net/zlib.{c,h})
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: deflate.c,v 1.12 2009/03/14 15:36:24 dsl Exp $");
40 #include <sys/types.h>
41 #include <sys/malloc.h>
42 #include <sys/param.h>
43 #include <sys/systm.h>
46 #include <opencrypto/cryptodev.h>
47 #include <opencrypto/deflate.h>
50 int window_inflate
= -1 * MAX_WBITS
;
51 int window_deflate
= -12;
54 * This function takes a block of data and (de)compress it using the deflate
59 ocf_zalloc(void *nil
, u_int type
, u_int size
)
63 ptr
= malloc(type
*size
, M_CRYPTO_DATA
, M_NOWAIT
);
68 ocf_zfree(void *nil
, void *ptr
)
70 free(ptr
, M_CRYPTO_DATA
);
74 deflate_global(u_int8_t
*data
, u_int32_t size
, int decomp
, u_int8_t
**out
)
76 /* decomp indicates whether we compress (0) or decompress (1) */
80 u_int32_t count
, result
;
82 struct deflate_buf
*buf
, *tmp
;
85 DPRINTF(("deflate_global: size %d\n", size
));
88 buf
= malloc(len
*sizeof(struct deflate_buf
), M_CRYPTO_DATA
, M_NOWAIT
);
92 memset(&zbuf
, 0, sizeof(z_stream
));
93 for (j
= 0; j
< len
; j
++)
96 zbuf
.next_in
= data
; /* data that is going to be processed */
97 zbuf
.zalloc
= ocf_zalloc
;
98 zbuf
.zfree
= ocf_zfree
;
100 zbuf
.avail_in
= size
; /* Total length of data to be processed */
103 buf
[i
].out
= malloc(size
, M_CRYPTO_DATA
, M_NOWAIT
);
104 if (buf
[i
].out
== NULL
)
111 * Choose a buffer with 4x the size of the input buffer
112 * for the size of the output buffer in the case of
113 * decompression. If it's not sufficient, it will need to be
114 * updated while the decompression is going on
117 buf
[i
].size
= size
* 4;
118 buf
[i
].out
= malloc(buf
[i
].size
, M_CRYPTO_DATA
, M_NOWAIT
);
119 if (buf
[i
].out
== NULL
)
125 zbuf
.next_out
= buf
[0].out
;
126 zbuf
.avail_out
= buf
[0].size
;
128 error
= decomp
? inflateInit2(&zbuf
, window_inflate
) :
129 deflateInit2(&zbuf
, Z_DEFAULT_COMPRESSION
, Z_METHOD
,
130 window_deflate
, Z_MEMLEVEL
, Z_DEFAULT_STRATEGY
);
135 error
= decomp
? inflate(&zbuf
, Z_PARTIAL_FLUSH
) :
136 deflate(&zbuf
, Z_PARTIAL_FLUSH
);
137 if (error
!= Z_OK
&& error
!= Z_STREAM_END
)
139 else if (zbuf
.avail_in
== 0 && zbuf
.avail_out
!= 0)
141 else if (zbuf
.avail_out
== 0) {
145 tmp
= realloc(buf
,len
*sizeof(struct deflate_buf
),
146 M_CRYPTO_DATA
, M_NOWAIT
);
150 for (j
= old_len
; j
< len
; j
++)
153 /* we need more output space, allocate size */
154 buf
[i
].out
= malloc(size
, M_CRYPTO_DATA
, M_NOWAIT
);
155 if (buf
[i
].out
== NULL
)
157 zbuf
.next_out
= buf
[i
].out
;
160 zbuf
.avail_out
= buf
[i
].size
;
167 result
= count
= zbuf
.total_out
;
169 *out
= malloc(result
, M_CRYPTO_DATA
, M_NOWAIT
);
177 for (j
= 0; buf
[j
].flag
!= 0; j
++) {
178 if (count
> buf
[j
].size
) {
179 memcpy(*out
, buf
[j
].out
, buf
[j
].size
);
181 free(buf
[j
].out
, M_CRYPTO_DATA
);
182 count
-= buf
[j
].size
;
184 /* it should be the last buffer */
185 memcpy(*out
, buf
[j
].out
, count
);
187 free(buf
[j
].out
, M_CRYPTO_DATA
);
191 free(buf
, M_CRYPTO_DATA
);
197 for (j
= 0; buf
[j
].flag
!= 0; j
++)
198 free(buf
[j
].out
, M_CRYPTO_DATA
);
199 free(buf
, M_CRYPTO_DATA
);
208 * Initial version will perform a single gzip encapsulation,
209 * filling in the header,
210 * and appending the crc and uncompressed length.
212 * Later version will support multiple buffers with
213 * a flag indication final buffer. The crc is maintained
214 * over all buffers and appended to the output along with
215 * the uncompressed length after the final data buffer
216 * has been compressed and output.
218 * Ditto for uncompress - CRC is extracted from the final packed
219 * and compared against CRC of uncompressed data.
223 /* constant header for the gzip */
224 static const char gzip_header
[10] = {
225 0x1f, 0x8b, /* ID1 ID2 */
228 0, 0, 0, 0, /* MTIME */
233 /* Followed by compressed payload */
234 /* Followed by uint32_t CRC32 and uint32_t ISIZE */
235 #define GZIP_TAIL_SIZE 8
238 gzip_global(u_int8_t
*data
, u_int32_t size
,
239 int decomp
, u_int8_t
**out
)
241 /* decomp indicates whether we compress (0) or decompress (1) */
244 u_int32_t count
, result
;
246 struct deflate_buf
*buf
, *tmp
;
247 size_t nbufs
, old_nbufs
;
251 DPRINTF(("gzip_global: decomp %d, size %d\n", decomp
, size
));
254 buf
= malloc(nbufs
*sizeof(struct deflate_buf
), M_CRYPTO_DATA
, M_NOWAIT
);
256 DPRINTF(("gzip_global.%d: failed to malloc %d\n",
257 __LINE__
, nbufs
*sizeof(struct deflate_buf
)));
261 memset(&zbuf
, 0, sizeof(z_stream
));
262 for (j
= 0; j
< nbufs
; j
++)
265 zbuf
.zalloc
= ocf_zalloc
;
266 zbuf
.zfree
= ocf_zfree
;
267 zbuf
.opaque
= Z_NULL
;
269 crc
= crc32(0, NULL
, 0); /* get initial crc value */
271 zbuf
.avail_in
= size
; /* Total length of data to be processed */
272 zbuf
.next_in
= data
; /* data that is going to be processed */
276 DPRINTF(("gzip_global: compress[%d] malloc %d + %d + %d = %d\n",
277 i
, size
, sizeof(gzip_header
), GZIP_TAIL_SIZE
,
278 size
+ sizeof(gzip_header
) + GZIP_TAIL_SIZE
));
280 buf
[i
].out
= malloc(size
, M_CRYPTO_DATA
, M_NOWAIT
);
281 if (buf
[i
].out
== NULL
)
286 zbuf
.next_out
= buf
[i
].out
;
287 zbuf
.avail_out
= buf
[i
].size
;
290 crc
= crc32(crc
, data
, size
);
291 DPRINTF(("gzip_compress: size %d, crc 0x%x\n", size
, crc
));
294 /* check the gzip header */
295 if (zbuf
.avail_in
<= 0) {
296 /* Not enough data for the header & tail */
297 DPRINTF(("gzip_global: not enough data (%d)\n",
302 /* XXX this is pretty basic,
303 * needs to be expanded to ignore MTIME, OS,
304 * but still ensure flags are 0.
305 * Q. Do we need to support the flags and
306 * optional header fields? Likely.
307 * XXX add flag and field support too.
309 if (memcmp(data
, gzip_header
, sizeof(gzip_header
)) != 0) {
310 DPRINTF(("gzip_global: unsupported gzip header (%02x%02x)\n",
314 DPRINTF(("gzip_global.%d: gzip header ok\n",__LINE__
));
317 isize
= *((uint32_t *)&data
[size
-sizeof(uint32_t)]);
319 DPRINTF(("gzip_global: isize = %d (%02x %02x %02x %02x)\n",
327 buf
[i
].out
= malloc(buf
[i
].size
, M_CRYPTO_DATA
, M_NOWAIT
);
328 if (buf
[i
].out
== NULL
)
331 zbuf
.next_out
= buf
[i
].out
;
332 zbuf
.avail_out
= buf
[i
].size
;
335 /* skip over the gzip header */
336 zbuf
.next_in
= data
+ sizeof(gzip_header
);
338 /* actual payload size stripped of gzip header and tail */
339 zbuf
.avail_in
= size
- sizeof(gzip_header
) - GZIP_TAIL_SIZE
;
340 DPRINTF(("zbuf avail_in %d, avail_out %d\n",
341 zbuf
.avail_in
, zbuf
.avail_out
));
346 error
= decomp
? inflateInit2(&zbuf
, window_inflate
) :
347 deflateInit2(&zbuf
, Z_DEFAULT_COMPRESSION
, Z_METHOD
,
348 window_deflate
, Z_MEMLEVEL
, Z_DEFAULT_STRATEGY
);
351 printf("deflateInit2() failed\n");
355 DPRINTF(("pre: %s in:%d out:%d\n", decomp
? "deflate()" : "inflate()",
356 zbuf
.avail_in
, zbuf
.avail_out
));
357 error
= decomp
? inflate(&zbuf
, Z_PARTIAL_FLUSH
) :
358 deflate(&zbuf
, Z_PARTIAL_FLUSH
);
359 DPRINTF(("post: %s in:%d out:%d\n", decomp
? "deflate()" : "inflate()",
360 zbuf
.avail_in
, zbuf
.avail_out
));
361 if (error
!= Z_OK
&& error
!= Z_STREAM_END
) {
362 printf("deflate() or inflate() failed, error=%d\n", error
);
364 } else if (zbuf
.avail_in
== 0 && zbuf
.avail_out
!= 0) {
365 DPRINTF(("gzip_global: avail_in == 0, ending\n"));
367 } else if (zbuf
.avail_in
== 0 && zbuf
.avail_out
== 0) {
368 DPRINTF(("gzip_global: avail_in == 0, avail_out == 0, ending\n"));
370 } else if (zbuf
.avail_out
== 0) {
371 if (i
== (nbufs
-1)) {
374 tmp
= realloc(buf
,nbufs
*sizeof(struct deflate_buf
),
375 M_CRYPTO_DATA
, M_NOWAIT
);
379 for (j
= old_nbufs
; j
< nbufs
; j
++)
382 /* we need more output space, allocate size */
383 buf
[i
].out
= malloc(size
, M_CRYPTO_DATA
, M_NOWAIT
);
384 if (buf
[i
].out
== NULL
)
386 zbuf
.next_out
= buf
[i
].out
;
389 zbuf
.avail_out
= buf
[i
].size
;
397 count
= result
= zbuf
.total_out
;
399 /* need room for header, CRC, and ISIZE */
400 result
= zbuf
.total_out
+ sizeof(gzip_header
) + GZIP_TAIL_SIZE
;
401 count
= zbuf
.total_out
;
404 DPRINTF(("gzip_global: in %d -> out %d\n", size
, result
));
406 *out
= malloc(result
, M_CRYPTO_DATA
, M_NOWAIT
);
415 /* fill in gzip header */
416 memcpy(output
, gzip_header
, sizeof(gzip_header
));
417 output
+= sizeof(gzip_header
);
419 for (j
= 0; buf
[j
].flag
!= 0; j
++) {
421 /* update crc for decompressed data */
422 crc
= crc32(crc
, buf
[j
].out
, buf
[j
].size
);
424 if (count
> buf
[j
].size
) {
425 memcpy(output
, buf
[j
].out
, buf
[j
].size
);
426 output
+= buf
[j
].size
;
427 free(buf
[j
].out
, M_CRYPTO_DATA
);
428 count
-= buf
[j
].size
;
430 /* it should be the last buffer */
431 memcpy(output
, buf
[j
].out
, count
);
433 free(buf
[j
].out
, M_CRYPTO_DATA
);
437 free(buf
, M_CRYPTO_DATA
);
440 /* fill in CRC and ISIZE */
441 ((uint32_t *)output
)[0] = crc
;
442 ((uint32_t *)output
)[1] = size
;
444 DPRINTF(("gzip_global: size = 0x%x (%02x %02x %02x %02x)\n",
461 for (j
= 0; buf
[j
].flag
!= 0; j
++)
462 free(buf
[j
].out
, M_CRYPTO_DATA
);
463 free(buf
, M_CRYPTO_DATA
);