[xmlsec/xmlsec-openssl-110: 1/9] convert openssl/ciphers.c to OpenSSL 1.1.0; fix minor warnings



commit a8ad0526fa1a65aee41c8501f83870eb96e97f86
Author: Aleksey Sanin <aleksey aleksey com>
Date:   Wed Jan 27 22:39:57 2016 -0800

    convert openssl/ciphers.c to OpenSSL 1.1.0; fix minor warnings

 apps/xmlsec.c            |    2 +-
 configure.in             |   32 ++++-
 include/xmlsec/errors.h  |    4 +-
 src/openssl/app.c        |    6 +
 src/openssl/ciphers.c    |  378 +++++++++++++++++++++++++++-------------------
 src/openssl/signatures.c |   10 +-
 6 files changed, 262 insertions(+), 170 deletions(-)
---
diff --git a/apps/xmlsec.c b/apps/xmlsec.c
index bd4faa7..9d298e9 100644
--- a/apps/xmlsec.c
+++ b/apps/xmlsec.c
@@ -132,7 +132,7 @@ static const char helpCheckTransforms[] =
 #define xmlSecAppCmdLineTopicEncCommon          0x0010
 #define xmlSecAppCmdLineTopicEncEncrypt         0x0020
 #define xmlSecAppCmdLineTopicEncDecrypt         0x0040
-// #define UNUSED         0x0080
+/* #define UNUSED         0x0080 */
 #define xmlSecAppCmdLineTopicKeysMngr           0x1000
 #define xmlSecAppCmdLineTopicX509Certs          0x2000
 #define xmlSecAppCmdLineTopicVersion            0x4000
diff --git a/configure.in b/configure.in
index 7d976d0..df7838c 100644
--- a/configure.in
+++ b/configure.in
@@ -137,7 +137,7 @@ if test "z$shrext" == "z" ; then
 fi
 
 dnl ==========================================================================
-dnl Check for __FUNCTION__ or __FUNCTION__
+dnl Check for __FUNCTION__ or __func__
 dnl ==========================================================================
 AC_MSG_CHECKING(for __FUNCTION__ or __func__)
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
@@ -150,7 +150,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
        [ac_func_exists=no])
 if test "z$ac_function_exists" = "zyes" ; then
        AC_MSG_RESULT(__FUNCTION__)
-       XMLSEC_DEFINES="$XMLSEC_DEFINES -D__XMLSEC_FUNCTION__=__FUNCTION__"
+       XMLSEC_DEFINES="$XMLSEC_DEFINES -D__XMLSEC_FUNCTION__='__extension__ __FUNCTION__'"
 elif test "z$ac_func_exists" = "zyes" ; then 
        AC_MSG_RESULT(__func__)
        XMLSEC_DEFINES="$XMLSEC_DEFINES -D__XMLSEC_FUNCTION__=__func__"
@@ -375,6 +375,12 @@ elif test "z$with_openssl" != "z" ; then
     OPENSSL_FOUND="yes"
 elif test "z$PKGCONFIG_FOUND" = "zyes" ; then
     if test "z$OPENSSL_VERSION" = "z" ; then
+        PKG_CHECK_MODULES(OPENSSL, openssl >= 1.1.0,
+            [OPENSSL_VERSION="1.1.0"],
+            [OPENSSL_VERSION=""])
+    fi
+
+    if test "z$OPENSSL_VERSION" = "z" ; then
         PKG_CHECK_MODULES(OPENSSL, openssl >= 1.0.0,
             [OPENSSL_VERSION="1.0.0"],
             [OPENSSL_VERSION=""])
@@ -393,7 +399,7 @@ elif test "z$PKGCONFIG_FOUND" = "zyes" ; then
     fi
 
     if test "z$OPENSSL_VERSION" != "z" ; then
-       OPENSSL_FOUND="yes"
+        OPENSSL_FOUND="yes"
     fi
 fi
 
