]>
Commit | Line | Data |
---|---|---|
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> | |
bdbc9b4d | 6 | #include <openssl/err.h> |
dfeab068 RE |
7 | |
8 | COMP_METHOD *COMP_zlib(void ); | |
9 | ||
20f88b9b | 10 | static COMP_METHOD zlib_method_nozlib={ |
dfeab068 | 11 | NID_undef, |
20f88b9b | 12 | "(undef)", |
dfeab068 RE |
13 | NULL, |
14 | NULL, | |
15 | NULL, | |
16 | NULL, | |
17 | NULL, | |
a4614bf0 | 18 | NULL, |
dfeab068 RE |
19 | }; |
20 | ||
c4438dc0 RL |
21 | #ifndef ZLIB |
22 | #undef ZLIB_SHARED | |
23 | #else | |
dfeab068 RE |
24 | |
25 | #include <zlib.h> | |
26 | ||
86a62cf1 RL |
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 | ||
6895cca8 | 34 | #if 0 |
dfeab068 RE |
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 | ||
86a62cf1 | 43 | static COMP_METHOD zlib_stateless_method={ |
dfeab068 RE |
44 | NID_zlib_compression, |
45 | LN_zlib_compression, | |
46 | NULL, | |
47 | NULL, | |
48 | zlib_compress_block, | |
49 | zlib_expand_block, | |
50 | NULL, | |
a4614bf0 | 51 | NULL, |
dfeab068 | 52 | }; |
6895cca8 | 53 | #endif |
dfeab068 | 54 | |
86a62cf1 RL |
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 | ||
20f88b9b RL |
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 | |
ad2695b1 | 70 | * and we do not link to a .LIB file when ZLIB_SHARED is set. |
20f88b9b | 71 | */ |
bc36ee62 | 72 | #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) |
c4438dc0 | 73 | # include <windows.h> |
bc36ee62 | 74 | #endif /* !(OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32) */ |
c4438dc0 RL |
75 | |
76 | #ifdef ZLIB_SHARED | |
77 | #include <openssl/dso.h> | |
20f88b9b | 78 | |
20f88b9b | 79 | /* Function pointers */ |
ad2695b1 | 80 | typedef int (*compress_ft)(Bytef *dest,uLongf *destLen, |
20f88b9b | 81 | const Bytef *source, uLong sourceLen); |
ad2695b1 DSH |
82 | typedef int (*inflateEnd_ft)(z_streamp strm); |
83 | typedef int (*inflate_ft)(z_streamp strm, int flush); | |
84 | typedef int (*inflateInit__ft)(z_streamp strm, | |
c4438dc0 | 85 | const char * version, int stream_size); |
ad2695b1 DSH |
86 | typedef int (*deflateEnd_ft)(z_streamp strm); |
87 | typedef int (*deflate_ft)(z_streamp strm, int flush); | |
88 | typedef int (*deflateInit__ft)(z_streamp strm, int level, | |
86a62cf1 | 89 | const char * version, int stream_size); |
c4438dc0 RL |
90 | static compress_ft p_compress=NULL; |
91 | static inflateEnd_ft p_inflateEnd=NULL; | |
92 | static inflate_ft p_inflate=NULL; | |
93 | static inflateInit__ft p_inflateInit_=NULL; | |
86a62cf1 RL |
94 | static deflateEnd_ft p_deflateEnd=NULL; |
95 | static deflate_ft p_deflate=NULL; | |
96 | static deflateInit__ft p_deflateInit_=NULL; | |
20f88b9b RL |
97 | |
98 | static int zlib_loaded = 0; /* only attempt to init func pts once */ | |
c4438dc0 | 99 | static DSO *zlib_dso = NULL; |
20f88b9b | 100 | |
ad2695b1 DSH |
101 | #define compress p_compress |
102 | #define inflateEnd p_inflateEnd | |
103 | #define inflate p_inflate | |
104 | #define inflateInit_ p_inflateInit_ | |
105 | #define deflateEnd p_deflateEnd | |
106 | #define deflate p_deflate | |
107 | #define deflateInit_ p_deflateInit_ | |
c4438dc0 | 108 | #endif /* ZLIB_SHARED */ |
20f88b9b | 109 | |
86a62cf1 RL |
110 | struct zlib_state |
111 | { | |
112 | z_stream istream; | |
113 | z_stream ostream; | |
114 | }; | |
115 | ||
116 | static int zlib_stateful_ex_idx = -1; | |
117 | ||
118 | static void zlib_stateful_free_ex_data(void *obj, void *item, | |
119 | CRYPTO_EX_DATA *ad, int ind,long argl, void *argp) | |
120 | { | |
121 | struct zlib_state *state = (struct zlib_state *)item; | |
122 | inflateEnd(&state->istream); | |
123 | deflateEnd(&state->ostream); | |
124 | OPENSSL_free(state); | |
125 | } | |
126 | ||
127 | static int zlib_stateful_init(COMP_CTX *ctx) | |
128 | { | |
129 | int err; | |
130 | struct zlib_state *state = | |
131 | (struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state)); | |
132 | ||
133 | if (state == NULL) | |
134 | goto err; | |
135 | ||
136 | state->istream.zalloc = Z_NULL; | |
137 | state->istream.zfree = Z_NULL; | |
138 | state->istream.opaque = Z_NULL; | |
139 | state->istream.next_in = Z_NULL; | |
140 | state->istream.next_out = Z_NULL; | |
141 | state->istream.avail_in = 0; | |
142 | state->istream.avail_out = 0; | |
6895cca8 RL |
143 | err = inflateInit_(&state->istream, |
144 | ZLIB_VERSION, sizeof(z_stream)); | |
86a62cf1 RL |
145 | if (err != Z_OK) |
146 | goto err; | |
147 | ||
148 | state->ostream.zalloc = Z_NULL; | |
149 | state->ostream.zfree = Z_NULL; | |
150 | state->ostream.opaque = Z_NULL; | |
151 | state->ostream.next_in = Z_NULL; | |
152 | state->ostream.next_out = Z_NULL; | |
153 | state->ostream.avail_in = 0; | |
154 | state->ostream.avail_out = 0; | |
6895cca8 RL |
155 | err = deflateInit_(&state->ostream,Z_DEFAULT_COMPRESSION, |
156 | ZLIB_VERSION, sizeof(z_stream)); | |
86a62cf1 RL |
157 | if (err != Z_OK) |
158 | goto err; | |
159 | ||
160 | CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data); | |
161 | if (zlib_stateful_ex_idx == -1) | |
162 | { | |
c40b9bde RL |
163 | CRYPTO_w_lock(CRYPTO_LOCK_COMP); |
164 | if (zlib_stateful_ex_idx == -1) | |
165 | zlib_stateful_ex_idx = | |
166 | CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP, | |
167 | 0,NULL,NULL,NULL,zlib_stateful_free_ex_data); | |
168 | CRYPTO_w_unlock(CRYPTO_LOCK_COMP); | |
86a62cf1 RL |
169 | if (zlib_stateful_ex_idx == -1) |
170 | goto err; | |
171 | } | |
172 | CRYPTO_set_ex_data(&ctx->ex_data,zlib_stateful_ex_idx,state); | |
173 | return 1; | |
174 | err: | |
175 | if (state) OPENSSL_free(state); | |
176 | return 0; | |
177 | } | |
178 | ||
179 | static void zlib_stateful_finish(COMP_CTX *ctx) | |
180 | { | |
181 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data); | |
182 | } | |
183 | ||
184 | static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, | |
185 | unsigned int olen, unsigned char *in, unsigned int ilen) | |
186 | { | |
187 | int err = Z_OK; | |
188 | struct zlib_state *state = | |
189 | (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, | |
190 | zlib_stateful_ex_idx); | |
191 | ||
192 | if (state == NULL) | |
193 | return -1; | |
194 | ||
195 | state->ostream.next_in = in; | |
196 | state->ostream.avail_in = ilen; | |
197 | state->ostream.next_out = out; | |
198 | state->ostream.avail_out = olen; | |
199 | if (ilen > 0) | |
200 | err = deflate(&state->ostream, Z_SYNC_FLUSH); | |
201 | if (err != Z_OK) | |
202 | return -1; | |
8228f302 RL |
203 | #ifdef DEBUG_ZLIB |
204 | fprintf(stderr,"compress(%4d)->%4d %s\n", | |
205 | ilen,olen - state->ostream.avail_out, | |
206 | (ilen != olen - state->ostream.avail_out)?"zlib":"clear"); | |
207 | #endif | |
86a62cf1 RL |
208 | return olen - state->ostream.avail_out; |
209 | } | |
210 | ||
211 | static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, | |
212 | unsigned int olen, unsigned char *in, unsigned int ilen) | |
213 | { | |
214 | int err = Z_OK; | |
215 | ||
216 | struct zlib_state *state = | |
217 | (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data, | |
218 | zlib_stateful_ex_idx); | |
219 | ||
220 | if (state == NULL) | |
221 | return 0; | |
222 | ||
223 | state->istream.next_in = in; | |
224 | state->istream.avail_in = ilen; | |
225 | state->istream.next_out = out; | |
226 | state->istream.avail_out = olen; | |
227 | if (ilen > 0) | |
228 | err = inflate(&state->istream, Z_SYNC_FLUSH); | |
229 | if (err != Z_OK) | |
230 | return -1; | |
8228f302 RL |
231 | #ifdef DEBUG_ZLIB |
232 | fprintf(stderr,"expand(%4d)->%4d %s\n", | |
233 | ilen,olen - state->istream.avail_out, | |
234 | (ilen != olen - state->istream.avail_out)?"zlib":"clear"); | |
235 | #endif | |
86a62cf1 RL |
236 | return olen - state->istream.avail_out; |
237 | } | |
238 | ||
6895cca8 | 239 | #if 0 |
6b691a5c | 240 | static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, |
86a62cf1 | 241 | unsigned int olen, unsigned char *in, unsigned int ilen) |
dfeab068 RE |
242 | { |
243 | unsigned long l; | |
244 | int i; | |
245 | int clear=1; | |
246 | ||
247 | if (ilen > 128) | |
248 | { | |
249 | out[0]=1; | |
250 | l=olen-1; | |
251 | i=compress(&(out[1]),&l,in,(unsigned long)ilen); | |
252 | if (i != Z_OK) | |
253 | return(-1); | |
254 | if (ilen > l) | |
255 | { | |
256 | clear=0; | |
257 | l++; | |
258 | } | |
259 | } | |
260 | if (clear) | |
261 | { | |
262 | out[0]=0; | |
263 | memcpy(&(out[1]),in,ilen); | |
264 | l=ilen+1; | |
265 | } | |
20f88b9b RL |
266 | #ifdef DEBUG_ZLIB |
267 | fprintf(stderr,"compress(%4d)->%4d %s\n", | |
268 | ilen,(int)l,(clear)?"clear":"zlib"); | |
269 | #endif | |
dfeab068 RE |
270 | return((int)l); |
271 | } | |
272 | ||
6b691a5c | 273 | static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, |
86a62cf1 | 274 | unsigned int olen, unsigned char *in, unsigned int ilen) |
dfeab068 RE |
275 | { |
276 | unsigned long l; | |
277 | int i; | |
278 | ||
279 | if (in[0]) | |
280 | { | |
281 | l=olen; | |
282 | i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1); | |
283 | if (i != Z_OK) | |
284 | return(-1); | |
285 | } | |
286 | else | |
287 | { | |
288 | memcpy(out,&(in[1]),ilen-1); | |
289 | l=ilen-1; | |
290 | } | |
20f88b9b RL |
291 | #ifdef DEBUG_ZLIB |
292 | fprintf(stderr,"expand (%4d)->%4d %s\n", | |
293 | ilen,(int)l,in[0]?"zlib":"clear"); | |
294 | #endif | |
dfeab068 RE |
295 | return((int)l); |
296 | } | |
297 | ||
6b691a5c UM |
298 | static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, |
299 | uLong sourceLen) | |
dfeab068 RE |
300 | { |
301 | z_stream stream; | |
302 | int err; | |
303 | ||
304 | stream.next_in = (Bytef*)source; | |
305 | stream.avail_in = (uInt)sourceLen; | |
306 | /* Check for source > 64K on 16-bit machine: */ | |
307 | if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; | |
308 | ||
309 | stream.next_out = dest; | |
310 | stream.avail_out = (uInt)*destLen; | |
311 | if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; | |
312 | ||
313 | stream.zalloc = (alloc_func)0; | |
314 | stream.zfree = (free_func)0; | |
315 | ||
6895cca8 RL |
316 | err = inflateInit_(&stream, |
317 | ZLIB_VERSION, sizeof(z_stream)); | |
dfeab068 RE |
318 | if (err != Z_OK) return err; |
319 | ||
320 | err = inflate(&stream, Z_FINISH); | |
321 | if (err != Z_STREAM_END) { | |
322 | inflateEnd(&stream); | |
323 | return err; | |
324 | } | |
325 | *destLen = stream.total_out; | |
326 | ||
327 | err = inflateEnd(&stream); | |
328 | return err; | |
329 | } | |
6895cca8 | 330 | #endif |
dfeab068 RE |
331 | |
332 | #endif | |
333 | ||
6b691a5c | 334 | COMP_METHOD *COMP_zlib(void) |
dfeab068 | 335 | { |
20f88b9b RL |
336 | COMP_METHOD *meth = &zlib_method_nozlib; |
337 | ||
c4438dc0 RL |
338 | #ifdef ZLIB_SHARED |
339 | if (!zlib_loaded) | |
20f88b9b | 340 | { |
bc36ee62 | 341 | #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) |
5b0f1f7d | 342 | zlib_dso = DSO_load(NULL, "ZLIB1", NULL, 0); |
c4438dc0 RL |
343 | #else |
344 | zlib_dso = DSO_load(NULL, "z", NULL, 0); | |
345 | #endif | |
346 | if (zlib_dso != NULL) | |
20f88b9b | 347 | { |
c4438dc0 RL |
348 | p_compress |
349 | = (compress_ft) DSO_bind_func(zlib_dso, | |
350 | "compress"); | |
351 | p_inflateEnd | |
352 | = (inflateEnd_ft) DSO_bind_func(zlib_dso, | |
353 | "inflateEnd"); | |
354 | p_inflate | |
355 | = (inflate_ft) DSO_bind_func(zlib_dso, | |
356 | "inflate"); | |
357 | p_inflateInit_ | |
358 | = (inflateInit__ft) DSO_bind_func(zlib_dso, | |
359 | "inflateInit_"); | |
86a62cf1 RL |
360 | p_deflateEnd |
361 | = (deflateEnd_ft) DSO_bind_func(zlib_dso, | |
362 | "deflateEnd"); | |
363 | p_deflate | |
364 | = (deflate_ft) DSO_bind_func(zlib_dso, | |
365 | "deflate"); | |
366 | p_deflateInit_ | |
367 | = (deflateInit__ft) DSO_bind_func(zlib_dso, | |
368 | "deflateInit_"); | |
da5a0e87 DSH |
369 | |
370 | if (p_compress && p_inflateEnd && p_inflate | |
371 | && p_inflateInit_ && p_deflateEnd | |
372 | && p_deflate && p_deflateInit_) | |
373 | zlib_loaded++; | |
20f88b9b RL |
374 | } |
375 | } | |
376 | ||
e984b2af | 377 | #endif |
0d894c9d | 378 | #ifdef ZLIB_SHARED |
da5a0e87 | 379 | if (zlib_loaded) |
0d894c9d DSH |
380 | #endif |
381 | #if defined(ZLIB) || defined(ZLIB_SHARED) | |
da5a0e87 | 382 | meth = &zlib_stateful_method; |
20f88b9b RL |
383 | #endif |
384 | ||
385 | return(meth); | |
386 | } | |
387 |