1 /* $NetBSD: deflate.c,v 1.23 2017/05/17 06:33:04 knakahara 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 (at) 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.23 2017/05/17 06:33:04 knakahara 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 #define ZBUF 10 50 51 struct deflate_buf { 52 u_int8_t *out; 53 u_int32_t size; 54 }; 55 56 int window_inflate = -1 * MAX_WBITS; 57 int window_deflate = -12; 58 59 /* 60 * This function takes a block of data and (de)compress it using the deflate 61 * algorithm 62 */ 63 64 static void * 65 ocf_zalloc(void *nil, u_int type, u_int size) 66 { 67 void *ptr; 68 69 ptr = malloc(type *size, M_CRYPTO_DATA, M_NOWAIT); 70 return ptr; 71 } 72 73 static void 74 ocf_zfree(void *nil, void *ptr) 75 { 76 free(ptr, M_CRYPTO_DATA); 77 } 78 79 u_int32_t 80 deflate_global(u_int8_t *data, u_int32_t size, int decomp, u_int8_t **out, 81 int size_hint) 82 { 83 /* decomp indicates whether we compress (0) or decompress (1) */ 84 85 z_stream zbuf; 86 u_int8_t *output; 87 u_int32_t count, result, tocopy; 88 int error, i, j; 89 struct deflate_buf buf[ZBUF]; 90 91 DPRINTF("size %u\n", size); 92 93 memset(&zbuf, 0, sizeof(z_stream)); 94 zbuf.next_in = data; /* data that is going to be processed */ 95 zbuf.zalloc = ocf_zalloc; 96 zbuf.zfree = ocf_zfree; 97 zbuf.opaque = Z_NULL; 98 zbuf.avail_in = size; /* Total length of data to be processed */ 99 100 if (!decomp) { 101 buf[0].size = size; 102 } else { 103 /* 104 * Choose a buffer with 4x the size of the input buffer 105 * for the size of the output buffer in the case of 106 * decompression. If it's not sufficient, it will need to be 107 * updated while the decompression is going on 108 */ 109 110 buf[0].size = MAX(size * 4, size_hint); 111 } 112 buf[0].out = malloc(buf[0].size, M_CRYPTO_DATA, M_NOWAIT); 113 if (buf[0].out == NULL) 114 return 0; 115 i = 1; 116 117 zbuf.next_out = buf[0].out; 118 zbuf.avail_out = buf[0].size; 119 120 error = decomp ? inflateInit2(&zbuf, window_inflate) : 121 deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD, 122 window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY); 123 124 if (error != Z_OK) 125 goto bad2; 126 for (;;) { 127 error = decomp ? inflate(&zbuf, Z_SYNC_FLUSH) : 128 deflate(&zbuf, Z_FINISH); 129 if (error == Z_STREAM_END) /* success */ 130 break; 131 /* 132 * XXX compensate for two problems: 133 * -Former versions of this code didn't set Z_FINISH 134 * on compression, so the compressed data are not correctly 135 * terminated and the decompressor doesn't get Z_STREAM_END. 136 * Accept such packets for interoperability. 137 * -sys/net/zlib.c has a bug which makes that Z_BUF_ERROR is 138 * set after successful decompression under rare conditions. 139 */ 140 else if (decomp && (error == Z_OK || error == Z_BUF_ERROR) 141 && zbuf.avail_in == 0 && zbuf.avail_out != 0) 142 break; 143 else if (error != Z_OK) 144 goto bad; 145 else if (zbuf.avail_out == 0) { 146 /* we need more output space, allocate size */ 147 int nextsize = buf[i-1].size * 2; 148 if (i == ZBUF || nextsize > 1000000) 149 goto bad; 150 buf[i].out = malloc(nextsize, M_CRYPTO_DATA, M_NOWAIT); 151 if (buf[i].out == NULL) 152 goto bad; 153 zbuf.next_out = buf[i].out; 154 zbuf.avail_out = buf[i].size = nextsize; 155 i++; 156 } 157 } 158 159 result = count = zbuf.total_out; 160 161 if (i != 1) { /* copy everything into one buffer */ 162 output = malloc(result, M_CRYPTO_DATA, M_NOWAIT); 163 if (output == NULL) 164 goto bad; 165 *out = output; 166 for (j = 0; j < i; j++) { 167 tocopy = MIN(count, buf[j].size); 168 /* XXX the last buf can be empty */ 169 KASSERT(tocopy || j == (i - 1)); 170 memcpy(output, buf[j].out, tocopy); 171 output += tocopy; 172 free(buf[j].out, M_CRYPTO_DATA); 173 count -= tocopy; 174 } 175 KASSERT(count == 0); 176 } else { 177 *out = buf[0].out; 178 } 179 if (decomp) 180 inflateEnd(&zbuf); 181 else 182 deflateEnd(&zbuf); 183 return result; 184 185 bad: 186 if (decomp) 187 inflateEnd(&zbuf); 188 else 189 deflateEnd(&zbuf); 190 bad2: 191 for (j = 0; j < i; j++) 192 free(buf[j].out, M_CRYPTO_DATA); 193 return 0; 194 } 195 196 /* 197 * Initial version will perform a single gzip encapsulation, 198 * filling in the header, 199 * and appending the crc and uncompressed length. 200 * 201 * Later version will support multiple buffers with 202 * a flag indication final buffer. The crc is maintained 203 * over all buffers and appended to the output along with 204 * the uncompressed length after the final data buffer 205 * has been compressed and output. 206 * 207 * Ditto for uncompress - CRC is extracted from the final packed 208 * and compared against CRC of uncompressed data. 209 * 210 */ 211 212 /* constant header for the gzip */ 213 static const char gzip_header[10] = { 214 0x1f, 0x8b, /* ID1 ID2 */ 215 Z_DEFLATED, /* CM */ 216 0, /* FLG */ 217 0, 0, 0, 0, /* MTIME */ 218 0, /* XFL */ 219 0x03 /* OS (Unix) */ 220 }; 221 222 /* Followed by compressed payload */ 223 /* Followed by uint32_t CRC32 and uint32_t ISIZE */ 224 #define GZIP_TAIL_SIZE 8 225 226 u_int32_t 227 gzip_global(u_int8_t *data, u_int32_t size, 228 int decomp, u_int8_t **out, int size_hint) 229 { 230 /* decomp indicates whether we compress (0) or decompress (1) */ 231 z_stream zbuf; 232 u_int8_t *output; 233 u_int32_t count, result; 234 int error, i, j; 235 struct deflate_buf buf[ZBUF]; 236 u_int32_t crc; 237 u_int32_t isize = 0, icrc = 0; 238 239 DPRINTF("decomp %d, size %u\n", decomp, size); 240 241 memset(&zbuf, 0, sizeof(z_stream)); 242 zbuf.zalloc = ocf_zalloc; 243 zbuf.zfree = ocf_zfree; 244 zbuf.opaque = Z_NULL; 245 246 if (!decomp) { 247 /* compress */ 248 DPRINTF("compress malloc %u + %zu + %u = %zu\n", 249 size, sizeof(gzip_header), GZIP_TAIL_SIZE, 250 size + sizeof(gzip_header) + GZIP_TAIL_SIZE); 251 252 buf[0].size = size; 253 crc = crc32(0, data, size); 254 DPRINTF("size %u, crc 0x%x\n", size, crc); 255 zbuf.avail_in = size; /* Total length of data to be processed */ 256 zbuf.next_in = data; /* data that is going to be processed */ 257 } else { 258 /* decompress */ 259 /* check the gzip header */ 260 if (size <= sizeof(gzip_header) + GZIP_TAIL_SIZE) { 261 /* Not enough data for the header & tail */ 262 DPRINTF("not enough data (%u)\n", size); 263 return 0; 264 } 265 266 /* XXX this is pretty basic, 267 * needs to be expanded to ignore MTIME, OS, 268 * but still ensure flags are 0. 269 * Q. Do we need to support the flags and 270 * optional header fields? Likely. 271 * XXX add flag and field support too. 272 */ 273 if (memcmp(data, gzip_header, sizeof(gzip_header)) != 0) { 274 DPRINTF("unsupported gzip header (%02x%02x)\n", 275 data[0], data[1]); 276 return 0; 277 } else { 278 DPRINTF("%d: gzip header ok\n",__LINE__); 279 } 280 281 memcpy(&isize, &data[size-sizeof(uint32_t)], sizeof(uint32_t)); 282 LE32TOH(isize); 283 memcpy(&icrc, &data[size-2*sizeof(uint32_t)], sizeof(uint32_t)); 284 LE32TOH(icrc); 285 286 DPRINTF("isize = %u (%02x %02x %02x %02x)\n", 287 isize, 288 data[size-4], 289 data[size-3], 290 data[size-2], 291 data[size-1]); 292 293 buf[0].size = isize; 294 crc = crc32(0, NULL, 0); /* get initial crc value */ 295 296 /* skip over the gzip header */ 297 zbuf.next_in = data + sizeof(gzip_header); 298 299 /* actual payload size stripped of gzip header and tail */ 300 zbuf.avail_in = size - sizeof(gzip_header) - GZIP_TAIL_SIZE; 301 } 302 303 buf[0].out = malloc(buf[0].size, M_CRYPTO_DATA, M_NOWAIT); 304 if (buf[0].out == NULL) 305 return 0; 306 zbuf.next_out = buf[0].out; 307 zbuf.avail_out = buf[0].size; 308 DPRINTF("zbuf avail_in %u, avail_out %u\n", 309 zbuf.avail_in, zbuf.avail_out); 310 i = 1; 311 312 error = decomp ? inflateInit2(&zbuf, window_inflate) : 313 deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD, 314 window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY); 315 316 if (error != Z_OK) { 317 printf("deflateInit2() failed\n"); 318 goto bad2; 319 } 320 for (;;) { 321 DPRINTF("pre: %s in:%u out:%u\n", decomp ? "deflate()" : "inflate()", 322 zbuf.avail_in, zbuf.avail_out); 323 error = decomp ? inflate(&zbuf, Z_SYNC_FLUSH) : 324 deflate(&zbuf, Z_FINISH); 325 DPRINTF("post: %s in:%u out:%u\n", decomp ? "deflate()" : "inflate()", 326 zbuf.avail_in, zbuf.avail_out); 327 if (error == Z_STREAM_END) /* success */ 328 break; 329 /* 330 * XXX compensate for a zlib problem: 331 * -sys/net/zlib.c has a bug which makes that Z_BUF_ERROR is 332 * set after successful decompression under rare conditions. 333 */ 334 else if (decomp && error == Z_BUF_ERROR 335 && zbuf.avail_in == 0 && zbuf.avail_out != 0) 336 break; 337 else if (error != Z_OK) 338 goto bad; 339 else if (zbuf.avail_out == 0) { 340 /* we need more output space, allocate size */ 341 int nextsize = buf[i-1].size * 2; 342 if (i == ZBUF || nextsize > 1000000) 343 goto bad; 344 buf[i].out = malloc(nextsize, M_CRYPTO_DATA, M_NOWAIT); 345 if (buf[i].out == NULL) 346 goto bad; 347 zbuf.next_out = buf[i].out; 348 zbuf.avail_out = buf[i].size = nextsize; 349 i++; 350 } 351 } 352 353 if (decomp) { 354 count = result = zbuf.total_out; 355 } else { 356 /* need room for header, CRC, and ISIZE */ 357 result = zbuf.total_out + sizeof(gzip_header) + GZIP_TAIL_SIZE; 358 count = zbuf.total_out; 359 } 360 361 DPRINTF("in %u -> out %u\n", size, result); 362 363 *out = malloc(result, M_CRYPTO_DATA, M_NOWAIT); 364 if (*out == NULL) 365 goto bad; 366 output = *out; 367 if (decomp) 368 inflateEnd(&zbuf); 369 else { 370 deflateEnd(&zbuf); 371 372 /* fill in gzip header */ 373 memcpy(output, gzip_header, sizeof(gzip_header)); 374 output += sizeof(gzip_header); 375 } 376 for (j = 0; j < i; j++) { 377 if (decomp) { 378 /* update crc for decompressed data */ 379 crc = crc32(crc, buf[j].out, MIN(count, buf[j].size)); 380 } 381 if (count > buf[j].size) { 382 memcpy(output, buf[j].out, buf[j].size); 383 output += buf[j].size; 384 free(buf[j].out, M_CRYPTO_DATA); 385 count -= buf[j].size; 386 } else { 387 /* it should be the last buffer */ 388 memcpy(output, buf[j].out, count); 389 output += count; 390 free(buf[j].out, M_CRYPTO_DATA); 391 count = 0; 392 } 393 } 394 395 if (!decomp) { 396 /* fill in CRC and ISIZE */ 397 HTOLE32(crc); 398 memcpy(output, &crc, sizeof(uint32_t)); 399 HTOLE32(size); 400 memcpy(output + sizeof(uint32_t), &size, sizeof(uint32_t)); 401 402 DPRINTF("size = 0x%x (%02x %02x %02x %02x)\n", 403 size, 404 output[7], 405 output[3], 406 output[5], 407 output[4]); 408 } else { 409 if (crc != icrc || result != isize) { 410 DPRINTF("crc/size mismatch\n"); 411 free(*out, M_CRYPTO_DATA); 412 *out = NULL; 413 return 0; 414 } 415 } 416 417 return result; 418 419 bad: 420 if (decomp) 421 inflateEnd(&zbuf); 422 else 423 deflateEnd(&zbuf); 424 bad2: 425 *out = NULL; 426 for (j = 0; j < i; j++) 427 free(buf[j].out, M_CRYPTO_DATA); 428 return 0; 429 } 430