@@ -442,6 +448,19 @@ if test "z$OPENSSL_FOUND" = "zyes" -a "z$OPENSSL_VERSION" = "z" ; then
 
     if test "z$OPENSSL_VERSION" = "z" ; then
         AC_EGREP_CPP(yes,[
+            #include <openssl/opensslv.h>
+        #if OPENSSL_VERSION_NUMBER >= 0x10100000L
+        yes
+        #endif
+    ],[
+        OPENSSL_VERSION="1.1.0"
+    ],[
+        OPENSSL_VERSION=""
+    ])
+    fi
+
+    if test "z$OPENSSL_VERSION" = "z" ; then
+        AC_EGREP_CPP(yes,[
            #include <openssl/opensslv.h>
            #if OPENSSL_VERSION_NUMBER >= 0x10000000L
                yes
@@ -494,11 +513,14 @@ fi
 if test "z$OPENSSL_FOUND" = "zyes" ; then
     XMLSEC_NO_OPENSSL="0"
     if test "z$OPENSSL_VERSION" = "z0.9.8" ; then
-       OPENSSL_CFLAGS="$OPENSSL_CFLAGS -DXMLSEC_OPENSSL_098=1 -DXMLSEC_NO_ECDSA=1"
-    fi    
+       OPENSSL_CFLAGS="$OPENSSL_CFLAGS -DXMLSEC_OPENSSL_098=1 -DXMLSEC_NO_ECDSA=1 -DXMLSEC_NO_SHA256=1"
+    fi
     if test "z$OPENSSL_VERSION" = "z1.0.0" ; then
        OPENSSL_CFLAGS="$OPENSSL_CFLAGS -DXMLSEC_OPENSSL_100=1"
     fi    
+    if test "z$OPENSSL_VERSION" = "z1.1.0" ; then
+    OPENSSL_CFLAGS="$OPENSSL_CFLAGS -DXMLSEC_OPENSSL_110=1"
+    fi    
     OPENSSL_CFLAGS="$OPENSSL_CFLAGS -DXMLSEC_CRYPTO_OPENSSL=1"
     XMLSEC_CRYPTO_LIST="$XMLSEC_CRYPTO_LIST openssl"
 else
diff --git a/include/xmlsec/errors.h b/include/xmlsec/errors.h
index 6e23620..469612d 100644
--- a/include/xmlsec/errors.h
+++ b/include/xmlsec/errors.h
@@ -370,7 +370,7 @@ extern "C" {
  * xmlSecErrorsCallback:
  * @file:               the error location file name (__FILE__ macro).
  * @line:               the error location line number (__LINE__ macro).
- * @func:               the error location function name (__FUNCTION__ macro).
+ * @func:               the error location function name (__func__ macro).
  * @errorObject:        the error specific error object
  * @errorSubject:       the error specific error subject.
  * @reason:             the error code.
@@ -407,7 +407,7 @@ XMLSEC_EXPORT const char*       xmlSecErrorsGetMsg              (xmlSecSize pos)
 
 /* __FUNCTION__ is defined for MSC compiler < MS VS .NET 2003 */
 #if defined(_MSC_VER) && (_MSC_VER >= 1300)
-#define __XMLSEC_FUNCTION__  __FUNCTION__
+#define __XMLSEC_FUNCTION__  __func__
 #endif /* _MSC_VER */
 
 /* fallback for __FUNCTION__ */
diff --git a/src/openssl/app.c b/src/openssl/app.c
index bf78627..7c7a262 100644
--- a/src/openssl/app.c
+++ b/src/openssl/app.c
@@ -106,9 +106,15 @@ xmlSecOpenSSLAppShutdown(void) {
     CRYPTO_cleanup_all_ex_data();
 
     /* finally cleanup errors */
+#if defined(XMLSEC_OPENSSL_100) || defined(XMLSEC_OPENSSL_110)
+    ERR_remove_thread_state(NULL);
+#else
     ERR_remove_state(0);
+#endif /* defined(XMLSEC_OPENSSL_100) || defined(XMLSEC_OPENSSL_110) */
+
     ERR_free_strings();
 
+    /* done */
     return(0);
 }
 
diff --git a/src/openssl/ciphers.c b/src/openssl/ciphers.c
index fb27658..32e245a 100644
--- a/src/openssl/ciphers.c
+++ b/src/openssl/ciphers.c
@@ -21,6 +21,11 @@
 #include <xmlsec/openssl/crypto.h>
 #include <xmlsec/openssl/evp.h>
 
+/* new API from OpenSSL 1.1.0 */
+#if !defined(XMLSEC_OPENSSL_110)
+#define EVP_CIPHER_CTX_encrypting(x) ((x)->encrypt)
+#endif /* !defined(XMLSEC_OPENSSL_110) */
+
 
 /**************************************************************************
  *
@@ -32,25 +37,33 @@ typedef struct _xmlSecOpenSSLEvpBlockCipherCtx          xmlSecOpenSSLEvpBlockCip
 struct _xmlSecOpenSSLEvpBlockCipherCtx {
     const EVP_CIPHER*   cipher;
     xmlSecKeyDataId     keyId;
-    EVP_CIPHER_CTX      cipherCtx;
+    EVP_CIPHER_CTX*     cipherCtx;
     int                 keyInitialized;
     int                 ctxInitialized;
     xmlSecByte          key[EVP_MAX_KEY_LENGTH];
     xmlSecByte          iv[EVP_MAX_IV_LENGTH];
-    xmlSecByte          pad[EVP_MAX_BLOCK_LENGTH];
+    xmlSecByte          pad[2*EVP_MAX_BLOCK_LENGTH];
 };
+
 static int      xmlSecOpenSSLEvpBlockCipherCtxInit      (xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
                                                          xmlSecBufferPtr in,
                                                          xmlSecBufferPtr out,
                                                          int encrypt,
                                                          const xmlChar* cipherName,
                                                          xmlSecTransformCtxPtr transformCtx);
+static int      xmlSecOpenSSLEvpBlockCipherCtxUpdateBlock(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+                                                         const xmlSecByte * in,
+                                                         int inSize,
+                                                         xmlSecBufferPtr out,
+                                                         const xmlChar* cipherName,
+                                                         int final);
 static int      xmlSecOpenSSLEvpBlockCipherCtxUpdate    (xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
                                                          xmlSecBufferPtr in,
                                                          xmlSecBufferPtr out,
                                                          const xmlChar* cipherName,
                                                          xmlSecTransformCtxPtr transformCtx);
 static int      xmlSecOpenSSLEvpBlockCipherCtxFinal     (xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+                                                         xmlSecBufferPtr in,
                                                          xmlSecBufferPtr out,
                                                          const xmlChar* cipherName,
                                                          xmlSecTransformCtxPtr transformCtx);
@@ -65,6 +78,7 @@ xmlSecOpenSSLEvpBlockCipherCtxInit(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
 
     xmlSecAssert2(ctx != NULL, -1);
     xmlSecAssert2(ctx->cipher != NULL, -1);
+    xmlSecAssert2(ctx->cipherCtx != NULL, -1);
     xmlSecAssert2(ctx->keyInitialized != 0, -1);
     xmlSecAssert2(ctx->ctxInitialized == 0, -1);
     xmlSecAssert2(in != NULL, -1);
@@ -122,7 +136,7 @@ xmlSecOpenSSLEvpBlockCipherCtxInit(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
     }
 
     /* set iv */
-    ret = EVP_CipherInit(&(ctx->cipherCtx), ctx->cipher, ctx->key, ctx->iv, encrypt);
+    ret = EVP_CipherInit(ctx->cipherCtx, ctx->cipher, ctx->key, ctx->iv, encrypt);
     if(ret != 1) {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     xmlSecErrorsSafeString(cipherName),
@@ -139,76 +153,54 @@ xmlSecOpenSSLEvpBlockCipherCtxInit(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
      * and is not supported by OpenSSL. However, it is possible
      * to disable padding and do it by yourself
      */
-    EVP_CIPHER_CTX_set_padding(&(ctx->cipherCtx), 0);
+    EVP_CIPHER_CTX_set_padding(ctx->cipherCtx, 0);
 
     return(0);
 }
 
 static int
-xmlSecOpenSSLEvpBlockCipherCtxUpdate(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
-                                  xmlSecBufferPtr in, xmlSecBufferPtr out,
-                                  const xmlChar* cipherName,
-                                  xmlSecTransformCtxPtr transformCtx) {
-    int blockLen, fixLength = 0, outLen = 0;
-    xmlSecSize inSize, outSize;
+xmlSecOpenSSLEvpBlockCipherCtxUpdateBlock(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+                                        const xmlSecByte * in,
+                                        int inSize,
+                                        xmlSecBufferPtr out,
+                                        const xmlChar* cipherName,
+                                        int final) {
     xmlSecByte* outBuf;
+    xmlSecSize outSize;
+    int blockLen, outLen = 0;
     int ret;
 
     xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(ctx->cipher != NULL, -1);
+    xmlSecAssert2(ctx->cipherCtx != NULL, -1);
     xmlSecAssert2(ctx->keyInitialized != 0, -1);
     xmlSecAssert2(ctx->ctxInitialized != 0, -1);
     xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(inSize > 0, -1);
     xmlSecAssert2(out != NULL, -1);
-    xmlSecAssert2(transformCtx != NULL, -1);
 
+    /* OpenSSL docs: If the pad parameter is zero then no padding is performed, the total amount of
+     * data encrypted or decrypted must then be a multiple of the block size or an error will occur.
+     */
     blockLen = EVP_CIPHER_block_size(ctx->cipher);
     xmlSecAssert2(blockLen > 0, -1);
+    xmlSecAssert2((inSize % blockLen) == 0, -1);
 
-    inSize = xmlSecBufferGetSize(in);
+    /* prepare: ensure we have enough space (+blockLen for final) */
     outSize = xmlSecBufferGetSize(out);
-
-    if(inSize == 0) {
-        /* wait for more data */
-        return(0);
-    }
-
-    /* OpenSSL docs: The amount of data written depends on the block
-     * alignment of the encrypted data: as a result the amount of data
-     * written may be anything from zero bytes to (inl + cipher_block_size - 1).
-     */
     ret = xmlSecBufferSetMaxSize(out, outSize + inSize + blockLen);
     if(ret < 0) {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     xmlSecErrorsSafeString(cipherName),
                     "xmlSecBufferSetMaxSize",
                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                    "size=%d", outSize + inSize + blockLen);
+                    "size=%d", (int)(outSize + inSize + blockLen));
         return(-1);
     }
-    outBuf = xmlSecBufferGetData(out) + outSize;
-
-    /*
-     * The padding used in XML Enc does not follow RFC 1423
-     * and is not supported by OpenSSL. However, it is possible
-     * to disable padding and do it by yourself
-     *
-     * The logic below is copied from EVP_DecryptUpdate() function.
-     * This is a hack but it's the only way I can provide binary
-     * compatibility with previous versions of xmlsec.
-     * This needs to be fixed in the next XMLSEC API refresh.
-     */
-    if(!ctx->cipherCtx.encrypt) {
-        if(ctx->cipherCtx.final_used) {
-            memcpy(outBuf, ctx->cipherCtx.final, blockLen);
-            outBuf += blockLen;
-            fixLength = 1;
-        } else {
-            fixLength = 0;
-        }
-    }
+    outBuf  = xmlSecBufferGetData(out) + outSize;
 
     /* encrypt/decrypt */
-    ret = EVP_CipherUpdate(&(ctx->cipherCtx), outBuf, &outLen, xmlSecBufferGetData(in), inSize);
+    ret = EVP_CipherUpdate(ctx->cipherCtx, outBuf, &outLen, in, inSize);
     if(ret != 1) {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     xmlSecErrorsSafeString(cipherName),
@@ -217,24 +209,23 @@ xmlSecOpenSSLEvpBlockCipherCtxUpdate(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
                     XMLSEC_ERRORS_NO_MESSAGE);
         return(-1);
     }
+    xmlSecAssert2(outLen == inSize, -1);
 
-    if(!ctx->cipherCtx.encrypt) {
-        /*
-         * The logic below is copied from EVP_DecryptUpdate() function.
-         * This is a hack but it's the only way I can provide binary
-         * compatibility with previous versions of xmlsec.
-         * This needs to be fixed in the next XMLSEC API refresh.
-         */
-        if (blockLen > 1 && !ctx->cipherCtx.buf_len) {
-            outLen -= blockLen;
-            ctx->cipherCtx.final_used = 1;
-            memcpy(ctx->cipherCtx.final, &outBuf[outLen], blockLen);
-        } else {
-            ctx->cipherCtx.final_used = 0;
-        }
-        if (fixLength) {
-            outLen += blockLen;
+    /* finalize transform if needed */
+    if(final != 0) {
+        int outLen2 = 0;
+
+        ret = EVP_CipherFinal(ctx->cipherCtx, outBuf + outLen, &outLen2);
+        if(ret != 1) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(cipherName),
+                        "EVP_CipherFinal",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
         }
+
+        outLen += outLen2;
     }
 
     /* set correct output buffer size */
@@ -244,160 +235,224 @@ xmlSecOpenSSLEvpBlockCipherCtxUpdate(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
                     xmlSecErrorsSafeString(cipherName),
                     "xmlSecBufferSetSize",
                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                    "size=%d", outSize + outLen);
+                    "size=%d", (int)(outSize + outLen));
+        return(-1);
+    }
+
+    /* done */
+    return (0);
+}
+
+static int
+xmlSecOpenSSLEvpBlockCipherCtxUpdate(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+                                  xmlSecBufferPtr in, xmlSecBufferPtr out,
+                                  const xmlChar* cipherName,
+                                  xmlSecTransformCtxPtr transformCtx) {
+    xmlSecSize inSize, blockLen, inBlocksLen;
+    xmlSecByte* inBuf;
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(ctx->cipherCtx != NULL, -1);
+    xmlSecAssert2(ctx->keyInitialized != 0, -1);
+    xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+    xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(transformCtx != NULL, -1);
+
+    blockLen = EVP_CIPHER_block_size(ctx->cipher);
+    xmlSecAssert2(blockLen > 0, -1);
+
+    inSize = xmlSecBufferGetSize(in);
+    if(inSize <= blockLen) {
+        /* wait for more data: we want to make sure we keep the last chunk in tmp buffer for
+         * padding check/removal on decryption
+         */
+        return(0);
+    }
+
+    /* OpenSSL docs: If the pad parameter is zero then no padding is performed, the total amount of
+     * data encrypted or decrypted must then be a multiple of the block size or an error will occur.
+     *
+     * We process all complete blocks from the input
+     */
+    inBlocksLen = blockLen * (inSize / blockLen);
+    if(inBlocksLen == inSize) {
+        inBlocksLen -= blockLen; /* ensure we keep the last block around for Final() call to 
add/check/remove padding */
+    }
+    xmlSecAssert2(inBlocksLen > 0, -1);
+
+    inBuf  = xmlSecBufferGetData(in);
+    ret = xmlSecOpenSSLEvpBlockCipherCtxUpdateBlock(ctx, inBuf, inBlocksLen, out, cipherName, 0); /* not 
final */
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(cipherName),
+                    "xmlSecOpenSSLEvpBlockCipherCtxUpdateBlock",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    NULL);
         return(-1);
     }
 
     /* remove the processed block from input */
-    ret = xmlSecBufferRemoveHead(in, inSize);
+    ret = xmlSecBufferRemoveHead(in, inBlocksLen);
     if(ret < 0) {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     xmlSecErrorsSafeString(cipherName),
                     "xmlSecBufferRemoveHead",
                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                    "size=%d", inSize);
+                    "size=%d", (int)inSize);
         return(-1);
     }
