c_zlib.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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. COMP_METHOD *COMP_zlib(void );
  8. static COMP_METHOD zlib_method_nozlib={
  9. NID_undef,
  10. "(undef)",
  11. NULL,
  12. NULL,
  13. NULL,
  14. NULL,
  15. NULL,
  16. NULL,
  17. };
  18. #ifndef ZLIB
  19. #undef ZLIB_SHARED
  20. #else
  21. #include <zlib.h>
  22. static int zlib_stateful_init(COMP_CTX *ctx);
  23. static void zlib_stateful_finish(COMP_CTX *ctx);
  24. static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
  25. unsigned int olen, unsigned char *in, unsigned int ilen);
  26. static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out,
  27. unsigned int olen, unsigned char *in, unsigned int ilen);
  28. #if 0
  29. static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
  30. unsigned int olen, unsigned char *in, unsigned int ilen);
  31. static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
  32. unsigned int olen, unsigned char *in, unsigned int ilen);
  33. static int zz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
  34. uLong sourceLen);
  35. static COMP_METHOD zlib_stateless_method={
  36. NID_zlib_compression,
  37. LN_zlib_compression,
  38. NULL,
  39. NULL,
  40. zlib_compress_block,
  41. zlib_expand_block,
  42. NULL,
  43. NULL,
  44. };
  45. #endif
  46. static COMP_METHOD zlib_stateful_method={
  47. NID_zlib_compression,
  48. LN_zlib_compression,
  49. zlib_stateful_init,
  50. zlib_stateful_finish,
  51. zlib_stateful_compress_block,
  52. zlib_stateful_expand_block,
  53. NULL,
  54. NULL,
  55. };
  56. /*
  57. * When OpenSSL is built on Windows, we do not want to require that
  58. * the ZLIB.DLL be available in order for the OpenSSL DLLs to
  59. * work. Therefore, all ZLIB routines are loaded at run time
  60. * and we do not link to a .LIB file when ZLIB_SHARED is set.
  61. */
  62. #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
  63. # include <windows.h>
  64. #endif /* !(OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32) */
  65. #ifdef ZLIB_SHARED
  66. #include <openssl/dso.h>
  67. /* Function pointers */
  68. typedef int (*compress_ft)(Bytef *dest,uLongf *destLen,
  69. const Bytef *source, uLong sourceLen);
  70. typedef int (*inflateEnd_ft)(z_streamp strm);
  71. typedef int (*inflate_ft)(z_streamp strm, int flush);
  72. typedef int (*inflateInit__ft)(z_streamp strm,
  73. const char * version, int stream_size);
  74. typedef int (*deflateEnd_ft)(z_streamp strm);
  75. typedef int (*deflate_ft)(z_streamp strm, int flush);
  76. typedef int (*deflateInit__ft)(z_streamp strm, int level,
  77. const char * version, int stream_size);
  78. static compress_ft p_compress=NULL;
  79. static inflateEnd_ft p_inflateEnd=NULL;
  80. static inflate_ft p_inflate=NULL;
  81. static inflateInit__ft p_inflateInit_=NULL;
  82. static deflateEnd_ft p_deflateEnd=NULL;
  83. static deflate_ft p_deflate=NULL;
  84. static deflateInit__ft p_deflateInit_=NULL;
  85. static int zlib_loaded = 0; /* only attempt to init func pts once */
  86. static DSO *zlib_dso = NULL;
  87. #define compress p_compress
  88. #define inflateEnd p_inflateEnd
  89. #define inflate p_inflate
  90. #define inflateInit_ p_inflateInit_
  91. #define deflateEnd p_deflateEnd
  92. #define deflate p_deflate
  93. #define deflateInit_ p_deflateInit_
  94. #endif /* ZLIB_SHARED */
  95. struct zlib_state
  96. {
  97. z_stream istream;
  98. z_stream ostream;
  99. };
  100. static int zlib_stateful_ex_idx = -1;
  101. static void zlib_stateful_free_ex_data(void *obj, void *item,
  102. CRYPTO_EX_DATA *ad, int ind,long argl, void *argp)
  103. {
  104. struct zlib_state *state = (struct zlib_state *)item;
  105. inflateEnd(&state->istream);
  106. deflateEnd(&state->ostream);
  107. OPENSSL_free(state);
  108. }
  109. static int zlib_stateful_init(COMP_CTX *ctx)
  110. {
  111. int err;
  112. struct zlib_state *state =
  113. (struct zlib_state *)OPENSSL_malloc(sizeof(struct zlib_state));
  114. if (state == NULL)
  115. goto err;
  116. state->istream.zalloc = Z_NULL;
  117. state->istream.zfree = Z_NULL;
  118. state->istream.opaque = Z_NULL;
  119. state->istream.next_in = Z_NULL;
  120. state->istream.next_out = Z_NULL;
  121. state->istream.avail_in = 0;
  122. state->istream.avail_out = 0;
  123. err = inflateInit_(&state->istream,
  124. ZLIB_VERSION, sizeof(z_stream));
  125. if (err != Z_OK)
  126. goto err;
  127. state->ostream.zalloc = Z_NULL;
  128. state->ostream.zfree = Z_NULL;
  129. state->ostream.opaque = Z_NULL;
  130. state->ostream.next_in = Z_NULL;
  131. state->ostream.next_out = Z_NULL;
  132. state->ostream.avail_in = 0;
  133. state->ostream.avail_out = 0;
  134. err = deflateInit_(&state->ostream,Z_DEFAULT_COMPRESSION,
  135. ZLIB_VERSION, sizeof(z_stream));
  136. if (err != Z_OK)
  137. goto err;
  138. CRYPTO_new_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
  139. if (zlib_stateful_ex_idx == -1)
  140. {
  141. CRYPTO_w_lock(CRYPTO_LOCK_COMP);
  142. if (zlib_stateful_ex_idx == -1)
  143. zlib_stateful_ex_idx =
  144. CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_COMP,
  145. 0,NULL,NULL,NULL,zlib_stateful_free_ex_data);
  146. CRYPTO_w_unlock(CRYPTO_LOCK_COMP);
  147. if (zlib_stateful_ex_idx == -1)
  148. goto err;
  149. }
  150. CRYPTO_set_ex_data(&ctx->ex_data,zlib_stateful_ex_idx,state);
  151. return 1;
  152. err:
  153. if (state) OPENSSL_free(state);
  154. return 0;
  155. }
  156. static void zlib_stateful_finish(COMP_CTX *ctx)
  157. {
  158. CRYPTO_free_ex_data(CRYPTO_EX_INDEX_COMP,ctx,&ctx->ex_data);
  159. }
  160. static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out,
  161. unsigned int olen, unsigned char *in, unsigned int ilen)
  162. {
  163. int err = Z_OK;
  164. struct zlib_state *state =
  165. (struct zlib_state *)CRYPTO_get_ex_data(&ctx->ex_data,
  166. zlib_stateful_ex_idx);
  167. if (state == NULL)
  168. return -1;
  169. state->ostream.next_in = in;
  170. state->ostream.avail_in = ilen;
  171. state->ostream.next_out = out;
  172. state->ostream.avail_out = olen;
  173. if (ilen > 0)
  174. err = deflate(&state->ostream, Z_SYNC_FLUSH);
  175. if (err != Z_OK)
  176. return -1;
  177. #ifdef DEBUG_ZLIB
  178. fprintf(stderr,"compress(%4d)->%4d %s\n",
  179. ilen,olen - state->ostream.avail_out,
  180. (ilen != olen - state->ostream.avail_out)?"zlib":"clear");
  181. #endif
  182. return olen - state->ostream.avail_out;
  183. }
  184. static int zlib_stateful_expand_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. if (state == NULL)
  192. return 0;
  193. state->istream.next_in = in;
  194. state->istream.avail_in = ilen;
  195. state->istream.next_out = out;
  196. state->istream.avail_out = olen;
  197. if (ilen > 0)
  198. err = inflate(&state->istream, Z_SYNC_FLUSH);
  199. if (err != Z_OK)
  200. return -1;
  201. #ifdef DEBUG_ZLIB
  202. fprintf(stderr,"expand(%4d)->%4d %s\n",
  203. ilen,olen - state->istream.avail_out,
  204. (ilen != olen - state->istream.avail_out)?"zlib":"clear");
  205. #endif
  206. return olen - state->istream.avail_out;
  207. }
  208. #if 0
  209. static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
  210. unsigned int olen, unsigned char *in, unsigned int ilen)
  211. {
  212. unsigned long l;
  213. int i;
  214. int clear=1;
  215. if (ilen > 128)
  216. {
  217. out[0]=1;
  218. l=olen-1;
  219. i=compress(&(out[1]),&l,in,(unsigned long)ilen);
  220. if (i != Z_OK)
  221. return(-1);
  222. if (ilen > l)
  223. {
  224. clear=0;
  225. l++;
  226. }
  227. }
  228. if (clear)
  229. {
  230. out[0]=0;
  231. memcpy(&(out[1]),in,ilen);
  232. l=ilen+1;
  233. }
  234. #ifdef DEBUG_ZLIB
  235. fprintf(stderr,"compress(%4d)->%4d %s\n",
  236. ilen,(int)l,(clear)?"clear":"zlib");
  237. #endif
  238. return((int)l);
  239. }
  240. static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
  241. unsigned int olen, unsigned char *in, unsigned int ilen)
  242. {
  243. unsigned long l;
  244. int i;
  245. if (in[0])
  246. {
  247. l=olen;
  248. i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1);
  249. if (i != Z_OK)
  250. return(-1);
  251. }
  252. else
  253. {
  254. memcpy(out,&(in[1]),ilen-1);
  255. l=ilen-1;
  256. }
  257. #ifdef DEBUG_ZLIB
  258. fprintf(stderr,"expand (%4d)->%4d %s\n",
  259. ilen,(int)l,in[0]?"zlib":"clear");
  260. #endif
  261. return((int)l);
  262. }
  263. static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source,
  264. uLong sourceLen)
  265. {
  266. z_stream stream;
  267. int err;
  268. stream.next_in = (Bytef*)source;
  269. stream.avail_in = (uInt)sourceLen;
  270. /* Check for source > 64K on 16-bit machine: */
  271. if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
  272. stream.next_out = dest;
  273. stream.avail_out = (uInt)*destLen;
  274. if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
  275. stream.zalloc = (alloc_func)0;
  276. stream.zfree = (free_func)0;
  277. err = inflateInit_(&stream,
  278. ZLIB_VERSION, sizeof(z_stream));
  279. if (err != Z_OK) return err;
  280. err = inflate(&stream, Z_FINISH);
  281. if (err != Z_STREAM_END) {
  282. inflateEnd(&stream);
  283. return err;
  284. }
  285. *destLen = stream.total_out;
  286. err = inflateEnd(&stream);
  287. return err;
  288. }
  289. #endif
  290. #endif
  291. COMP_METHOD *COMP_zlib(void)
  292. {
  293. COMP_METHOD *meth = &zlib_method_nozlib;
  294. #ifdef ZLIB_SHARED
  295. if (!zlib_loaded)
  296. {
  297. #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
  298. zlib_dso = DSO_load(NULL, "ZLIB1", NULL, 0);
  299. #else
  300. zlib_dso = DSO_load(NULL, "z", NULL, 0);
  301. #endif
  302. if (zlib_dso != NULL)
  303. {
  304. p_compress
  305. = (compress_ft) DSO_bind_func(zlib_dso,
  306. "compress");
  307. p_inflateEnd
  308. = (inflateEnd_ft) DSO_bind_func(zlib_dso,
  309. "inflateEnd");
  310. p_inflate
  311. = (inflate_ft) DSO_bind_func(zlib_dso,
  312. "inflate");
  313. p_inflateInit_
  314. = (inflateInit__ft) DSO_bind_func(zlib_dso,
  315. "inflateInit_");
  316. p_deflateEnd
  317. = (deflateEnd_ft) DSO_bind_func(zlib_dso,
  318. "deflateEnd");
  319. p_deflate
  320. = (deflate_ft) DSO_bind_func(zlib_dso,
  321. "deflate");
  322. p_deflateInit_
  323. = (deflateInit__ft) DSO_bind_func(zlib_dso,
  324. "deflateInit_");
  325. if (p_compress && p_inflateEnd && p_inflate
  326. && p_inflateInit_ && p_deflateEnd
  327. && p_deflate && p_deflateInit_)
  328. zlib_loaded++;
  329. }
  330. }
  331. #endif
  332. #ifdef ZLIB_SHARED
  333. if (zlib_loaded)
  334. #endif
  335. #if defined(ZLIB) || defined(ZLIB_SHARED)
  336. meth = &zlib_stateful_method;
  337. #endif
  338. return(meth);
  339. }