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