+
+    /* just a double check */
+    inSize = xmlSecBufferGetSize(in);
+    xmlSecAssert2(inSize > 0, -1);
+    xmlSecAssert2(inSize <= blockLen, -1);
+
+    /* done */
     return(0);
 }
 
 static int
 xmlSecOpenSSLEvpBlockCipherCtxFinal(xmlSecOpenSSLEvpBlockCipherCtxPtr ctx,
+                                 xmlSecBufferPtr in,
                                  xmlSecBufferPtr out,
                                  const xmlChar* cipherName,
                                  xmlSecTransformCtxPtr transformCtx) {
-    int blockLen, outLen = 0, outLen2 = 0;
-    xmlSecSize outSize;
+    xmlSecSize inSize, outSize, blockLen;
+    xmlSecByte* inBuf;
     xmlSecByte* outBuf;
     int ret;
 
     xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(ctx->cipher != NULL, -1);
+    xmlSecAssert2(ctx->cipherCtx != NULL, -1);
     xmlSecAssert2(ctx->keyInitialized != 0, -1);
     xmlSecAssert2(ctx->ctxInitialized != 0, -1);
+    xmlSecAssert2(in != NULL, -1);
     xmlSecAssert2(out != NULL, -1);
     xmlSecAssert2(transformCtx != NULL, -1);
 
     blockLen = EVP_CIPHER_block_size(ctx->cipher);
     xmlSecAssert2(blockLen > 0, -1);
+    xmlSecAssert2(blockLen <= EVP_MAX_BLOCK_LENGTH, -1);
 
-    outSize = xmlSecBufferGetSize(out);
-
-    /* OpenSSL docs: The encrypted final data is written to out which should
-     * have sufficient space for one cipher block. We might have to write
-     * one more block with padding
-     */
-    ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen);
-    if(ret < 0) {
-        xmlSecError(XMLSEC_ERRORS_HERE,
-                    xmlSecErrorsSafeString(cipherName),
-                    "xmlSecBufferSetMaxSize",
-                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                    "size=%d", outSize + 2 * blockLen);
-        return(-1);
-    }
-    outBuf = xmlSecBufferGetData(out) + outSize;
+    /* not more than one block left */
+    inSize = xmlSecBufferGetSize(in);
+    inBuf = xmlSecBufferGetData(in);
+    xmlSecAssert2(inSize <= blockLen, -1);
 
     /*
      * The padding used in XML Enc does not follow RFC 1423
      * and is not supported by OpenSSL. However, it is possible
      * to disable padding and do it by yourself
-     *
-     * The logic below is copied from EVP_DecryptFinal() function.
-     * This is a hack but it's the only way I can provide binary
-     * compatibility with previous versions of xmlsec.
-     * This needs to be fixed in the next XMLSEC API refresh.
      */
