1 /* $OpenBSD: xform_ipcomp.c,v 1.8 2019/01/09 12:11:38 mpi 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 33 */ 34 35 #include <sys/param.h> 36 #include <sys/malloc.h> 37 #include <sys/systm.h> 38 #include <lib/libz/zutil.h> 39 40 #define Z_METHOD 8 41 #define Z_MEMLEVEL 8 42 #define ZBUF 10 43 44 u_int32_t deflate_global(u_int8_t *, u_int32_t, int, u_int8_t **); 45 46 struct deflate_buf { 47 u_int8_t *out; 48 u_int32_t size; 49 int flag; 50 }; 51 52 int window_inflate = -1 * MAX_WBITS; 53 int window_deflate = -12; 54 55 /* 56 * This function takes a block of data and (de)compress it using the deflate 57 * algorithm 58 */ 59 60 u_int32_t 61 deflate_global(u_int8_t *data, u_int32_t size, int decomp, u_int8_t **out) 62 { 63 z_stream zbuf; 64 u_int8_t *output; 65 u_int32_t count, result; 66 int error, i = 0, j; 67 struct deflate_buf buf[ZBUF]; 68 69 bzero(&zbuf, sizeof(z_stream)); 70 for (j = 0; j < ZBUF; j++) 71 buf[j].flag = 0; 72 73 zbuf.next_in = data; /* data that is going to be processed */ 74 zbuf.zalloc = zcalloc; 75 zbuf.zfree = zcfree; 76 zbuf.opaque = Z_NULL; 77 zbuf.avail_in = size; /* Total length of data to be processed */ 78 79 if (decomp) { 80 /* 81 * Choose a buffer with 4x the size of the input buffer 82 * for the size of the output buffer in the case of 83 * decompression. If it's not sufficient, it will need to be 84 * updated while the decompression is going on 85 */ 86 if (size < 32 * 1024) 87 size *= 4; 88 } 89 buf[i].out = malloc((u_long)size, M_CRYPTO_DATA, M_NOWAIT); 90 if (buf[i].out == NULL) 91 goto bad; 92 buf[i].size = size; 93 buf[i].flag = 1; 94 i++; 95 96 zbuf.next_out = buf[0].out; 97 zbuf.avail_out = buf[0].size; 98 99 error = decomp ? 100 inflateInit2(&zbuf, window_inflate) : 101 deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD, 102 window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY); 103 104 if (error != Z_OK) 105 goto bad; 106 for (;;) { 107 error = decomp ? 108 inflate(&zbuf, Z_PARTIAL_FLUSH) : 109 deflate(&zbuf, Z_FINISH); 110 if (error == Z_STREAM_END) 111 break; 112 if (error != Z_OK) 113 goto bad; 114 if (zbuf.avail_out == 0 && i < (ZBUF - 1)) { 115 /* we need more output space, allocate size */ 116 if (size < 32 * 1024) 117 size *= 2; 118 buf[i].out = malloc((u_long)size, M_CRYPTO_DATA, 119 M_NOWAIT); 120 if (buf[i].out == NULL) 121 goto bad; 122 zbuf.next_out = buf[i].out; 123 buf[i].size = size; 124 buf[i].flag = 1; 125 zbuf.avail_out = buf[i].size; 126 i++; 127 } else 128 goto bad; /* out of buffers */ 129 } 130 result = count = zbuf.total_out; 131 132 *out = malloc((u_long)result, M_CRYPTO_DATA, M_NOWAIT); 133 if (*out == NULL) 134 goto bad; 135 if (decomp) 136 inflateEnd(&zbuf); 137 else 138 deflateEnd(&zbuf); 139 output = *out; 140 for (j = 0; buf[j].flag != 0; j++) { 141 if (count > buf[j].size) { 142 bcopy(buf[j].out, *out, buf[j].size); 143 *out += buf[j].size; 144 free(buf[j].out, M_CRYPTO_DATA, buf[j].size); 145 count -= buf[j].size; 146 } else { 147 /* it should be the last buffer */ 148 bcopy(buf[j].out, *out, count); 149 *out += count; 150 free(buf[j].out, M_CRYPTO_DATA, buf[j].size); 151 count = 0; 152 } 153 } 154 *out = output; 155 return result; 156 157 bad: 158 *out = NULL; 159 for (j = 0; buf[j].flag != 0; j++) 160 free(buf[j].out, M_CRYPTO_DATA, buf[j].size); 161 if (decomp) 162 inflateEnd(&zbuf); 163 else 164 deflateEnd(&zbuf); 165 return 0; 166 } 167