xref: /minix3/crypto/external/bsd/netpgp/dist/src/lib/compress.c (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1*ebfedea0SLionel Sambuc /*-
2*ebfedea0SLionel Sambuc  * Copyright (c) 2009 The NetBSD Foundation, Inc.
3*ebfedea0SLionel Sambuc  * All rights reserved.
4*ebfedea0SLionel Sambuc  *
5*ebfedea0SLionel Sambuc  * This code is derived from software contributed to The NetBSD Foundation
6*ebfedea0SLionel Sambuc  * by Alistair Crooks (agc@NetBSD.org)
7*ebfedea0SLionel Sambuc  *
8*ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9*ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10*ebfedea0SLionel Sambuc  * are met:
11*ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
12*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
13*ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
14*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
15*ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
16*ebfedea0SLionel Sambuc  *
17*ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18*ebfedea0SLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19*ebfedea0SLionel Sambuc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20*ebfedea0SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21*ebfedea0SLionel Sambuc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*ebfedea0SLionel Sambuc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*ebfedea0SLionel Sambuc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*ebfedea0SLionel Sambuc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*ebfedea0SLionel Sambuc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*ebfedea0SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*ebfedea0SLionel Sambuc  * POSSIBILITY OF SUCH DAMAGE.
28*ebfedea0SLionel Sambuc  */
29*ebfedea0SLionel Sambuc /*
30*ebfedea0SLionel Sambuc  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31*ebfedea0SLionel Sambuc  * All rights reserved.
32*ebfedea0SLionel Sambuc  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33*ebfedea0SLionel Sambuc  * their moral rights under the UK Copyright Design and Patents Act 1988 to
34*ebfedea0SLionel Sambuc  * be recorded as the authors of this copyright work.
35*ebfedea0SLionel Sambuc  *
36*ebfedea0SLionel Sambuc  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37*ebfedea0SLionel Sambuc  * use this file except in compliance with the License.
38*ebfedea0SLionel Sambuc  *
39*ebfedea0SLionel Sambuc  * You may obtain a copy of the License at
40*ebfedea0SLionel Sambuc  *     http://www.apache.org/licenses/LICENSE-2.0
41*ebfedea0SLionel Sambuc  *
42*ebfedea0SLionel Sambuc  * Unless required by applicable law or agreed to in writing, software
43*ebfedea0SLionel Sambuc  * distributed under the License is distributed on an "AS IS" BASIS,
44*ebfedea0SLionel Sambuc  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45*ebfedea0SLionel Sambuc  *
46*ebfedea0SLionel Sambuc  * See the License for the specific language governing permissions and
47*ebfedea0SLionel Sambuc  * limitations under the License.
48*ebfedea0SLionel Sambuc  */
49*ebfedea0SLionel Sambuc 
50*ebfedea0SLionel Sambuc /** \file
51*ebfedea0SLionel Sambuc  */
52*ebfedea0SLionel Sambuc #include "config.h"
53*ebfedea0SLionel Sambuc 
54*ebfedea0SLionel Sambuc #ifdef HAVE_SYS_CDEFS_H
55*ebfedea0SLionel Sambuc #include <sys/cdefs.h>
56*ebfedea0SLionel Sambuc #endif
57*ebfedea0SLionel Sambuc 
58*ebfedea0SLionel Sambuc #if defined(__NetBSD__)
59*ebfedea0SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60*ebfedea0SLionel Sambuc __RCSID("$NetBSD: compress.c,v 1.23 2012/03/05 02:20:18 christos Exp $");
61*ebfedea0SLionel Sambuc #endif
62*ebfedea0SLionel Sambuc 
63*ebfedea0SLionel Sambuc #ifdef HAVE_ZLIB_H
64*ebfedea0SLionel Sambuc #include <zlib.h>
65*ebfedea0SLionel Sambuc #endif
66*ebfedea0SLionel Sambuc 
67*ebfedea0SLionel Sambuc #ifdef HAVE_BZLIB_H
68*ebfedea0SLionel Sambuc #include <bzlib.h>
69*ebfedea0SLionel Sambuc #endif
70*ebfedea0SLionel Sambuc 
71*ebfedea0SLionel Sambuc #include <string.h>
72*ebfedea0SLionel Sambuc 
73*ebfedea0SLionel Sambuc #include "packet-parse.h"
74*ebfedea0SLionel Sambuc #include "errors.h"
75*ebfedea0SLionel Sambuc #include "netpgpdefs.h"
76*ebfedea0SLionel Sambuc #include "crypto.h"
77*ebfedea0SLionel Sambuc #include "memory.h"
78*ebfedea0SLionel Sambuc #include "writer.h"
79*ebfedea0SLionel Sambuc 
80*ebfedea0SLionel Sambuc #define DECOMPRESS_BUFFER	1024
81*ebfedea0SLionel Sambuc 
82*ebfedea0SLionel Sambuc typedef struct {
83*ebfedea0SLionel Sambuc 	pgp_compression_type_t type;
84*ebfedea0SLionel Sambuc 	pgp_region_t   *region;
85*ebfedea0SLionel Sambuc 	uint8_t   	in[DECOMPRESS_BUFFER];
86*ebfedea0SLionel Sambuc 	uint8_t   	out[DECOMPRESS_BUFFER];
87*ebfedea0SLionel Sambuc 	z_stream        zstream;/* ZIP and ZLIB */
88*ebfedea0SLionel Sambuc 	size_t          offset;
89*ebfedea0SLionel Sambuc 	int             inflate_ret;
90*ebfedea0SLionel Sambuc } z_decompress_t;
91*ebfedea0SLionel Sambuc 
92*ebfedea0SLionel Sambuc #ifdef HAVE_BZLIB_H
93*ebfedea0SLionel Sambuc typedef struct {
94*ebfedea0SLionel Sambuc 	pgp_compression_type_t type;
95*ebfedea0SLionel Sambuc 	pgp_region_t   *region;
96*ebfedea0SLionel Sambuc 	char            in[DECOMPRESS_BUFFER];
97*ebfedea0SLionel Sambuc 	char            out[DECOMPRESS_BUFFER];
98*ebfedea0SLionel Sambuc 	bz_stream       bzstream;	/* BZIP2 */
99*ebfedea0SLionel Sambuc 	size_t          offset;
100*ebfedea0SLionel Sambuc 	int             inflate_ret;
101*ebfedea0SLionel Sambuc } bz_decompress_t;
102*ebfedea0SLionel Sambuc #endif
103*ebfedea0SLionel Sambuc 
104*ebfedea0SLionel Sambuc typedef struct {
105*ebfedea0SLionel Sambuc 	z_stream        stream;
106*ebfedea0SLionel Sambuc 	uint8_t  	*src;
107*ebfedea0SLionel Sambuc 	uint8_t  	*dst;
108*ebfedea0SLionel Sambuc } compress_t;
109*ebfedea0SLionel Sambuc 
110*ebfedea0SLionel Sambuc /*
111*ebfedea0SLionel Sambuc  * \todo remove code duplication between this and
112*ebfedea0SLionel Sambuc  * bzip2_compressed_data_reader
113*ebfedea0SLionel Sambuc  */
114*ebfedea0SLionel Sambuc static int
zlib_compressed_data_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)115*ebfedea0SLionel Sambuc zlib_compressed_data_reader(pgp_stream_t *stream, void *dest, size_t length,
116*ebfedea0SLionel Sambuc 			    pgp_error_t **errors,
117*ebfedea0SLionel Sambuc 			    pgp_reader_t *readinfo,
118*ebfedea0SLionel Sambuc 			    pgp_cbdata_t *cbinfo)
119*ebfedea0SLionel Sambuc {
120*ebfedea0SLionel Sambuc 	z_decompress_t *z = pgp_reader_get_arg(readinfo);
121*ebfedea0SLionel Sambuc 	size_t           len;
122*ebfedea0SLionel Sambuc 	size_t		 cc;
123*ebfedea0SLionel Sambuc 	char		*cdest = dest;
124*ebfedea0SLionel Sambuc 
125*ebfedea0SLionel Sambuc 	if (z->type != PGP_C_ZIP && z->type != PGP_C_ZLIB) {
126*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
127*ebfedea0SLionel Sambuc 			"zlib_compressed_data_reader: weird type %d\n",
128*ebfedea0SLionel Sambuc 			z->type);
129*ebfedea0SLionel Sambuc 		return 0;
130*ebfedea0SLionel Sambuc 	}
131*ebfedea0SLionel Sambuc 
132*ebfedea0SLionel Sambuc 	if (z->inflate_ret == Z_STREAM_END &&
133*ebfedea0SLionel Sambuc 	    z->zstream.next_out == &z->out[z->offset]) {
134*ebfedea0SLionel Sambuc 		return 0;
135*ebfedea0SLionel Sambuc 	}
136*ebfedea0SLionel Sambuc 	if (pgp_get_debug_level(__FILE__)) {
137*ebfedea0SLionel Sambuc 		(void) fprintf(stderr,
138*ebfedea0SLionel Sambuc 			"zlib_compressed_data_reader: length %" PRIsize "d\n",
139*ebfedea0SLionel Sambuc 			length);
140*ebfedea0SLionel Sambuc 	}
141*ebfedea0SLionel Sambuc 	for (cc = 0 ; cc < length ; cc += len) {
142*ebfedea0SLionel Sambuc 		if (&z->out[z->offset] == z->zstream.next_out) {
143*ebfedea0SLionel Sambuc 			int             ret;
144*ebfedea0SLionel Sambuc 
145*ebfedea0SLionel Sambuc 			z->zstream.next_out = z->out;
146*ebfedea0SLionel Sambuc 			z->zstream.avail_out = sizeof(z->out);
147*ebfedea0SLionel Sambuc 			z->offset = 0;
148*ebfedea0SLionel Sambuc 			if (z->zstream.avail_in == 0) {
149*ebfedea0SLionel Sambuc 				unsigned        n = z->region->length;
150*ebfedea0SLionel Sambuc 
151*ebfedea0SLionel Sambuc 				if (!z->region->indeterminate) {
152*ebfedea0SLionel Sambuc 					n -= z->region->readc;
153*ebfedea0SLionel Sambuc 					if (n > sizeof(z->in)) {
154*ebfedea0SLionel Sambuc 						n = sizeof(z->in);
155*ebfedea0SLionel Sambuc 					}
156*ebfedea0SLionel Sambuc 				} else {
157*ebfedea0SLionel Sambuc 					n = sizeof(z->in);
158*ebfedea0SLionel Sambuc 				}
159*ebfedea0SLionel Sambuc 				if (!pgp_stacked_limited_read(stream, z->in, n,
160*ebfedea0SLionel Sambuc 						z->region,
161*ebfedea0SLionel Sambuc 						errors, readinfo, cbinfo)) {
162*ebfedea0SLionel Sambuc 					return -1;
163*ebfedea0SLionel Sambuc 				}
164*ebfedea0SLionel Sambuc 
165*ebfedea0SLionel Sambuc 				z->zstream.next_in = z->in;
166*ebfedea0SLionel Sambuc 				z->zstream.avail_in = (z->region->indeterminate) ?
167*ebfedea0SLionel Sambuc 					z->region->last_read : n;
168*ebfedea0SLionel Sambuc 			}
169*ebfedea0SLionel Sambuc 			ret = inflate(&z->zstream, Z_SYNC_FLUSH);
170*ebfedea0SLionel Sambuc 			if (ret == Z_STREAM_END) {
171*ebfedea0SLionel Sambuc 				if (!z->region->indeterminate &&
172*ebfedea0SLionel Sambuc 				    z->region->readc != z->region->length) {
173*ebfedea0SLionel Sambuc 					PGP_ERROR_1(cbinfo->errors,
174*ebfedea0SLionel Sambuc 						PGP_E_P_DECOMPRESSION_ERROR,
175*ebfedea0SLionel Sambuc 						"%s",
176*ebfedea0SLionel Sambuc 						"Compressed stream ended before packet end.");
177*ebfedea0SLionel Sambuc 				}
178*ebfedea0SLionel Sambuc 			} else if (ret != Z_OK) {
179*ebfedea0SLionel Sambuc 				(void) fprintf(stderr, "ret=%d\n", ret);
180*ebfedea0SLionel Sambuc 				PGP_ERROR_1(cbinfo->errors,
181*ebfedea0SLionel Sambuc 					PGP_E_P_DECOMPRESSION_ERROR, "%s",
182*ebfedea0SLionel Sambuc 					z->zstream.msg);
183*ebfedea0SLionel Sambuc 			}
184*ebfedea0SLionel Sambuc 			z->inflate_ret = ret;
185*ebfedea0SLionel Sambuc 		}
186*ebfedea0SLionel Sambuc 		if (z->zstream.next_out <= &z->out[z->offset]) {
187*ebfedea0SLionel Sambuc 			(void) fprintf(stderr, "Out of memory in buffer\n");
188*ebfedea0SLionel Sambuc 			return 0;
189*ebfedea0SLionel Sambuc 		}
190*ebfedea0SLionel Sambuc 		len = (size_t)(z->zstream.next_out - &z->out[z->offset]);
191*ebfedea0SLionel Sambuc 		if (len > length) {
192*ebfedea0SLionel Sambuc 			len = length;
193*ebfedea0SLionel Sambuc 		}
194*ebfedea0SLionel Sambuc 		(void) memcpy(&cdest[cc], &z->out[z->offset], len);
195*ebfedea0SLionel Sambuc 		z->offset += len;
196*ebfedea0SLionel Sambuc 	}
197*ebfedea0SLionel Sambuc 
198*ebfedea0SLionel Sambuc 	return (int)length;
199*ebfedea0SLionel Sambuc }
200*ebfedea0SLionel Sambuc 
201*ebfedea0SLionel Sambuc #ifdef HAVE_BZLIB_H
202*ebfedea0SLionel Sambuc /* \todo remove code duplication between this and zlib_compressed_data_reader */
203*ebfedea0SLionel Sambuc static int
bzip2_compressed_data_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)204*ebfedea0SLionel Sambuc bzip2_compressed_data_reader(pgp_stream_t *stream, void *dest, size_t length,
205*ebfedea0SLionel Sambuc 			     pgp_error_t **errors,
206*ebfedea0SLionel Sambuc 			     pgp_reader_t *readinfo,
207*ebfedea0SLionel Sambuc 			     pgp_cbdata_t *cbinfo)
208*ebfedea0SLionel Sambuc {
209*ebfedea0SLionel Sambuc 	bz_decompress_t *bz = pgp_reader_get_arg(readinfo);
210*ebfedea0SLionel Sambuc 	size_t		len;
211*ebfedea0SLionel Sambuc 	size_t		 cc;
212*ebfedea0SLionel Sambuc 	char		*cdest = dest;
213*ebfedea0SLionel Sambuc 
214*ebfedea0SLionel Sambuc 	if (bz->type != PGP_C_BZIP2) {
215*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "Weird type %d\n", bz->type);
216*ebfedea0SLionel Sambuc 		return 0;
217*ebfedea0SLionel Sambuc 	}
218*ebfedea0SLionel Sambuc 	if (bz->inflate_ret == BZ_STREAM_END &&
219*ebfedea0SLionel Sambuc 	    bz->bzstream.next_out == &bz->out[bz->offset]) {
220*ebfedea0SLionel Sambuc 		return 0;
221*ebfedea0SLionel Sambuc 	}
222*ebfedea0SLionel Sambuc 	for (cc = 0 ; cc < length ; cc += len) {
223*ebfedea0SLionel Sambuc 		if (&bz->out[bz->offset] == bz->bzstream.next_out) {
224*ebfedea0SLionel Sambuc 			int             ret;
225*ebfedea0SLionel Sambuc 
226*ebfedea0SLionel Sambuc 			bz->bzstream.next_out = (char *) bz->out;
227*ebfedea0SLionel Sambuc 			bz->bzstream.avail_out = sizeof(bz->out);
228*ebfedea0SLionel Sambuc 			bz->offset = 0;
229*ebfedea0SLionel Sambuc 			if (bz->bzstream.avail_in == 0) {
230*ebfedea0SLionel Sambuc 				unsigned        n = bz->region->length;
231*ebfedea0SLionel Sambuc 
232*ebfedea0SLionel Sambuc 				if (!bz->region->indeterminate) {
233*ebfedea0SLionel Sambuc 					n -= bz->region->readc;
234*ebfedea0SLionel Sambuc 					if (n > sizeof(bz->in))
235*ebfedea0SLionel Sambuc 						n = sizeof(bz->in);
236*ebfedea0SLionel Sambuc 				} else
237*ebfedea0SLionel Sambuc 					n = sizeof(bz->in);
238*ebfedea0SLionel Sambuc 
239*ebfedea0SLionel Sambuc 				if (!pgp_stacked_limited_read(stream,
240*ebfedea0SLionel Sambuc 						(uint8_t *) bz->in,
241*ebfedea0SLionel Sambuc 						n, bz->region,
242*ebfedea0SLionel Sambuc 						errors, readinfo, cbinfo))
243*ebfedea0SLionel Sambuc 					return -1;
244*ebfedea0SLionel Sambuc 
245*ebfedea0SLionel Sambuc 				bz->bzstream.next_in = bz->in;
246*ebfedea0SLionel Sambuc 				bz->bzstream.avail_in =
247*ebfedea0SLionel Sambuc 					(bz->region->indeterminate) ?
248*ebfedea0SLionel Sambuc 					 bz->region->last_read : n;
249*ebfedea0SLionel Sambuc 			}
250*ebfedea0SLionel Sambuc 			ret = BZ2_bzDecompress(&bz->bzstream);
251*ebfedea0SLionel Sambuc 			if (ret == BZ_STREAM_END) {
252*ebfedea0SLionel Sambuc 				if (!bz->region->indeterminate &&
253*ebfedea0SLionel Sambuc 				    bz->region->readc != bz->region->length)
254*ebfedea0SLionel Sambuc 					PGP_ERROR_1(cbinfo->errors,
255*ebfedea0SLionel Sambuc 						PGP_E_P_DECOMPRESSION_ERROR,
256*ebfedea0SLionel Sambuc 						"%s",
257*ebfedea0SLionel Sambuc 						"Compressed stream ended before packet end.");
258*ebfedea0SLionel Sambuc 			} else if (ret != BZ_OK) {
259*ebfedea0SLionel Sambuc 				PGP_ERROR_1(cbinfo->errors,
260*ebfedea0SLionel Sambuc 					PGP_E_P_DECOMPRESSION_ERROR,
261*ebfedea0SLionel Sambuc 					"Invalid return %d from BZ2_bzDecompress", ret);
262*ebfedea0SLionel Sambuc 			}
263*ebfedea0SLionel Sambuc 			bz->inflate_ret = ret;
264*ebfedea0SLionel Sambuc 		}
265*ebfedea0SLionel Sambuc 		if (bz->bzstream.next_out <= &bz->out[bz->offset]) {
266*ebfedea0SLionel Sambuc 			(void) fprintf(stderr, "Out of bz memroy\n");
267*ebfedea0SLionel Sambuc 			return 0;
268*ebfedea0SLionel Sambuc 		}
269*ebfedea0SLionel Sambuc 		len = (size_t)(bz->bzstream.next_out - &bz->out[bz->offset]);
270*ebfedea0SLionel Sambuc 		if (len > length) {
271*ebfedea0SLionel Sambuc 			len = length;
272*ebfedea0SLionel Sambuc 		}
273*ebfedea0SLionel Sambuc 		(void) memcpy(&cdest[cc], &bz->out[bz->offset], len);
274*ebfedea0SLionel Sambuc 		bz->offset += len;
275*ebfedea0SLionel Sambuc 	}
276*ebfedea0SLionel Sambuc 
277*ebfedea0SLionel Sambuc 	return (int)length;
278*ebfedea0SLionel Sambuc }
279*ebfedea0SLionel Sambuc #endif
280*ebfedea0SLionel Sambuc 
281*ebfedea0SLionel Sambuc /**
282*ebfedea0SLionel Sambuc  * \ingroup Core_Compress
283*ebfedea0SLionel Sambuc  *
284*ebfedea0SLionel Sambuc  * \param *region 	Pointer to a region
285*ebfedea0SLionel Sambuc  * \param *stream 	How to parse
286*ebfedea0SLionel Sambuc  * \param type Which compression type to expect
287*ebfedea0SLionel Sambuc */
288*ebfedea0SLionel Sambuc 
289*ebfedea0SLionel Sambuc int
pgp_decompress(pgp_region_t * region,pgp_stream_t * stream,pgp_compression_type_t type)290*ebfedea0SLionel Sambuc pgp_decompress(pgp_region_t *region, pgp_stream_t *stream,
291*ebfedea0SLionel Sambuc 	       pgp_compression_type_t type)
292*ebfedea0SLionel Sambuc {
293*ebfedea0SLionel Sambuc 	z_decompress_t z;
294*ebfedea0SLionel Sambuc #ifdef HAVE_BZLIB_H
295*ebfedea0SLionel Sambuc 	bz_decompress_t bz;
296*ebfedea0SLionel Sambuc #endif
297*ebfedea0SLionel Sambuc 	const int	printerrors = 1;
298*ebfedea0SLionel Sambuc 	int             ret;
299*ebfedea0SLionel Sambuc 
300*ebfedea0SLionel Sambuc 	switch (type) {
301*ebfedea0SLionel Sambuc 	case PGP_C_ZIP:
302*ebfedea0SLionel Sambuc 	case PGP_C_ZLIB:
303*ebfedea0SLionel Sambuc 		(void) memset(&z, 0x0, sizeof(z));
304*ebfedea0SLionel Sambuc 
305*ebfedea0SLionel Sambuc 		z.region = region;
306*ebfedea0SLionel Sambuc 		z.offset = 0;
307*ebfedea0SLionel Sambuc 		z.type = type;
308*ebfedea0SLionel Sambuc 
309*ebfedea0SLionel Sambuc 		z.zstream.next_in = Z_NULL;
310*ebfedea0SLionel Sambuc 		z.zstream.avail_in = 0;
311*ebfedea0SLionel Sambuc 		z.zstream.next_out = z.out;
312*ebfedea0SLionel Sambuc 		z.zstream.zalloc = Z_NULL;
313*ebfedea0SLionel Sambuc 		z.zstream.zfree = Z_NULL;
314*ebfedea0SLionel Sambuc 		z.zstream.opaque = Z_NULL;
315*ebfedea0SLionel Sambuc 
316*ebfedea0SLionel Sambuc 		break;
317*ebfedea0SLionel Sambuc 
318*ebfedea0SLionel Sambuc #ifdef HAVE_BZLIB_H
319*ebfedea0SLionel Sambuc 	case PGP_C_BZIP2:
320*ebfedea0SLionel Sambuc 		(void) memset(&bz, 0x0, sizeof(bz));
321*ebfedea0SLionel Sambuc 
322*ebfedea0SLionel Sambuc 		bz.region = region;
323*ebfedea0SLionel Sambuc 		bz.offset = 0;
324*ebfedea0SLionel Sambuc 		bz.type = type;
325*ebfedea0SLionel Sambuc 
326*ebfedea0SLionel Sambuc 		bz.bzstream.next_in = NULL;
327*ebfedea0SLionel Sambuc 		bz.bzstream.avail_in = 0;
328*ebfedea0SLionel Sambuc 		bz.bzstream.next_out = bz.out;
329*ebfedea0SLionel Sambuc 		bz.bzstream.bzalloc = NULL;
330*ebfedea0SLionel Sambuc 		bz.bzstream.bzfree = NULL;
331*ebfedea0SLionel Sambuc 		bz.bzstream.opaque = NULL;
332*ebfedea0SLionel Sambuc #endif
333*ebfedea0SLionel Sambuc 
334*ebfedea0SLionel Sambuc 		break;
335*ebfedea0SLionel Sambuc 
336*ebfedea0SLionel Sambuc 	default:
337*ebfedea0SLionel Sambuc 		PGP_ERROR_1(&stream->errors,
338*ebfedea0SLionel Sambuc 			PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG,
339*ebfedea0SLionel Sambuc 			"Compression algorithm %d is not yet supported", type);
340*ebfedea0SLionel Sambuc 		return 0;
341*ebfedea0SLionel Sambuc 	}
342*ebfedea0SLionel Sambuc 
343*ebfedea0SLionel Sambuc 	switch (type) {
344*ebfedea0SLionel Sambuc 	case PGP_C_ZIP:
345*ebfedea0SLionel Sambuc 		/* LINTED */ /* this is a lint problem in zlib.h header */
346*ebfedea0SLionel Sambuc 		ret = (int)inflateInit2(&z.zstream, -15);
347*ebfedea0SLionel Sambuc 		break;
348*ebfedea0SLionel Sambuc 
349*ebfedea0SLionel Sambuc 	case PGP_C_ZLIB:
350*ebfedea0SLionel Sambuc 		/* LINTED */ /* this is a lint problem in zlib.h header */
351*ebfedea0SLionel Sambuc 		ret = (int)inflateInit(&z.zstream);
352*ebfedea0SLionel Sambuc 		break;
353*ebfedea0SLionel Sambuc 
354*ebfedea0SLionel Sambuc #ifdef HAVE_BZLIB_H
355*ebfedea0SLionel Sambuc 	case PGP_C_BZIP2:
356*ebfedea0SLionel Sambuc 		ret = BZ2_bzDecompressInit(&bz.bzstream, 1, 0);
357*ebfedea0SLionel Sambuc 		break;
358*ebfedea0SLionel Sambuc #endif
359*ebfedea0SLionel Sambuc 
360*ebfedea0SLionel Sambuc 	default:
361*ebfedea0SLionel Sambuc 		PGP_ERROR_1(&stream->errors,
362*ebfedea0SLionel Sambuc 			PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG,
363*ebfedea0SLionel Sambuc 			"Compression algorithm %d is not yet supported", type);
364*ebfedea0SLionel Sambuc 		return 0;
365*ebfedea0SLionel Sambuc 	}
366*ebfedea0SLionel Sambuc 
367*ebfedea0SLionel Sambuc 	switch (type) {
368*ebfedea0SLionel Sambuc 	case PGP_C_ZIP:
369*ebfedea0SLionel Sambuc 	case PGP_C_ZLIB:
370*ebfedea0SLionel Sambuc 		if (ret != Z_OK) {
371*ebfedea0SLionel Sambuc 			PGP_ERROR_1(&stream->errors,
372*ebfedea0SLionel Sambuc 				PGP_E_P_DECOMPRESSION_ERROR,
373*ebfedea0SLionel Sambuc "Cannot initialise ZIP or ZLIB stream for decompression: error=%d", ret);
374*ebfedea0SLionel Sambuc 			return 0;
375*ebfedea0SLionel Sambuc 		}
376*ebfedea0SLionel Sambuc 		pgp_reader_push(stream, zlib_compressed_data_reader,
377*ebfedea0SLionel Sambuc 					NULL, &z);
378*ebfedea0SLionel Sambuc 		break;
379*ebfedea0SLionel Sambuc 
380*ebfedea0SLionel Sambuc #ifdef HAVE_BZLIB_H
381*ebfedea0SLionel Sambuc 	case PGP_C_BZIP2:
382*ebfedea0SLionel Sambuc 		if (ret != BZ_OK) {
383*ebfedea0SLionel Sambuc 			PGP_ERROR_1(&stream->errors,
384*ebfedea0SLionel Sambuc 				PGP_E_P_DECOMPRESSION_ERROR,
385*ebfedea0SLionel Sambuc "Cannot initialise BZIP2 stream for decompression: error=%d", ret);
386*ebfedea0SLionel Sambuc 			return 0;
387*ebfedea0SLionel Sambuc 		}
388*ebfedea0SLionel Sambuc 		pgp_reader_push(stream, bzip2_compressed_data_reader,
389*ebfedea0SLionel Sambuc 					NULL, &bz);
390*ebfedea0SLionel Sambuc 		break;
391*ebfedea0SLionel Sambuc #endif
392*ebfedea0SLionel Sambuc 
393*ebfedea0SLionel Sambuc 	default:
394*ebfedea0SLionel Sambuc 		PGP_ERROR_1(&stream->errors,
395*ebfedea0SLionel Sambuc 			PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG,
396*ebfedea0SLionel Sambuc 			"Compression algorithm %d is not yet supported", type);
397*ebfedea0SLionel Sambuc 		return 0;
398*ebfedea0SLionel Sambuc 	}
399*ebfedea0SLionel Sambuc 
400*ebfedea0SLionel Sambuc 	ret = pgp_parse(stream, !printerrors);
401*ebfedea0SLionel Sambuc 
402*ebfedea0SLionel Sambuc 	pgp_reader_pop(stream);
403*ebfedea0SLionel Sambuc 
404*ebfedea0SLionel Sambuc 	return ret;
405*ebfedea0SLionel Sambuc }
406*ebfedea0SLionel Sambuc 
407*ebfedea0SLionel Sambuc /**
408*ebfedea0SLionel Sambuc \ingroup Core_WritePackets
409*ebfedea0SLionel Sambuc \brief Writes Compressed packet
410*ebfedea0SLionel Sambuc \param data Data to write out
411*ebfedea0SLionel Sambuc \param len Length of data
412*ebfedea0SLionel Sambuc \param output Write settings
413*ebfedea0SLionel Sambuc \return 1 if OK; else 0
414*ebfedea0SLionel Sambuc */
415*ebfedea0SLionel Sambuc 
416*ebfedea0SLionel Sambuc unsigned
pgp_writez(pgp_output_t * out,const uint8_t * data,const unsigned len)417*ebfedea0SLionel Sambuc pgp_writez(pgp_output_t *out, const uint8_t *data, const unsigned len)
418*ebfedea0SLionel Sambuc {
419*ebfedea0SLionel Sambuc 	compress_t	*zip;
420*ebfedea0SLionel Sambuc 	size_t		 sz_in;
421*ebfedea0SLionel Sambuc 	size_t		 sz_out;
422*ebfedea0SLionel Sambuc 	int              ret;
423*ebfedea0SLionel Sambuc 	int              r = 0;
424*ebfedea0SLionel Sambuc 
425*ebfedea0SLionel Sambuc 	/* compress the data */
426*ebfedea0SLionel Sambuc 	const int       level = Z_DEFAULT_COMPRESSION;	/* \todo allow varying
427*ebfedea0SLionel Sambuc 							 * levels */
428*ebfedea0SLionel Sambuc 
429*ebfedea0SLionel Sambuc 	if ((zip = calloc(1, sizeof(*zip))) == NULL) {
430*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "pgp_writez: bad alloc\n");
431*ebfedea0SLionel Sambuc 		return 0;
432*ebfedea0SLionel Sambuc 	}
433*ebfedea0SLionel Sambuc 	zip->stream.zalloc = Z_NULL;
434*ebfedea0SLionel Sambuc 	zip->stream.zfree = Z_NULL;
435*ebfedea0SLionel Sambuc 	zip->stream.opaque = NULL;
436*ebfedea0SLionel Sambuc 
437*ebfedea0SLionel Sambuc 	/* all other fields set to zero by use of calloc */
438*ebfedea0SLionel Sambuc 
439*ebfedea0SLionel Sambuc 	/* LINTED */ /* this is a lint problem in zlib.h header */
440*ebfedea0SLionel Sambuc 	if ((int)deflateInit(&zip->stream, level) != Z_OK) {
441*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "pgp_writez: can't initialise\n");
442*ebfedea0SLionel Sambuc 		return 0;
443*ebfedea0SLionel Sambuc 	}
444*ebfedea0SLionel Sambuc 	/* do necessary transformation */
445*ebfedea0SLionel Sambuc 	/* copy input to maintain const'ness of src */
446*ebfedea0SLionel Sambuc 	if (zip->src != NULL || zip->dst != NULL) {
447*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "pgp_writez: non-null streams\n");
448*ebfedea0SLionel Sambuc 		return 0;
449*ebfedea0SLionel Sambuc 	}
450*ebfedea0SLionel Sambuc 
451*ebfedea0SLionel Sambuc 	sz_in = len * sizeof(uint8_t);
452*ebfedea0SLionel Sambuc 	sz_out = ((101 * sz_in) / 100) + 12;	/* from zlib webpage */
453*ebfedea0SLionel Sambuc 	if ((zip->src = calloc(1, sz_in)) == NULL) {
454*ebfedea0SLionel Sambuc 		free(zip);
455*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "pgp_writez: bad alloc2\n");
456*ebfedea0SLionel Sambuc 		return 0;
457*ebfedea0SLionel Sambuc 	}
458*ebfedea0SLionel Sambuc 	if ((zip->dst = calloc(1, sz_out)) == NULL) {
459*ebfedea0SLionel Sambuc 		free(zip->src);
460*ebfedea0SLionel Sambuc 		free(zip);
461*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "pgp_writez: bad alloc3\n");
462*ebfedea0SLionel Sambuc 		return 0;
463*ebfedea0SLionel Sambuc 	}
464*ebfedea0SLionel Sambuc 	(void) memcpy(zip->src, data, len);
465*ebfedea0SLionel Sambuc 
466*ebfedea0SLionel Sambuc 	/* setup stream */
467*ebfedea0SLionel Sambuc 	zip->stream.next_in = zip->src;
468*ebfedea0SLionel Sambuc 	zip->stream.avail_in = (unsigned)sz_in;
469*ebfedea0SLionel Sambuc 	zip->stream.total_in = 0;
470*ebfedea0SLionel Sambuc 
471*ebfedea0SLionel Sambuc 	zip->stream.next_out = zip->dst;
472*ebfedea0SLionel Sambuc 	zip->stream.avail_out = (unsigned)sz_out;
473*ebfedea0SLionel Sambuc 	zip->stream.total_out = 0;
474*ebfedea0SLionel Sambuc 
475*ebfedea0SLionel Sambuc 	do {
476*ebfedea0SLionel Sambuc 		r = deflate(&zip->stream, Z_FINISH);
477*ebfedea0SLionel Sambuc 	} while (r != Z_STREAM_END);
478*ebfedea0SLionel Sambuc 
479*ebfedea0SLionel Sambuc 	/* write it out */
480*ebfedea0SLionel Sambuc 	ret = pgp_write_ptag(out, PGP_PTAG_CT_COMPRESSED) &&
481*ebfedea0SLionel Sambuc 		pgp_write_length(out, (unsigned)(zip->stream.total_out + 1))&&
482*ebfedea0SLionel Sambuc 		pgp_write_scalar(out, PGP_C_ZLIB, 1) &&
483*ebfedea0SLionel Sambuc 		pgp_write(out, zip->dst, (unsigned)zip->stream.total_out);
484*ebfedea0SLionel Sambuc 
485*ebfedea0SLionel Sambuc 	free(zip->src);
486*ebfedea0SLionel Sambuc 	free(zip->dst);
487*ebfedea0SLionel Sambuc 	free(zip);
488*ebfedea0SLionel Sambuc 	return ret;
489*ebfedea0SLionel Sambuc }
490