1 /* $OpenBSD: xform_ipcomp.c,v 1.1 2011/07/07 02:57:24 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * This file contains a wrapper around the deflate algo compression 32 * functions using the zlib library (see net/zlib.{c,h}) 33 */ 34 35 #include <sys/types.h> 36 #include <sys/malloc.h> 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <lib/libz/zutil.h> 40 41 #define Z_METHOD 8 42 #define Z_MEMLEVEL 8 43 #define MINCOMP 2 /* won't be used, but must be defined */ 44 #define ZBUF 10 45 46 u_int32_t deflate_global(u_int8_t *, u_int32_t, int, u_int8_t **); 47 48 struct deflate_buf { 49 u_int8_t *out; 50 u_int32_t size; 51 int flag; 52 }; 53 54 int window_inflate = -1 * MAX_WBITS; 55 int window_deflate = -12; 56 57 /* 58 * This function takes a block of data and (de)compress it using the deflate 59 * algorithm 60 */ 61 62 u_int32_t 63 deflate_global(u_int8_t *data, u_int32_t size, int comp, u_int8_t **out) 64 { 65 /* comp indicates whether we compress (0) or decompress (1) */ 66 67 z_stream zbuf; 68 u_int8_t *output; 69 u_int32_t count, result; 70 int error, i = 0, j; 71 struct deflate_buf buf[ZBUF]; 72 73 bzero(&zbuf, sizeof(z_stream)); 74 for (j = 0; j < ZBUF; j++) 75 buf[j].flag = 0; 76 77 zbuf.next_in = data; /* data that is going to be processed */ 78 zbuf.zalloc = zcalloc; 79 zbuf.zfree = zcfree; 80 zbuf.opaque = Z_NULL; 81 zbuf.avail_in = size; /* Total length of data to be processed */ 82 83 if (comp == 0) { 84 buf[i].out = malloc((u_long)size, M_CRYPTO_DATA, 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 buf[i].out = malloc((u_long)(size * 4), M_CRYPTO_DATA, M_NOWAIT); 98 if (buf[i].out == NULL) 99 goto bad; 100 buf[i].size = size * 4; 101 buf[i].flag = 1; 102 i++; 103 } 104 105 zbuf.next_out = buf[0].out; 106 zbuf.avail_out = buf[0].size; 107 108 error = comp ? inflateInit2(&zbuf, window_inflate) : 109 deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD, 110 window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY); 111 112 if (error != Z_OK) 113 goto bad; 114 for (;;) { 115 error = comp ? inflate(&zbuf, Z_PARTIAL_FLUSH) : 116 deflate(&zbuf, Z_PARTIAL_FLUSH); 117 if (error != Z_OK && error != Z_STREAM_END) 118 goto bad; 119 else if (zbuf.avail_in == 0 && zbuf.avail_out != 0) 120 goto end; 121 else if (zbuf.avail_out == 0 && i < (ZBUF - 1)) { 122 /* we need more output space, allocate size */ 123 buf[i].out = malloc((u_long)size, M_CRYPTO_DATA, 124 M_NOWAIT); 125 if (buf[i].out == NULL) 126 goto bad; 127 zbuf.next_out = buf[i].out; 128 buf[i].size = size; 129 buf[i].flag = 1; 130 zbuf.avail_out = buf[i].size; 131 i++; 132 } else 133 goto bad; 134 } 135 136 end: 137 result = count = zbuf.total_out; 138 139 *out = malloc((u_long)result, M_CRYPTO_DATA, M_NOWAIT); 140 if (*out == NULL) 141 goto bad; 142 if (comp) 143 inflateEnd(&zbuf); 144 else 145 deflateEnd(&zbuf); 146 output = *out; 147 for (j = 0; buf[j].flag != 0; j++) { 148 if (count > buf[j].size) { 149 bcopy(buf[j].out, *out, buf[j].size); 150 *out += buf[j].size; 151 free(buf[j].out, M_CRYPTO_DATA); 152 count -= buf[j].size; 153 } else { 154 /* it should be the last buffer */ 155 bcopy(buf[j].out, *out, count); 156 *out += count; 157 free(buf[j].out, M_CRYPTO_DATA); 158 count = 0; 159 } 160 } 161 *out = output; 162 return result; 163 164 bad: 165 *out = NULL; 166 for (j = 0; buf[j].flag != 0; j++) 167 free(buf[j].out, M_CRYPTO_DATA); 168 if (comp) 169 inflateEnd(&zbuf); 170 else 171 deflateEnd(&zbuf); 172 return 0; 173 } 174