Backport of zlib compression BIO from HEAD. Update mkdef.pl script to handle
authorDr. Stephen Henson <steve@openssl.org>
Wed, 2 Apr 2008 11:37:25 +0000 (11:37 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 2 Apr 2008 11:37:25 +0000 (11:37 +0000)
ZLIB. Update ordinals.

CHANGES
crypto/bio/bio.h
crypto/comp/c_zlib.c
crypto/comp/comp.h
crypto/comp/comp_err.c
util/libeay.num
util/mkdef.pl

diff --git a/CHANGES b/CHANGES
index f57d81c26bcb3e940d79cb9b70e3e0502c8bb650..5fbcbed58b037333e2fa35c9d7aad9e2f5191c10 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 0.9.8g and 0.9.8h  [xx XXX xxxx]
 
+  *) Zlib compression BIO. This is a filter BIO which compressed and
+     uncompresses any data passed through it. Add options to enc utility
+     to support it.
+     [Steve Henson]
+
   *) Add AES_wrap_key() and AES_unwrap_key() functions to implement
      RFC3394 compatible AES key wrapping.
      [Steve Henson]
index 0362bb90caf4b14a774cb4546adcbefc0668d26f..cecb6a720771f56d94230f0e683027527d67ead8 100644 (file)
@@ -95,6 +95,7 @@ extern "C" {
 #define BIO_TYPE_BIO           (19|0x0400)             /* (half a) BIO pair */
 #define BIO_TYPE_LINEBUFFER    (20|0x0200)             /* filter */
 #define BIO_TYPE_DGRAM         (21|0x0400|0x0100)
+#define BIO_TYPE_COMP          (23|0x0200)             /* filter */
 
 #define BIO_TYPE_DESCRIPTOR    0x0100  /* socket, fd, connect or accept */
 #define BIO_TYPE_FILTER                0x0200
index 43402e75dbf52f3c8e2a50621911f3a0127107fd..0f34597e70427cf45dd1fe4a6c7c3195e77fea4f 100644 (file)
@@ -105,6 +105,7 @@ typedef int (*deflateEnd_ft)(z_streamp strm);
 typedef int (*deflate_ft)(z_streamp strm, int flush);
 typedef int (*deflateInit__ft)(z_streamp strm, int level,
        const char * version, int stream_size);
+typedef const char * (*zError__ft)(int err);
 static compress_ft     p_compress=NULL;
 static inflateEnd_ft   p_inflateEnd=NULL;
 static inflate_ft      p_inflate=NULL;
@@ -112,6 +113,7 @@ static inflateInit__ft      p_inflateInit_=NULL;
 static deflateEnd_ft   p_deflateEnd=NULL;
 static deflate_ft      p_deflate=NULL;
 static deflateInit__ft p_deflateInit_=NULL;
+static zError__ft      p_zError=NULL;
 
 static int zlib_loaded = 0;     /* only attempt to init func pts once */
 static DSO *zlib_dso = NULL;
@@ -123,6 +125,7 @@ static DSO *zlib_dso = NULL;
 #define deflateEnd              p_deflateEnd
 #define deflate                 p_deflate
 #define deflateInit_            p_deflateInit_
+#define zError                 p_zError
 #endif /* ZLIB_SHARED */
 
 struct zlib_state
@@ -373,10 +376,13 @@ COMP_METHOD *COMP_zlib(void)
                        p_deflateInit_
                                = (deflateInit__ft) DSO_bind_func(zlib_dso,
                                        "deflateInit_");
+                       p_zError
+                               = (zError__ft) DSO_bind_func(zlib_dso,
+                                       "zError");
 
                        if (p_compress && p_inflateEnd && p_inflate
                                && p_inflateInit_ && p_deflateEnd
-                               && p_deflate && p_deflateInit_)
+                               && p_deflate && p_deflateInit_ && p_zError)
                                zlib_loaded++;
                        }
                }
@@ -410,3 +416,386 @@ err:
        return(meth);
        }
 
