xref: /onnv-gate/usr/src/common/openssl/crypto/comp/c_zlib.c (revision 2139:6243c3338933)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <openssl/objects.h>
5 #include <openssl/comp.h>
6 #include <openssl/err.h>
7 
8 COMP_METHOD *COMP_zlib(void );
9 
10 static COMP_METHOD zlib_method_nozlib={
11 	NID_undef,
12 	"(undef)",
13 	NULL,
14 	NULL,
15 	NULL,
16 	NULL,
17 	NULL,
18 	NULL,
19 	};
20 
21 #ifndef ZLIB
22 #undef ZLIB_SHARED
23 #else
24 
25 #include <zlib.h>
26 
27 static int zlib_stateful_init(COMP_CTX *ctx);
28 static void zlib_stateful_finish(COMP_CTX *ctx);
29 static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
30 	unsigned int olen, unsigned char *in, unsigned int ilen);
31 static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
32 	unsigned int olen, unsigned char *in, unsigned int ilen);
33 
34 #if 0
35 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
36 	unsigned int olen, unsigned char *in, unsigned int ilen);
37 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
38 	unsigned int olen, unsigned char *in, unsigned int ilen);
39 
40 static int zz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
41 	uLong sourceLen);
42 
43 static COMP_METHOD zlib_stateless_method={
44 	NID_zlib_compression,
45 	LN_zlib_compression,
46 	NULL,
47 	NULL,
48 	zlib_compress_block,
49 	zlib_expand_block,
50 	NULL,
51 	NULL,
52 	};
53 #endif
54 
55 static COMP_METHOD zlib_stateful_method={
56 	NID_zlib_compression,
57 	LN_zlib_compression,
58 	zlib_stateful_init,
59 	zlib_stateful_finish,
60 	zlib_stateful_compress_block,
61 	zlib_stateful_expand_block,
62 	NULL,
63 	NULL,
64 	};
65 
66 /*
67  * When OpenSSL is built on Windows, we do not want to require that
68  * the ZLIB.DLL be available in order for the OpenSSL DLLs to
69  * work.  Therefore, all ZLIB routines are loaded at run time
70  * and we do not link to a .LIB file.
71  */
72 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
73 # include <windows.h>
74 
75 # define Z_CALLCONV _stdcall
76 # ifndef ZLIB_SHARED
77 #  define ZLIB_SHARED
78 # endif
79 #else
80 # define Z_CALLCONV
81 #endif /* !(OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32) */
82 
83 #ifdef ZLIB_SHARED
84 #include <openssl/dso.h>
85 
86 /* Prototypes for built in stubs */
87 #if 0
88 static int stub_compress(Bytef *dest,uLongf *destLen,
89 	const Bytef *source, uLong sourceLen);
90 #endif
91 static int stub_inflateEnd(z_streamp strm);
92 static int stub_inflate(z_streamp strm, int flush);
93 static int stub_inflateInit_(z_streamp strm, const char * version,
94 	int stream_size);
95 static int stub_deflateEnd(z_streamp strm);
96 static int stub_deflate(z_streamp strm, int flush);
97 static int stub_deflateInit_(z_streamp strm, int level,
98 	const char * version, int stream_size);
99 
100 /* Function pointers */
101 typedef int (Z_CALLCONV *compress_ft)(Bytef *dest,uLongf *destLen,
102 	const Bytef *source, uLong sourceLen);
103 typedef int (Z_CALLCONV *inflateEnd_ft)(z_streamp strm);
104 typedef int (Z_CALLCONV *inflate_ft)(z_streamp strm, int flush);
105 typedef int (Z_CALLCONV *inflateInit__ft)(z_streamp strm,
106 	const char * version, int stream_size);
107 typedef int (Z_CALLCONV *deflateEnd_ft)(z_streamp strm);
108 typedef int (Z_CALLCONV *deflate_ft)(z_streamp strm, int flush);
109 typedef int (Z_CALLCONV *deflateInit__ft)(z_streamp strm, int level,
110 	const char * version, int stream_size);
111 static compress_ft	p_compress=NULL;
112 static inflateEnd_ft	p_inflateEnd=NULL;
113 static inflate_ft	p_inflate=NULL;
114 static inflateInit__ft	p_inflateInit_=NULL;
115 static deflateEnd_ft	p_deflateEnd=NULL;
116 static deflate_ft	p_deflate=NULL;
117 static deflateInit__ft	p_deflateInit_=NULL;
118 
119 static int zlib_loaded = 0;     /* only attempt to init func pts once */
120 static DSO *zlib_dso = NULL;
121 
122 #define compress                stub_compress
123 #define inflateEnd              stub_inflateEnd
124 #define inflate                 stub_inflate
125 #define inflateInit_            stub_inflateInit_
126 #define deflateEnd              stub_deflateEnd
127 #define deflate                 stub_deflate
128 #define deflateInit_            stub_deflateInit_
129 #endif /* ZLIB_SHARED */
130 
131 struct zlib_state
132 	{
133 	z_stream istream;
134 	z_stream ostream;
135 	};
136 
137 static int zlib_stateful_ex_idx = -1;
138 
zlib_stateful_free_ex_data(void * obj,void * item,CRYPTO_EX_DATA * ad,int ind,long argl,void * argp)139 static void zlib_stateful_free_ex_data(void *obj, void *item,
140 	CRYPTO_EX_DATA *ad, int ind,long argl, void *argp)
141 	{
142 	struct zlib_state *state = (struct zlib_state *)item;
143 	inflateEnd(&state->istream);
144 	deflateEnd(&state->ostream);
145 	OPENSSL_free(state);
146 	}
147 
zlib_stateful_init(COMP_CTX * ctx)148 static int zlib_stateful_init(COMP_CTX *ctx)
149 	{
150 	int err;
151 	struct zlib_state *state =
152 		(struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state));
153 
154 	if (state == NULL)
155 		goto err;
156 
157 	state->istream.zalloc = Z_NULL;
158 	state->istream.zfree = Z_NULL;
159 	state->istream.opaque = Z_NULL;
160 	state->istream.next_in = Z_NULL;
161 	state->istream.next_out = Z_NULL;
162 	state->istream.avail_in = 0;
163 	state->istream.avail_out = 0;
164 	err = inflateInit_(&state->istream,
165 		ZLIB_VERSION, sizeof(z_stream));
166 	if (err != Z_OK)
167 		goto err;
168 
169 	state->ostream.zalloc = Z_NULL;
170 	state->ostream.zfree = Z_NULL;
171 	state->ostream.opaque = Z_NULL;
172 	state->ostream.next_in = Z_NULL;
173 	state->ostream.next_out = Z_NULL;
174 	state->ostream.avail_in = 0;
175 	state->ostream.avail_out = 0;
176 	err = deflateInit_(&state->ostream,Z_DEFAULT_COMPRESSION,
177 		ZLIB_VERSION, sizeof(z_stream));
178 	if (err != Z_OK)
179 		goto err;
180 
181 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
182 	if (zlib_stateful_ex_idx == -1)
183 		{
184 		CRYPTO_w_lock(CRYPTO_LOCK_COMP);
185 		if (zlib_stateful_ex_idx == -1)
186 			zlib_stateful_ex_idx =
187 				CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP,
188 					0,NULL,NULL,NULL,zlib_stateful_free_ex_data);
189 		CRYPTO_w_unlock(CRYPTO_LOCK_COMP);
190 		if (zlib_stateful_ex_idx == -1)
191 			goto err;
192 		}
193 	CRYPTO_set_ex_data(&ctx->ex_data,zlib_stateful_ex_idx,state);
194 	return 1;
195  err:
196 	if (state) OPENSSL_free(state);
197 	return 0;
198 	}
199 
zlib_stateful_finish(COMP_CTX * ctx)200 static void zlib_stateful_finish(COMP_CTX *ctx)
201 	{
202 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
203 	}
204 
zlib_stateful_compress_block(COMP_CTX * ctx,unsigned char * out,unsigned int olen,unsigned char * in,unsigned int ilen)205 static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
206 	unsigned int olen, unsigned char *in, unsigned int ilen)
207 	{
208 	int err = Z_OK;
209 	struct zlib_state *state =
210 		(struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
211 			zlib_stateful_ex_idx);
212 
213 	if (state == NULL)
214 		return -1;
215 
216 	state->ostream.next_in = in;
217 	state->ostream.avail_in = ilen;
218 	state->ostream.next_out = out;
219 	state->ostream.avail_out = olen;
220 	if (ilen > 0)
221 		err = deflate(&state->ostream, Z_SYNC_FLUSH);
222 	if (err != Z_OK)
223 		return -1;
224 #ifdef DEBUG_ZLIB
225 	fprintf(stderr,"compress(%4d)->%4d %s\n",
226 		ilen,olen - state->ostream.avail_out,
227 		(ilen != olen - state->ostream.avail_out)?"zlib":"clear");
228 #endif
229 	return olen - state->ostream.avail_out;
230 	}
231 
zlib_stateful_expand_block(COMP_CTX * ctx,unsigned char * out,unsigned int olen,unsigned char * in,unsigned int ilen)232 static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
233 	unsigned int olen, unsigned char *in, unsigned int ilen)
234 	{
235 	int err = Z_OK;
236 
237 	struct zlib_state *state =
238 		(struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
239 			zlib_stateful_ex_idx);
240 
241 	if (state == NULL)
242 		return 0;
243 
244 	state->istream.next_in = in;
245 	state->istream.avail_in = ilen;
246 	state->istream.next_out = out;
247 	state->istream.avail_out = olen;
248 	if (ilen > 0)
249 		err = inflate(&state->istream, Z_SYNC_FLUSH);
250 	if (err != Z_OK)
251 		return -1;
252 #ifdef DEBUG_ZLIB
253 	fprintf(stderr,"expand(%4d)->%4d %s\n",
254 		ilen,olen - state->istream.avail_out,
255 		(ilen != olen - state->istream.avail_out)?"zlib":"clear");
256 #endif
257 	return olen - state->istream.avail_out;
258 	}
259 
260 #if 0
261 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
262 	unsigned int olen, unsigned char *in, unsigned int ilen)
263 	{
264 	unsigned long l;
265 	int i;
266 	int clear=1;
267 
268 	if (ilen > 128)
269 		{
270 		out[0]=1;
271 		l=olen-1;
272 		i=compress(&(out[1]),&l,in,(unsigned long)ilen);
273 		if (i != Z_OK)
274 			return(-1);
275 		if (ilen > l)
276 			{
277 			clear=0;
278 			l++;
279 			}
280 		}
281 	if (clear)
282 		{
283 		out[0]=0;
284 		memcpy(&(out[1]),in,ilen);
285 		l=ilen+1;
286 		}
287 #ifdef DEBUG_ZLIB
288 	fprintf(stderr,"compress(%4d)->%4d %s\n",
289 		ilen,(int)l,(clear)?"clear":"zlib");
290 #endif
291 	return((int)l);
292 	}
293 
294 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
295 	unsigned int olen, unsigned char *in, unsigned int ilen)
296 	{
297 	unsigned long l;
298 	int i;
299 
300 	if (in[0])
301 		{
302 		l=olen;
303 		i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1);
304 		if (i != Z_OK)
305 			return(-1);
306 		}
307 	else
308 		{
309 		memcpy(out,&(in[1]),ilen-1);
310 		l=ilen-1;
311 		}
312 #ifdef DEBUG_ZLIB
313         fprintf(stderr,"expand  (%4d)->%4d %s\n",
314 		ilen,(int)l,in[0]?"zlib":"clear");
315 #endif
316 	return((int)l);
317 	}
318 
319 static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source,
320 	     uLong sourceLen)
321 {
322     z_stream stream;
323     int err;
324 
325     stream.next_in = (Bytef*)source;
326     stream.avail_in = (uInt)sourceLen;
327     /* Check for source > 64K on 16-bit machine: */
328     if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
329 
330     stream.next_out = dest;
331     stream.avail_out = (uInt)*destLen;
332     if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
333 
334     stream.zalloc = (alloc_func)0;
335     stream.zfree = (free_func)0;
336 
337     err = inflateInit_(&stream,
338 	    ZLIB_VERSION, sizeof(z_stream));
339     if (err != Z_OK) return err;
340 
341     err = inflate(&stream, Z_FINISH);
342     if (err != Z_STREAM_END) {
343         inflateEnd(&stream);
344         return err;
345     }
346     *destLen = stream.total_out;
347 
348     err = inflateEnd(&stream);
349     return err;
350 }
351 #endif
352 
353 #endif
354 
COMP_zlib(void)355 COMP_METHOD *COMP_zlib(void)
356 	{
357 	COMP_METHOD *meth = &zlib_method_nozlib;
358 
359 #ifdef ZLIB_SHARED
360 	if (!zlib_loaded)
361 		{
362 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
363 		zlib_dso = DSO_load(NULL, "ZLIB1", NULL, 0);
364 		if (!zlib_dso)
365 			{
366 			zlib_dso = DSO_load(NULL, "ZLIB", NULL, 0);
367 			if (zlib_dso)
368 				{
369 				/* Clear the errors from the first failed
370 				   DSO_load() */
371 				ERR_clear_error();
372 				}
373 			}
374 #else
375 		zlib_dso = DSO_load(NULL, "z", NULL, 0);
376 #endif
377 		if (zlib_dso != NULL)
378 			{
379 			p_compress
380 				= (compress_ft) DSO_bind_func(zlib_dso,
381 					"compress");
382 			p_inflateEnd
383 				= (inflateEnd_ft) DSO_bind_func(zlib_dso,
384 					"inflateEnd");
385 			p_inflate
386 				= (inflate_ft) DSO_bind_func(zlib_dso,
387 					"inflate");
388 			p_inflateInit_
389 				= (inflateInit__ft) DSO_bind_func(zlib_dso,
390 					"inflateInit_");
391 			p_deflateEnd
392 				= (deflateEnd_ft) DSO_bind_func(zlib_dso,
393 					"deflateEnd");
394 			p_deflate
395 				= (deflate_ft) DSO_bind_func(zlib_dso,
396 					"deflate");
397 			p_deflateInit_
398 				= (deflateInit__ft) DSO_bind_func(zlib_dso,
399 					"deflateInit_");
400 			zlib_loaded++;
401 			}
402 		}
403 
404 #endif
405 #if defined(ZLIB) || defined(ZLIB_SHARED)
406 	meth = &zlib_stateful_method;
407 #endif
408 
409 	return(meth);
410 	}
411 
412 #ifdef ZLIB_SHARED
413 #if 0
414 /* Stubs for each function to be dynamicly loaded */
415 static int
416 stub_compress(Bytef *dest,uLongf *destLen,const Bytef *source, uLong sourceLen)
417 	{
418 	if (p_compress)
419 		return(p_compress(dest,destLen,source,sourceLen));
420 	else
421 		return(Z_MEM_ERROR);
422 	}
423 #endif
424 
425 static int
stub_inflateEnd(z_streamp strm)426 stub_inflateEnd(z_streamp strm)
427 	{
428 	if ( p_inflateEnd )
429 		return(p_inflateEnd(strm));
430 	else
431 		return(Z_MEM_ERROR);
432 	}
433 
434 static int
stub_inflate(z_streamp strm,int flush)435 stub_inflate(z_streamp strm, int flush)
436 	{
437 	if ( p_inflate )
438 		return(p_inflate(strm,flush));
439 	else
440 		return(Z_MEM_ERROR);
441 	}
442 
443 static int
stub_inflateInit_(z_streamp strm,const char * version,int stream_size)444 stub_inflateInit_(z_streamp strm, const char * version, int stream_size)
445 	{
446 	if ( p_inflateInit_ )
447 		return(p_inflateInit_(strm,version,stream_size));
448 	else
449 		return(Z_MEM_ERROR);
450 	}
451 
452 static int
stub_deflateEnd(z_streamp strm)453 stub_deflateEnd(z_streamp strm)
454 	{
455 	if ( p_deflateEnd )
456 		return(p_deflateEnd(strm));
457 	else
458 		return(Z_MEM_ERROR);
459 	}
460 
461 static int
stub_deflate(z_streamp strm,int flush)462 stub_deflate(z_streamp strm, int flush)
463 	{
464 	if ( p_deflate )
465 		return(p_deflate(strm,flush));
466 	else
467 		return(Z_MEM_ERROR);
468 	}
469 
470 static int
stub_deflateInit_(z_streamp strm,int level,const char * version,int stream_size)471 stub_deflateInit_(z_streamp strm, int level,
472 	const char * version, int stream_size)
473 	{
474 	if ( p_deflateInit_ )
475 		return(p_deflateInit_(strm,level,version,stream_size));
476 	else
477 		return(Z_MEM_ERROR);
478 	}
479 
480 #endif /* ZLIB_SHARED */
481