-    if(ctx->cipherCtx.encrypt) {
-        int padLen;
+    if(EVP_CIPHER_CTX_encrypting(ctx->cipherCtx)) {
+        xmlSecSize padLen;
 
-        xmlSecAssert2(blockLen <= EVP_MAX_BLOCK_LENGTH, -1);
-
-        padLen = blockLen - ctx->cipherCtx.buf_len;
+        /* figure out pad length, if it is 0 (i.e. inSize == blockLen) then set it to blockLen */
+        padLen = blockLen - inSize;
+        if(padLen == 0) {
+            padLen = blockLen;
+        }
         xmlSecAssert2(padLen > 0, -1);
+        xmlSecAssert2(inSize + padLen <= sizeof(ctx->pad), -1);
+
+        /* we can have inSize == 0 if there were no data at all, otherwise -- copy the data */
+        if(inSize > 0) {
+            memcpy(ctx->pad, inBuf, inSize);
+        }
 
         /* generate random padding */
         if(padLen > 1) {
-            ret = RAND_bytes(ctx->pad, padLen - 1);
+            ret = RAND_bytes(ctx->pad + inSize, padLen - 1);
             if(ret != 1) {
                 xmlSecError(XMLSEC_ERRORS_HERE,
                             xmlSecErrorsSafeString(cipherName),
                             "RAND_bytes",
                             XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                            "size=%d", padLen - 1);
+                            "size=%d", (int)(padLen - 1));
                 return(-1);
             }
         }
-        ctx->pad[padLen - 1] = padLen;
 
-        /* write padding */
-        ret = EVP_CipherUpdate(&(ctx->cipherCtx), outBuf, &outLen, ctx->pad, padLen);
-        if(ret != 1) {
+        /* set the last byte to the pad length */
+        ctx->pad[inSize + padLen - 1] = padLen;
+
+        /* update the last 1 or 2 blocks with padding */
+        ret = xmlSecOpenSSLEvpBlockCipherCtxUpdateBlock(ctx, ctx->pad, inSize + padLen, out, cipherName, 1); 
/* final */
+        if(ret < 0) {
             xmlSecError(XMLSEC_ERRORS_HERE,
                         xmlSecErrorsSafeString(cipherName),
-                        "EVP_CipherUpdate",
-                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                        XMLSEC_ERRORS_NO_MESSAGE);
+                        "xmlSecOpenSSLEvpBlockCipherCtxUpdateBlock",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        NULL);
             return(-1);
         }
-        outBuf += outLen;
-    }
+    } else {
+        xmlSecSize padLen;
 
-    /* finalize transform */
-    ret = EVP_CipherFinal(&(ctx->cipherCtx), outBuf, &outLen2);
-    if(ret != 1) {
-        xmlSecError(XMLSEC_ERRORS_HERE,
+        /* update the last one block with padding */
+        ret = xmlSecOpenSSLEvpBlockCipherCtxUpdateBlock(ctx, inBuf, inSize, out, cipherName, 1); /* final */
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(cipherName),
+                        "xmlSecOpenSSLEvpBlockCipherCtxUpdateBlock",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        NULL);
+            return(-1);
+        }
+
+        /* we expect at least one block in the output -- the one we just decrypted */
+        outBuf = xmlSecBufferGetData(out);
+        outSize = xmlSecBufferGetSize(out);
+        if(outSize < blockLen) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
                     xmlSecErrorsSafeString(cipherName),
-                    "EVP_CipherFinal",
-                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                    XMLSEC_ERRORS_NO_MESSAGE);
-        return(-1);
-    }
+                    NULL,
+                    XMLSEC_ERRORS_R_INVALID_DATA,
+                    "outSize=%d;blockLen=%d",
+                    (int)outSize, (int)blockLen);
+            return(-1);
+        }
 
