1 /* $OpenBSD: c_zlib.c,v 1.20 2018/03/17 16:20:01 beck Exp $ */
5 #include <openssl/objects.h>
6 #include <openssl/comp.h>
7 #include <openssl/err.h>
9 COMP_METHOD
*COMP_zlib(void );
11 static COMP_METHOD zlib_method_nozlib
= {
20 static int zlib_stateful_init(COMP_CTX
*ctx
);
21 static void zlib_stateful_finish(COMP_CTX
*ctx
);
22 static int zlib_stateful_compress_block(COMP_CTX
*ctx
, unsigned char *out
,
23 unsigned int olen
, unsigned char *in
, unsigned int ilen
);
24 static int zlib_stateful_expand_block(COMP_CTX
*ctx
, unsigned char *out
,
25 unsigned int olen
, unsigned char *in
, unsigned int ilen
);
28 /* memory allocations functions for zlib intialization */
30 zlib_zalloc(void* opaque
, unsigned int no
, unsigned int size
)
32 return calloc(no
, size
);
36 zlib_zfree(void* opaque
, void* address
)
41 static COMP_METHOD zlib_stateful_method
= {
42 .type
= NID_zlib_compression
,
43 .name
= LN_zlib_compression
,
44 .init
= zlib_stateful_init
,
45 .finish
= zlib_stateful_finish
,
46 .compress
= zlib_stateful_compress_block
,
47 .expand
= zlib_stateful_expand_block
55 static int zlib_stateful_ex_idx
= -1;
58 zlib_stateful_init(COMP_CTX
*ctx
)
61 struct zlib_state
*state
= malloc(sizeof(struct zlib_state
));
66 state
->istream
.zalloc
= zlib_zalloc
;
67 state
->istream
.zfree
= zlib_zfree
;
68 state
->istream
.opaque
= Z_NULL
;
69 state
->istream
.next_in
= Z_NULL
;
70 state
->istream
.next_out
= Z_NULL
;
71 state
->istream
.avail_in
= 0;
72 state
->istream
.avail_out
= 0;
73 err
= inflateInit_(&state
->istream
, ZLIB_VERSION
, sizeof(z_stream
));
77 state
->ostream
.zalloc
= zlib_zalloc
;
78 state
->ostream
.zfree
= zlib_zfree
;
79 state
->ostream
.opaque
= Z_NULL
;
80 state
->ostream
.next_in
= Z_NULL
;
81 state
->ostream
.next_out
= Z_NULL
;
82 state
->ostream
.avail_in
= 0;
83 state
->ostream
.avail_out
= 0;
84 err
= deflateInit_(&state
->ostream
, Z_DEFAULT_COMPRESSION
,
85 ZLIB_VERSION
, sizeof(z_stream
));
89 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP
, ctx
, &ctx
->ex_data
);
90 CRYPTO_set_ex_data(&ctx
->ex_data
, zlib_stateful_ex_idx
, state
);
99 zlib_stateful_finish(COMP_CTX
*ctx
)
101 struct zlib_state
*state
=
102 (struct zlib_state
*)CRYPTO_get_ex_data(&ctx
->ex_data
,
103 zlib_stateful_ex_idx
);
105 inflateEnd(&state
->istream
);
106 deflateEnd(&state
->ostream
);
108 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP
, ctx
, &ctx
->ex_data
);
112 zlib_stateful_compress_block(COMP_CTX
*ctx
, unsigned char *out
,
113 unsigned int olen
, unsigned char *in
, unsigned int ilen
)
116 struct zlib_state
*state
=
117 (struct zlib_state
*)CRYPTO_get_ex_data(&ctx
->ex_data
,
118 zlib_stateful_ex_idx
);
123 state
->ostream
.next_in
= in
;
124 state
->ostream
.avail_in
= ilen
;
125 state
->ostream
.next_out
= out
;
126 state
->ostream
.avail_out
= olen
;
128 err
= deflate(&state
->ostream
, Z_SYNC_FLUSH
);
133 fprintf(stderr
, "compress(%4d)->%4d %s\n",
134 ilen
, olen
- state
->ostream
.avail_out
,
135 (ilen
!= olen
- state
->ostream
.avail_out
)?"zlib":"clear");
138 return olen
- state
->ostream
.avail_out
;
142 zlib_stateful_expand_block(COMP_CTX
*ctx
, unsigned char *out
,
143 unsigned int olen
, unsigned char *in
, unsigned int ilen
)
147 struct zlib_state
*state
=
148 (struct zlib_state
*)CRYPTO_get_ex_data(&ctx
->ex_data
,
149 zlib_stateful_ex_idx
);
154 state
->istream
.next_in
= in
;
155 state
->istream
.avail_in
= ilen
;
156 state
->istream
.next_out
= out
;
157 state
->istream
.avail_out
= olen
;
159 err
= inflate(&state
->istream
, Z_SYNC_FLUSH
);
164 fprintf(stderr
, "expand(%4d)->%4d %s\n",
165 ilen
, olen
- state
->istream
.avail_out
,
166 (ilen
!= olen
- state
->istream
.avail_out
)?"zlib":"clear");
169 return olen
- state
->istream
.avail_out
;
177 COMP_METHOD
*meth
= &zlib_method_nozlib
;
181 /* init zlib_stateful_ex_idx here so that in a multi-process
182 * application it's enough to intialize openssl before forking
183 * (idx will be inherited in all the children) */
184 if (zlib_stateful_ex_idx
== -1) {
185 CRYPTO_w_lock(CRYPTO_LOCK_COMP
);
186 if (zlib_stateful_ex_idx
== -1)
187 zlib_stateful_ex_idx
=
188 CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP
,
189 0, NULL
, NULL
, NULL
, NULL
);
190 CRYPTO_w_unlock(CRYPTO_LOCK_COMP
);
191 if (zlib_stateful_ex_idx
== -1)
194 if (!OPENSSL_init_crypto(0, NULL
))
197 meth
= &zlib_stateful_method
;
207 COMP_zlib_cleanup(void)
213 /* Zlib based compression/decompression filter BIO */
216 unsigned char *ibuf
; /* Input buffer */
217 int ibufsize
; /* Buffer size */
218 z_stream zin
; /* Input decompress context */
219 unsigned char *obuf
; /* Output buffer */
220 int obufsize
; /* Output buffer size */
221 unsigned char *optr
; /* Position in output buffer */
222 int ocount
; /* Amount of data in output buffer */
223 int odone
; /* deflate EOF */
224 int comp_level
; /* Compression level to use */
225 z_stream zout
; /* Output compression context */
228 #define ZLIB_DEFAULT_BUFSIZE 1024
230 static int bio_zlib_new(BIO
*bi
);
231 static int bio_zlib_free(BIO
*bi
);
232 static int bio_zlib_read(BIO
*b
, char *out
, int outl
);
233 static int bio_zlib_write(BIO
*b
, const char *in
, int inl
);
234 static long bio_zlib_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
);
235 static long bio_zlib_callback_ctrl(BIO
*b
, int cmd
, bio_info_cb
*fp
);
237 static BIO_METHOD bio_meth_zlib
= {
238 .type
= BIO_TYPE_COMP
,
240 .bwrite
= bio_zlib_write
,
241 .bread
= bio_zlib_read
,
242 .ctrl
= bio_zlib_ctrl
,
243 .create
= bio_zlib_new
,
244 .destroy
= bio_zlib_free
,
245 .callback_ctrl
= bio_zlib_callback_ctrl
251 return &bio_meth_zlib
;
256 bio_zlib_new(BIO
*bi
)
260 ctx
= malloc(sizeof(BIO_ZLIB_CTX
));
262 COMPerror(ERR_R_MALLOC_FAILURE
);
267 ctx
->ibufsize
= ZLIB_DEFAULT_BUFSIZE
;
268 ctx
->obufsize
= ZLIB_DEFAULT_BUFSIZE
;
269 ctx
->zin
.zalloc
= Z_NULL
;
270 ctx
->zin
.zfree
= Z_NULL
;
271 ctx
->zin
.next_in
= NULL
;
272 ctx
->zin
.avail_in
= 0;
273 ctx
->zin
.next_out
= NULL
;
274 ctx
->zin
.avail_out
= 0;
275 ctx
->zout
.zalloc
= Z_NULL
;
276 ctx
->zout
.zfree
= Z_NULL
;
277 ctx
->zout
.next_in
= NULL
;
278 ctx
->zout
.avail_in
= 0;
279 ctx
->zout
.next_out
= NULL
;
280 ctx
->zout
.avail_out
= 0;
282 ctx
->comp_level
= Z_DEFAULT_COMPRESSION
;
284 bi
->ptr
= (char *)ctx
;
290 bio_zlib_free(BIO
*bi
)
296 ctx
= (BIO_ZLIB_CTX
*)bi
->ptr
;
298 /* Destroy decompress context */
299 inflateEnd(&ctx
->zin
);
303 /* Destroy compress context */
304 deflateEnd(&ctx
->zout
);
315 bio_zlib_read(BIO
*b
, char *out
, int outl
)
323 ctx
= (BIO_ZLIB_CTX
*)b
->ptr
;
325 BIO_clear_retry_flags(b
);
327 ctx
->ibuf
= malloc(ctx
->ibufsize
);
329 COMPerror(ERR_R_MALLOC_FAILURE
);
333 zin
->next_in
= ctx
->ibuf
;
337 /* Copy output data directly to supplied buffer */
338 zin
->next_out
= (unsigned char *)out
;
339 zin
->avail_out
= (unsigned int)outl
;
341 /* Decompress while data available */
342 while (zin
->avail_in
) {
343 ret
= inflate(zin
, 0);
344 if ((ret
!= Z_OK
) && (ret
!= Z_STREAM_END
)) {
345 COMPerror(COMP_R_ZLIB_INFLATE_ERROR
);
346 ERR_asprintf_error_data("zlib error:%s",
350 /* If EOF or we've read everything then return */
351 if ((ret
== Z_STREAM_END
) || !zin
->avail_out
)
352 return outl
- zin
->avail_out
;
355 /* No data in input buffer try to read some in,
356 * if an error then return the total data read.
358 ret
= BIO_read(b
->next_bio
, ctx
->ibuf
, ctx
->ibufsize
);
360 /* Total data read */
361 int tot
= outl
- zin
->avail_out
;
362 BIO_copy_next_retry(b
);
364 return (tot
> 0) ? tot
: ret
;
368 zin
->next_in
= ctx
->ibuf
;
373 bio_zlib_write(BIO
*b
, const char *in
, int inl
)
381 ctx
= (BIO_ZLIB_CTX
*)b
->ptr
;
385 BIO_clear_retry_flags(b
);
387 ctx
->obuf
= malloc(ctx
->obufsize
);
388 /* Need error here */
390 COMPerror(ERR_R_MALLOC_FAILURE
);
393 ctx
->optr
= ctx
->obuf
;
395 deflateInit(zout
, ctx
->comp_level
);
396 zout
->next_out
= ctx
->obuf
;
397 zout
->avail_out
= ctx
->obufsize
;
399 /* Obtain input data directly from supplied buffer */
400 zout
->next_in
= (void *)in
;
401 zout
->avail_in
= inl
;
403 /* If data in output buffer write it first */
404 while (ctx
->ocount
) {
405 ret
= BIO_write(b
->next_bio
, ctx
->optr
, ctx
->ocount
);
407 /* Total data written */
408 int tot
= inl
- zout
->avail_in
;
409 BIO_copy_next_retry(b
);
411 return (tot
> 0) ? tot
: ret
;
418 /* Have we consumed all supplied data? */
422 /* Compress some more */
425 ctx
->optr
= ctx
->obuf
;
426 zout
->next_out
= ctx
->obuf
;
427 zout
->avail_out
= ctx
->obufsize
;
428 /* Compress some more */
429 ret
= deflate(zout
, 0);
431 COMPerror(COMP_R_ZLIB_DEFLATE_ERROR
);
432 ERR_asprintf_error_data("zlib error:%s", zError(ret
));
435 ctx
->ocount
= ctx
->obufsize
- zout
->avail_out
;
440 bio_zlib_flush(BIO
*b
)
446 ctx
= (BIO_ZLIB_CTX
*)b
->ptr
;
447 /* If no data written or already flush show success */
448 if (!ctx
->obuf
|| (ctx
->odone
&& !ctx
->ocount
))
451 BIO_clear_retry_flags(b
);
452 /* No more input data */
453 zout
->next_in
= NULL
;
456 /* If data in output buffer write it first */
457 while (ctx
->ocount
) {
458 ret
= BIO_write(b
->next_bio
, ctx
->optr
, ctx
->ocount
);
460 BIO_copy_next_retry(b
);
469 /* Compress some more */
472 ctx
->optr
= ctx
->obuf
;
473 zout
->next_out
= ctx
->obuf
;
474 zout
->avail_out
= ctx
->obufsize
;
475 /* Compress some more */
476 ret
= deflate(zout
, Z_FINISH
);
477 if (ret
== Z_STREAM_END
)
479 else if (ret
!= Z_OK
) {
480 COMPerror(COMP_R_ZLIB_DEFLATE_ERROR
);
481 ERR_asprintf_error_data("zlib error:%s", zError(ret
));
484 ctx
->ocount
= ctx
->obufsize
- zout
->avail_out
;
489 bio_zlib_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
)
496 ctx
= (BIO_ZLIB_CTX
*)b
->ptr
;
506 ret
= bio_zlib_flush(b
);
508 ret
= BIO_flush(b
->next_bio
);
511 case BIO_C_SET_BUFF_SIZE
:
539 case BIO_C_DO_STATE_MACHINE
:
540 BIO_clear_retry_flags(b
);
541 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
542 BIO_copy_next_retry(b
);
546 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
556 bio_zlib_callback_ctrl(BIO
*b
, int cmd
, bio_info_cb
*fp
)
560 return BIO_callback_ctrl(b
->next_bio
, cmd
, fp
);