+void COMP_zlib_cleanup(void)
+       {
+#ifdef ZLIB_SHARED
+       if (zlib_dso)
+               DSO_free(zlib_dso);
+#endif
+       }
+
+#ifdef ZLIB
+
+/* Zlib based compression/decompression filter BIO */
+
+typedef struct
+       {
+       unsigned char *ibuf;    /* Input buffer */
+       int ibufsize;           /* Buffer size */
+       z_stream zin;           /* Input decompress context */
+       unsigned char *obuf;    /* Output buffer */
+       int obufsize;           /* Output buffer size */
+       unsigned char *optr;    /* Position in output buffer */
+       int ocount;             /* Amount of data in output buffer */
+       int odone;              /* deflate EOF */
+       int comp_level;         /* Compression level to use */
+       z_stream zout;          /* Output compression context */
+       } BIO_ZLIB_CTX;
+
+#define ZLIB_DEFAULT_BUFSIZE 1024
+
+static int bio_zlib_new(BIO *bi);
+static int bio_zlib_free(BIO *bi);
+static int bio_zlib_read(BIO *b, char *out, int outl);
+static int bio_zlib_write(BIO *b, const char *in, int inl);
+static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr);
+static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp);
+
+static BIO_METHOD bio_meth_zlib = 
+       {
+       BIO_TYPE_COMP,
+       "zlib",
+       bio_zlib_write,
+       bio_zlib_read,
+       NULL,
+       NULL,
+       bio_zlib_ctrl,
+       bio_zlib_new,
+       bio_zlib_free,
+       bio_zlib_callback_ctrl
+       };
+
+BIO_METHOD *BIO_f_zlib(void)
+       {
+       return &bio_meth_zlib;
+       }
+
+
+static int bio_zlib_new(BIO *bi)
+       {
+       BIO_ZLIB_CTX *ctx;
+#ifdef ZLIB_SHARED
+       (void)COMP_zlib();
+       if (!zlib_loaded)
+               {
+               COMPerr(COMP_F_BIO_ZLIB_NEW, COMP_R_ZLIB_NOT_SUPPORTED);
+               return 0;
+               }
+#endif
+       ctx = OPENSSL_malloc(sizeof(BIO_ZLIB_CTX));
+       if(!ctx)
+               {
+               COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE);
+               return 0;
+               }
+       ctx->ibuf = NULL;
+       ctx->obuf = NULL;
+       ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE;
+       ctx->obufsize = ZLIB_DEFAULT_BUFSIZE;
+       ctx->zin.zalloc = Z_NULL;
+       ctx->zin.zfree = Z_NULL;
+       ctx->zin.next_in = NULL;
+       ctx->zin.avail_in = 0;
+       ctx->zin.next_out = NULL;
+       ctx->zin.avail_out = 0;
+       ctx->zout.zalloc = Z_NULL;
+       ctx->zout.zfree = Z_NULL;
+       ctx->zout.next_in = NULL;
+       ctx->zout.avail_in = 0;
+       ctx->zout.next_out = NULL;
+       ctx->zout.avail_out = 0;
+       ctx->odone = 0;
+       ctx->comp_level = Z_DEFAULT_COMPRESSION;
+       bi->init = 1;
+       bi->ptr = (char *)ctx;
+       bi->flags = 0;
+       return 1;
+       }
+
+static int bio_zlib_free(BIO *bi)
+       {
+       BIO_ZLIB_CTX *ctx;
+       if(!bi) return 0;
+       ctx = (BIO_ZLIB_CTX *)bi->ptr;
+       if(ctx->ibuf)
+               {
+               /* Destroy decompress context */
+               inflateEnd(&ctx->zin);
+               OPENSSL_free(ctx->ibuf);
+               }
+       if(ctx->obuf)
+               {
+               /* Destroy compress context */
+               deflateEnd(&ctx->zout);
+               OPENSSL_free(ctx->obuf);
+               }
+       OPENSSL_free(ctx);
+       bi->ptr = NULL;
+       bi->init = 0;
+       bi->flags = 0;
+       return 1;
+       }
+
+static int bio_zlib_read(BIO *b, char *out, int outl)
+       {
+       BIO_ZLIB_CTX *ctx;
+       int ret;
+       z_stream *zin;
+       if(!out || !outl) return 0;
+       ctx = (BIO_ZLIB_CTX *)b->ptr;
+       zin = &ctx->zin;
+       BIO_clear_retry_flags(b);
+       if(!ctx->ibuf)
+               {
+               ctx->ibuf = OPENSSL_malloc(ctx->ibufsize);
+               if(!ctx->ibuf)
+                       {
+                       COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE);
+                       return 0;
+                       }
+               inflateInit(zin);
+               zin->next_in = ctx->ibuf;
+               zin->avail_in = 0;
+               }
+
+       /* Copy output data directly to supplied buffer */
+       zin->next_out = (unsigned char *)out;
+       zin->avail_out = (unsigned int)outl;
+       for(;;)
+               {
+               /* Decompress while data available */
+               while(zin->avail_in)
+                       {
+                       ret = inflate(zin, 0);
+                       if((ret != Z_OK) && (ret != Z_STREAM_END))
+                               {
+                               COMPerr(COMP_F_BIO_ZLIB_READ,
+                                               COMP_R_ZLIB_INFLATE_ERROR);
+                               ERR_add_error_data(2, "zlib error:",
+                                                       zError(ret));
+                               return 0;
+                               }
+                       /* If EOF or we've read everything then return */
+                       if((ret == Z_STREAM_END) || !zin->avail_out)
+                               return outl - zin->avail_out;
+                       }
+
+               /* No data in input buffer try to read some in,
+                * if an error then return the total data read.
+                */
+               ret = BIO_read(b->next_bio, ctx->ibuf, ctx->ibufsize);
+               if(ret <= 0)
+                       {
+                       /* Total data read */
+                       int tot = outl - zin->avail_out;
+                       BIO_copy_next_retry(b);
+                       if(ret < 0) return (tot > 0) ? tot : ret;
+                       return tot;
+                       }
+               zin->avail_in = ret;
+               zin->next_in = ctx->ibuf;
+               }
+       }
+
+static int bio_zlib_write(BIO *b, const char *in, int inl)
+       {
+       BIO_ZLIB_CTX *ctx;
+       int ret;
+       z_stream *zout;
+       if(!in || !inl) return 0;
+       ctx = (BIO_ZLIB_CTX *)b->ptr;
+       if(ctx->odone) return 0;
+       zout = &ctx->zout;
+       BIO_clear_retry_flags(b);
+       if(!ctx->obuf)
+               {
+               ctx->obuf = OPENSSL_malloc(ctx->obufsize);
+               /* Need error here */
+               if(!ctx->obuf)
+                       {
+                       COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE);
+                       return 0;
+                       }
+               ctx->optr = ctx->obuf;
+               ctx->ocount = 0;
+               deflateInit(zout, ctx->comp_level);
+               zout->next_out = ctx->obuf;
+               zout->avail_out = ctx->obufsize;
+               }
+       /* Obtain input data directly from supplied buffer */
+       zout->next_in = (void *)in;
+       zout->avail_in = inl;
+       for(;;)
+               {
+               /* If data in output buffer write it first */
+               while(ctx->ocount) {
+                       ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
+                       if(ret <= 0)
+                               {
+                               /* Total data written */
+                               int tot = inl - zout->avail_in;
+                               BIO_copy_next_retry(b);
+                               if(ret < 0) return (tot > 0) ? tot : ret;
+                               return tot;
+                               }
+                       ctx->optr += ret;
+                       ctx->ocount -= ret;
+               }
+
+               /* Have we consumed all supplied data? */
+               if(!zout->avail_in)
+                       return inl;
+
+               /* Compress some more */
+
+               /* Reset buffer */
+               ctx->optr = ctx->obuf;
+               zout->next_out = ctx->obuf;
+               zout->avail_out = ctx->obufsize;
+               /* Compress some more */
+               ret = deflate(zout, 0);
+               if(ret != Z_OK)
+                       {
+                       COMPerr(COMP_F_BIO_ZLIB_WRITE,
+                                               COMP_R_ZLIB_DEFLATE_ERROR);
+                       ERR_add_error_data(2, "zlib error:", zError(ret));
+                       return 0;
+                       }
+               ctx->ocount = ctx->obufsize - zout->avail_out;
+               }
+       }
+
+static int bio_zlib_flush(BIO *b)
+       {
+       BIO_ZLIB_CTX *ctx;
+       int ret;
+       z_stream *zout;
+       ctx = (BIO_ZLIB_CTX *)b->ptr;
+       /* If no data written or already flush show success */
+       if(!ctx->obuf || (ctx->odone && !ctx->ocount)) return 1;
+       zout = &ctx->zout;
+       BIO_clear_retry_flags(b);
+       /* No more input data */
+       zout->next_in = NULL;
+       zout->avail_in = 0;
+       for(;;)
+               {
+               /* If data in output buffer write it first */
+               while(ctx->ocount)
+                       {
+                       ret = BIO_write(b->next_bio, ctx->optr, ctx->ocount);
+                       if(ret <= 0)
+                               {
+                               BIO_copy_next_retry(b);
+                               return ret;
+                               }
+                       ctx->optr += ret;
+                       ctx->ocount -= ret;
+                       }
+               if(ctx->odone) return 1;
+
+               /* Compress some more */
+
+               /* Reset buffer */
+               ctx->optr = ctx->obuf;
+               zout->next_out = ctx->obuf;
+               zout->avail_out = ctx->obufsize;
+               /* Compress some more */
+               ret = deflate(zout, Z_FINISH);
+               if(ret == Z_STREAM_END) ctx->odone = 1;
+               else if(ret != Z_OK)
+                       {
+                       COMPerr(COMP_F_BIO_ZLIB_FLUSH,
+                                               COMP_R_ZLIB_DEFLATE_ERROR);
+                       ERR_add_error_data(2, "zlib error:", zError(ret));
+                       return 0;
+                       }
+               ctx->ocount = ctx->obufsize - zout->avail_out;
+               }
+       }
+
+static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
+       {
+       BIO_ZLIB_CTX *ctx;
+       int ret, *ip;
+       int ibs, obs;
+       if(!b->next_bio) return 0;
+       ctx = (BIO_ZLIB_CTX *)b->ptr;
+       switch (cmd)
+               {
+
+       case BIO_CTRL_RESET:
+               ctx->ocount = 0;
+               ctx->odone = 0;
+               break;
+
+       case BIO_CTRL_FLUSH:
+               ret = bio_zlib_flush(b);
+               if (ret > 0)
+                       ret = BIO_flush(b->next_bio);
+               break;
+
+       case BIO_C_SET_BUFF_SIZE:
+               ibs = -1;
+               obs = -1;
+               if (ptr != NULL)
+                       {
+                       ip = ptr;
+                       if (*ip == 0)
+                               ibs = (int) num;
+                       else 
+                               obs = (int) num;
+                       }
+               else
+                       {
+                       ibs = (int)num;
+                       obs = ibs;
+                       }
+
+               if (ibs != -1)
+                       {
+                       if (ctx->ibuf)
+                               {
+                               OPENSSL_free(ctx->ibuf);
+                               ctx->ibuf = NULL;
+                               }
+                       ctx->ibufsize = ibs;
+                       }
+
+               if (obs != -1)
+                       {
+                       if (ctx->obuf)
+                               {
+                               OPENSSL_free(ctx->obuf);
+                               ctx->obuf = NULL;
+                               }
+                       ctx->obufsize = obs;
+                       }
+
+               break;
+
+       case BIO_C_DO_STATE_MACHINE:
+               BIO_clear_retry_flags(b);
+               ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+               BIO_copy_next_retry(b);
+               break;
+
+       default:
+               ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+               break;
+
+               }
+
+       return ret;
+       }
+
+
+static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
+       {
+       if(!b->next_bio)
+               return 0;
+       return
+               BIO_callback_ctrl(b->next_bio, cmd, fp);
+       }
+
+#endif
index 5d59354a5715f9db49dcf258a59c39bd011b4456..4b405c7d49ef1a038a3f652164c9c04d5efb9251 100644 (file)
@@ -47,6 +47,13 @@ int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen,
        unsigned char *in, int ilen);
 COMP_METHOD *COMP_rle(void );
 COMP_METHOD *COMP_zlib(void );