-    /*
-     * The padding used in XML Enc does not follow RFC 1423
-     * and is not supported by OpenSSL. However, it is possible
-     * to disable padding and do it by yourself
-     *
-     * The logic below is copied from EVP_DecryptFinal() function.
-     * This is a hack but it's the only way I can provide binary
-     * compatibility with previous versions of xmlsec.
-     * This needs to be fixed in the next XMLSEC API refresh.
-     */
-     if(!ctx->cipherCtx.encrypt) {
-        /* we instructed openssl to do not use padding so there
-         * should be no final block
-         */
-        xmlSecAssert2(outLen2 == 0, -1);
-        xmlSecAssert2(ctx->cipherCtx.buf_len == 0, -1);
-        xmlSecAssert2(ctx->cipherCtx.final_used, -1);
-
-        if(blockLen > 1) {
-            outLen2 = blockLen - ctx->cipherCtx.final[blockLen - 1];
-            if(outLen2 > 0) {
-                memcpy(outBuf, ctx->cipherCtx.final, outLen2);
-            } else if(outLen2 < 0) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                            xmlSecErrorsSafeString(cipherName),
-                            NULL,
-                            XMLSEC_ERRORS_R_INVALID_DATA,
-                            "padding=%d;buffer=%d",
-                            ctx->cipherCtx.final[blockLen - 1], blockLen);
-                return(-1);
-            }
+        /* get the pad length from the last byte */
+        padLen = (xmlSecSize)(outBuf[outSize - 1]);
+        if(padLen > blockLen) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(cipherName),
+                    NULL,
+                    XMLSEC_ERRORS_R_INVALID_DATA,
+                    "padLen=%d;blockLen=%d",
+                    (int)padLen, (int)blockLen);
+            return(-1);
+        }
+        xmlSecAssert2(padLen <= outSize, -1);
+
+        /* remove the padding */
+        ret = xmlSecBufferRemoveTail(out, padLen);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(cipherName),
+                        "xmlSecBufferRemoveTail",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "size=%d", (int)padLen);
+            return(-1);
         }
     }
 
