1 /* $NetBSD: deflate.c,v 1.5 2006/03/17 23:29:11 christos 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.5 2006/03/17 23:29:11 christos 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 int window_inflate = -1 * MAX_WBITS; 50 int window_deflate = -12; 51 52 /* 53 * This function takes a block of data and (de)compress it using the deflate 54 * algorithm 55 */ 56 57 static void * 58 ocf_zalloc(void *nil, u_int type, u_int size) 59 { 60 void *ptr; 61 62 ptr = malloc(type *size, M_CRYPTO_DATA, M_NOWAIT); 63 return ptr; 64 } 65 66 static void 67 ocf_zfree(void *nil, void *ptr) 68 { 69 free(ptr, M_CRYPTO_DATA); 70 } 71 72 u_int32_t 73 deflate_global(data, size, decomp, out) 74 u_int8_t *data; 75 u_int32_t size; 76 int decomp; 77 u_int8_t **out; 78 { 79 /* decomp indicates whether we compress (0) or decompress (1) */ 80 81 z_stream zbuf; 82 u_int8_t *output; 83 u_int32_t count, result; 84 int error, i = 0, j; 85 struct deflate_buf buf[ZBUF]; 86 87 bzero(&zbuf, sizeof(z_stream)); 88 for (j = 0; j < ZBUF; j++) 89 buf[j].flag = 0; 90 91 zbuf.next_in = data; /* data that is going to be processed */ 92 zbuf.zalloc = ocf_zalloc; 93 zbuf.zfree = ocf_zfree; 94 zbuf.opaque = Z_NULL; 95 zbuf.avail_in = size; /* Total length of data to be processed */ 96 97 if (!decomp) { 98 buf[i].out = malloc(size, M_CRYPTO_DATA, M_NOWAIT); 99 if (buf[i].out == NULL) 100 goto bad; 101 buf[i].size = size; 102 buf[i].flag = 1; 103 i++; 104 } else { 105 /* 106 * Choose a buffer with 4x the size of the input buffer 107 * for the size of the output buffer in the case of 108 * decompression. If it's not sufficient, it will need to be 109 * updated while the decompression is going on 110 */ 111 112 buf[i].size = size * 4; 113 buf[i].out = malloc(buf[i].size, M_CRYPTO_DATA, M_NOWAIT); 114 if (buf[i].out == NULL) 115 goto bad; 116 buf[i].flag = 1; 117 i++; 118 } 119 120 zbuf.next_out = buf[0].out; 121 zbuf.avail_out = buf[0].size; 122 123 error = decomp ? inflateInit2(&zbuf, window_inflate) : 124 deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD, 125 window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY); 126 127 if (error != Z_OK) 128 goto bad; 129 for (;;) { 130 error = decomp ? inflate(&zbuf, Z_PARTIAL_FLUSH) : 131 deflate(&zbuf, Z_PARTIAL_FLUSH); 132 if (error != Z_OK && error != Z_STREAM_END) 133 goto bad; 134 else if (zbuf.avail_in == 0 && zbuf.avail_out != 0) 135 goto end; 136 else if (zbuf.avail_out == 0 && i < (ZBUF - 1)) { 137 /* we need more output space, allocate size */ 138 buf[i].out = malloc(size, M_CRYPTO_DATA, M_NOWAIT); 139 if (buf[i].out == NULL) 140 goto bad; 141 zbuf.next_out = buf[i].out; 142 buf[i].size = size; 143 buf[i].flag = 1; 144 zbuf.avail_out = buf[i].size; 145 i++; 146 } else 147 goto bad; 148 } 149 150 end: 151 result = count = zbuf.total_out; 152 153 *out = malloc(result, M_CRYPTO_DATA, M_NOWAIT); 154 if (*out == NULL) 155 goto bad; 156 if (decomp) 157 inflateEnd(&zbuf); 158 else 159 deflateEnd(&zbuf); 160 output = *out; 161 for (j = 0; buf[j].flag != 0; j++) { 162 if (count > buf[j].size) { 163 bcopy(buf[j].out, *out, buf[j].size); 164 *out += buf[j].size; 165 FREE(buf[j].out, M_CRYPTO_DATA); 166 count -= buf[j].size; 167 } else { 168 /* it should be the last buffer */ 169 bcopy(buf[j].out, *out, count); 170 *out += count; 171 FREE(buf[j].out, M_CRYPTO_DATA); 172 count = 0; 173 } 174 } 175 *out = output; 176 return result; 177 178 bad: 179 *out = NULL; 180 for (j = 0; buf[j].flag != 0; j++) 181 FREE(buf[j].out, M_CRYPTO_DATA); 182 if (decomp) 183 inflateEnd(&zbuf); 184 else 185 deflateEnd(&zbuf); 186 return 0; 187 } 188