+void COMP_zlib_cleanup(void);
+
+#ifdef HEADER_BIO_H
+#ifdef ZLIB
+BIO_METHOD *BIO_f_zlib(void);
+#endif
+#endif
 
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
@@ -57,8 +64,15 @@ void ERR_load_COMP_strings(void);
 /* Error codes for the COMP functions. */
 
 /* Function codes. */
+#define COMP_F_BIO_ZLIB_FLUSH                           99
+#define COMP_F_BIO_ZLIB_NEW                             100
+#define COMP_F_BIO_ZLIB_READ                            101
+#define COMP_F_BIO_ZLIB_WRITE                           102
 
 /* Reason codes. */
+#define COMP_R_ZLIB_DEFLATE_ERROR                       99
+#define COMP_R_ZLIB_INFLATE_ERROR                       100
+#define COMP_R_ZLIB_NOT_SUPPORTED                       101
 
 #ifdef  __cplusplus
 }
index 07372226c9d08eae5b1d244abbaef7092763a851..187d68b725ca0dda60c69e2b2ed74b870fe2788c 100644 (file)
@@ -1,6 +1,6 @@
 /* crypto/comp/comp_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 static ERR_STRING_DATA COMP_str_functs[]=
        {
+{ERR_FUNC(COMP_F_BIO_ZLIB_FLUSH),      "BIO_ZLIB_FLUSH"},
+{ERR_FUNC(COMP_F_BIO_ZLIB_NEW),        "BIO_ZLIB_NEW"},
+{ERR_FUNC(COMP_F_BIO_ZLIB_READ),       "BIO_ZLIB_READ"},
+{ERR_FUNC(COMP_F_BIO_ZLIB_WRITE),      "BIO_ZLIB_WRITE"},
 {0,NULL}
        };
 
 static ERR_STRING_DATA COMP_str_reasons[]=
        {
+{ERR_REASON(COMP_R_ZLIB_DEFLATE_ERROR)   ,"zlib deflate error"},
+{ERR_REASON(COMP_R_ZLIB_INFLATE_ERROR)   ,"zlib inflate error"},
+{ERR_REASON(COMP_R_ZLIB_NOT_SUPPORTED)   ,"zlib not supported"},
 {0,NULL}
        };
 
index 5f3d6b589c3071deeb8cc7a2dea57a17a06827ec..b261e7b0ec8f9ef49d1d7486ed9e05f850a9197c 100755 (executable)
@@ -3529,3 +3529,16 @@ i2d_X509_EXTENSIONS                     3922     EXIST::FUNCTION:
 OCSP_sendreq_nbio                       3923   EXIST::FUNCTION:
 OCSP_sendreq_new                        3924   EXIST::FUNCTION:
 d2i_X509_EXTENSIONS                     3925   EXIST::FUNCTION:
+X509_ALGORS_it                          3926   EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
+X509_ALGORS_it                          3926   EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
+X509_ALGOR_get0                         3927   EXIST::FUNCTION:
+X509_ALGOR_set0                         3928   EXIST::FUNCTION:
+AES_unwrap_key                          3929   EXIST::FUNCTION:AES
+AES_wrap_key                            3930   EXIST::FUNCTION:AES
+X509at_get0_data_by_OBJ                 3931   EXIST::FUNCTION:
+ASN1_TYPE_set1                          3932   EXIST::FUNCTION:
+ASN1_STRING_set0                        3933   EXIST::FUNCTION:
+i2d_X509_ALGORS                         3934   EXIST::FUNCTION:
+BIO_f_zlib                              3935   EXIST:ZLIB:FUNCTION:
+COMP_zlib_cleanup                       3936   EXIST::FUNCTION:
+d2i_X509_ALGORS                         3937   EXIST::FUNCTION:
index b9ef68b06366199fcbdfdbac9a723b7d82fa1174..cb69983d7469837c0f7010d8cc1d923345451616 100755 (executable)
@@ -79,7 +79,7 @@ my $OS2=0;
 my $safe_stack_def = 0;
 
 my @known_platforms = ( "__FreeBSD__", "PERL5", "NeXT",
-                       "EXPORT_VAR_AS_FUNCTION" );
+                       "EXPORT_VAR_AS_FUNCTION", "ZLIB" );
 my @known_ossl_platforms = ( "VMS", "WIN16", "WIN32", "WINNT", "OS2" );
 my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
                         "CAST", "MD2", "MD4", "MD5", "SHA", "SHA0", "SHA1",
@@ -140,6 +140,11 @@ foreach (@ARGV, split(/ /, $options))
        }
        $VMS=1 if $_ eq "VMS";
        $OS2=1 if $_ eq "OS2";
+       if ($_ eq "zlib" || $_ eq "zlib-dynamic"
+                        || $_ eq "enable-zlib-dynamic") {
+               $zlib = 1;
+       }
+
 
        $do_ssl=1 if $_ eq "ssleay";
        if ($_ eq "ssl") {
@@ -1078,6 +1083,7 @@ sub is_valid
                        if ($keyword eq "EXPORT_VAR_AS_FUNCTION" && ($VMSVAX || $W32 || $W16)) {
                                return 1;
                        }
+                       if ($keyword eq "ZLIB" && $zlib) { return 1; }
                        return 0;
                } else {
                        # algorithms