-    /* set correct output buffer size */
-    ret = xmlSecBufferSetSize(out, outSize + outLen + outLen2);
+    /* remove the processed block from input */
+    ret = xmlSecBufferRemoveHead(in, inSize);
     if(ret < 0) {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     xmlSecErrorsSafeString(cipherName),
-                    "xmlSecBufferSetSize",
+                    "xmlSecBufferRemoveHead",
                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                    "size=%d", outSize + outLen + outLen2);
+                    "size=%d", (int)inSize);
         return(-1);
     }
 
+    /* done */
     return(0);
 }
 
@@ -488,7 +543,18 @@ xmlSecOpenSSLEvpBlockCipherInitialize(xmlSecTransformPtr transform) {
         return(-1);
     }
 
-    EVP_CIPHER_CTX_init(&(ctx->cipherCtx));
+    /* create cipher ctx */
+    ctx->cipherCtx = EVP_CIPHER_CTX_new();
+    if(ctx->cipherCtx == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                    "EVP_CIPHER_CTX_new",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    /* done */
     return(0);
 }
 
@@ -502,7 +568,10 @@ xmlSecOpenSSLEvpBlockCipherFinalize(xmlSecTransformPtr transform) {
     ctx = xmlSecOpenSSLEvpBlockCipherGetCtx(transform);
     xmlSecAssert(ctx != NULL);
 
-    EVP_CIPHER_CTX_cleanup(&(ctx->cipherCtx));
+    if(ctx->cipherCtx != NULL) {
+        EVP_CIPHER_CTX_free(ctx->cipherCtx);
+    }
+
     memset(ctx, 0, sizeof(xmlSecOpenSSLEvpBlockCipherCtx));
 }
 
