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