1 /* $NetBSD: deflate.c,v 1.9 2007/09/22 23:38:17 degroote 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.9 2007/09/22 23:38:17 degroote 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, *tmp; 86 size_t len, old_len; 87 88 len = ZBUF; 89 buf = malloc(len*sizeof(struct deflate_buf), M_CRYPTO_DATA, M_NOWAIT); 90 if (buf == NULL) 91 return 0; 92 93 memset(&zbuf, 0, sizeof(z_stream)); 94 for (j = 0; j < len; j++) 95 buf[j].flag = 0; 96 97 zbuf.next_in = data; /* data that is going to be processed */ 98 zbuf.zalloc = ocf_zalloc; 99 zbuf.zfree = ocf_zfree; 100 zbuf.opaque = Z_NULL; 101 zbuf.avail_in = size; /* Total length of data to be processed */ 102 103 if (!decomp) { 104 buf[i].out = malloc(size, M_CRYPTO_DATA, M_NOWAIT); 105 if (buf[i].out == NULL) 106 goto bad; 107 buf[i].size = size; 108 buf[i].flag = 1; 109 i++; 110 } else { 111 /* 112 * Choose a buffer with 4x the size of the input buffer 113 * for the size of the output buffer in the case of 114 * decompression. If it's not sufficient, it will need to be 115 * updated while the decompression is going on 116 */ 117 118 buf[i].size = size * 4; 119 buf[i].out = malloc(buf[i].size, M_CRYPTO_DATA, M_NOWAIT); 120 if (buf[i].out == NULL) 121 goto bad; 122 buf[i].flag = 1; 123 i++; 124 } 125 126 zbuf.next_out = buf[0].out; 127 zbuf.avail_out = buf[0].size; 128 129 error = decomp ? inflateInit2(&zbuf, window_inflate) : 130 deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD, 131 window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY); 132 133 if (error != Z_OK) 134 goto bad; 135 for (;;) { 136 error = decomp ? inflate(&zbuf, Z_PARTIAL_FLUSH) : 137 deflate(&zbuf, Z_PARTIAL_FLUSH); 138 if (error != Z_OK && error != Z_STREAM_END) 139 goto bad; 140 else if (zbuf.avail_in == 0 && zbuf.avail_out != 0) 141 goto end; 142 else if (zbuf.avail_out == 0) { 143 if (i == (len-1)) { 144 old_len = i; 145 len += ZBUF; 146 tmp = realloc(buf,len*sizeof(struct deflate_buf), 147 M_CRYPTO_DATA, M_NOWAIT); 148 if (tmp == NULL) 149 goto bad; 150 buf = tmp; 151 for (j = old_len; j < len; j++) 152 buf[j].flag = 0; 153 } 154 /* we need more output space, allocate size */ 155 buf[i].out = malloc(size, M_CRYPTO_DATA, M_NOWAIT); 156 if (buf[i].out == NULL) 157 goto bad; 158 zbuf.next_out = buf[i].out; 159 buf[i].size = size; 160 buf[i].flag = 1; 161 zbuf.avail_out = buf[i].size; 162 i++; 163 } else 164 goto bad; 165 } 166 167 end: 168 result = count = zbuf.total_out; 169 170 *out = malloc(result, M_CRYPTO_DATA, M_NOWAIT); 171 if (*out == NULL) 172 goto bad; 173 if (decomp) 174 inflateEnd(&zbuf); 175 else 176 deflateEnd(&zbuf); 177 output = *out; 178 for (j = 0; buf[j].flag != 0; j++) { 179 if (count > buf[j].size) { 180 memcpy(*out, buf[j].out, buf[j].size); 181 *out += buf[j].size; 182 free(buf[j].out, M_CRYPTO_DATA); 183 count -= buf[j].size; 184 } else { 185 /* it should be the last buffer */ 186 memcpy(*out, buf[j].out, count); 187 *out += count; 188 free(buf[j].out, M_CRYPTO_DATA); 189 count = 0; 190 } 191 } 192 free(buf, M_CRYPTO_DATA); 193 *out = output; 194 return result; 195 196 bad: 197 *out = NULL; 198 for (j = 0; buf[j].flag != 0; j++) 199 free(buf[j].out, M_CRYPTO_DATA); 200 free(buf, M_CRYPTO_DATA); 201 if (decomp) 202 inflateEnd(&zbuf); 203 else 204 deflateEnd(&zbuf); 205 return 0; 206 } 207