@@ -567,7 +636,7 @@ xmlSecOpenSSLEvpBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key
                     NULL,
                     XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
                     "keySize=%d;expected=%d",
-                    xmlSecBufferGetSize(buffer), cipherKeyLen);
+                    (int)xmlSecBufferGetSize(buffer), (int)cipherKeyLen);
         return(-1);
     }
 
@@ -637,9 +706,7 @@ xmlSecOpenSSLEvpBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSe
         }
 
         if(last != 0) {
-            /* by now there should be no input */
-            xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
-            ret = xmlSecOpenSSLEvpBlockCipherCtxFinal(ctx, out,
+            ret = xmlSecOpenSSLEvpBlockCipherCtxFinal(ctx, in, out,
                                             xmlSecTransformGetName(transform),
                                             transformCtx);
             if(ret < 0) {
@@ -651,6 +718,9 @@ xmlSecOpenSSLEvpBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSe
                 return(-1);
             }
             transform->status = xmlSecTransformStatusFinished;
+
+            /* by now there should be no input */
+            xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
         }
     } else if(transform->status == xmlSecTransformStatusFinished) {
         /* the only way we can get here is if there is no input */
@@ -663,7 +733,7 @@ xmlSecOpenSSLEvpBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSe
                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                     NULL,
                     XMLSEC_ERRORS_R_INVALID_STATUS,
-                    "status=%d", transform->status);
+                    "status=%d", (int)(transform->status));
         return(-1);
     }
 
