1 /* $NetBSD: deflate.c,v 1.4 2005/12/11 12:25:20 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.4 2005/12/11 12:25:20 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 MALLOC(buf[i].out, u_int8_t *, (u_long) size, M_CRYPTO_DATA, 99 M_NOWAIT); 100 if (buf[i].out == NULL) 101 goto bad; 102 buf[i].size = size; 103 buf[i].flag = 1; 104 i++; 105 } else { 106 /* 107 * Choose a buffer with 4x the size of the input buffer 108 * for the size of the output buffer in the case of 109 * decompression. If it's not sufficient, it will need to be 110 * updated while the decompression is going on 111 */ 112 113 MALLOC(buf[i].out, u_int8_t *, (u_long) (size * 4), 114 M_CRYPTO_DATA, M_NOWAIT); 115 if (buf[i].out == NULL) 116 goto bad; 117 buf[i].size = size * 4; 118 buf[i].flag = 1; 119 i++; 120 } 121 122 zbuf.next_out = buf[0].out; 123 zbuf.avail_out = buf[0].size; 124 125 error = decomp ? inflateInit2(&zbuf, window_inflate) : 126 deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD, 127 window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY); 128 129 if (error != Z_OK) 130 goto bad; 131 for (;;) { 132 error = decomp ? inflate(&zbuf, Z_PARTIAL_FLUSH) : 133 deflate(&zbuf, Z_PARTIAL_FLUSH); 134 if (error != Z_OK && error != Z_STREAM_END) 135 goto bad; 136 else if (zbuf.avail_in == 0 && zbuf.avail_out != 0) 137 goto end; 138 else if (zbuf.avail_out == 0 && i < (ZBUF - 1)) { 139 /* we need more output space, allocate size */ 140 MALLOC(buf[i].out, u_int8_t *, (u_long) size, 141 M_CRYPTO_DATA, M_NOWAIT); 142 if (buf[i].out == NULL) 143 goto bad; 144 zbuf.next_out = buf[i].out; 145 buf[i].size = size; 146 buf[i].flag = 1; 147 zbuf.avail_out = buf[i].size; 148 i++; 149 } else 150 goto bad; 151 } 152 153 end: 154 result = count = zbuf.total_out; 155 156 MALLOC(*out, u_int8_t *, (u_long) result, M_CRYPTO_DATA, M_NOWAIT); 157 if (*out == NULL) 158 goto bad; 159 if (decomp) 160 inflateEnd(&zbuf); 161 else 162 deflateEnd(&zbuf); 163 output = *out; 164 for (j = 0; buf[j].flag != 0; j++) { 165 if (count > buf[j].size) { 166 bcopy(buf[j].out, *out, buf[j].size); 167 *out += buf[j].size; 168 FREE(buf[j].out, M_CRYPTO_DATA); 169 count -= buf[j].size; 170 } else { 171 /* it should be the last buffer */ 172 bcopy(buf[j].out, *out, count); 173 *out += count; 174 FREE(buf[j].out, M_CRYPTO_DATA); 175 count = 0; 176 } 177 } 178 *out = output; 179 return result; 180 181 bad: 182 *out = NULL; 183 for (j = 0; buf[j].flag != 0; j++) 184 FREE(buf[j].out, M_CRYPTO_DATA); 185 if (decomp) 186 inflateEnd(&zbuf); 187 else 188 deflateEnd(&zbuf); 189 return 0; 190 } 191