diff --git a/src/openssl/signatures.c b/src/openssl/signatures.c
index 14d20cd..b0fdb89 100644
--- a/src/openssl/signatures.c
+++ b/src/openssl/signatures.c
@@ -34,9 +34,7 @@ static const EVP_MD *xmlSecOpenSSLDsaSha1Evp                    (void);
 #endif /* XMLSEC_NO_SHA1 */
 
 #ifndef XMLSEC_NO_SHA256
-#ifdef XMLSEC_OPENSSL_100
 static const EVP_MD *xmlSecOpenSSLDsaSha256Evp                  (void);
-#endif /* XMLSEC_OPENSSL_100 */
 #endif /* XMLSEC_NO_SHA256 */
 
 #endif /* XMLSEC_NO_DSA */
@@ -267,12 +265,10 @@ xmlSecOpenSSLEvpSignatureInitialize(xmlSecTransformPtr transform) {
 #endif /* XMLSEC_NO_SHA1 */
 
 #ifndef XMLSEC_NO_SHA256
-#ifdef XMLSEC_OPENSSL_100
     if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformDsaSha256Id)) {
         ctx->digest     = xmlSecOpenSSLDsaSha256Evp();
         ctx->keyId      = xmlSecOpenSSLKeyDataDsaId;
     } else
-#endif /* XMLSEC_OPENSSL_100 */
 #endif /* XMLSEC_NO_SHA256 */
 
 #endif /* XMLSEC_NO_DSA */
@@ -932,9 +928,9 @@ static const EVP_MD xmlSecOpenSSLDsaSha1MdEvp = {
     {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3,EVP_PKEY_DSA4,0},
     SHA_CBLOCK,
     sizeof(EVP_MD *)+sizeof(SHA_CTX)
-#ifdef XMLSEC_OPENSSL_100
+#if defined(XMLSEC_OPENSSL_100) || defined(XMLSEC_OPENSSL_110)
    , NULL
-#endif /* XMLSEC_OPENSSL_100 */
+#endif /* defined(XMLSEC_OPENSSL_100) || defined(XMLSEC_OPENSSL_110) */
 };
 
 static const EVP_MD *xmlSecOpenSSLDsaSha1Evp(void)
@@ -990,7 +986,6 @@ xmlSecOpenSSLTransformDsaSha256GetKlass(void) {
     return(&xmlSecOpenSSLDsaSha256Klass);
 }
 
-#ifdef XMLSEC_OPENSSL_100
 static int
 xmlSecOpenSSLDsaSha256EvpInit(EVP_MD_CTX *ctx)
 {
@@ -1032,7 +1027,6 @@ static const EVP_MD *xmlSecOpenSSLDsaSha256Evp(void)
 {
     return(&xmlSecOpenSSLDsaSha256MdEvp);
 }
-#endif /* XMLSEC_OPENSSL_100 */
 
 #endif /* XMLSEC_NO_SHA256 */
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]