[xmlsec] adding AES KW support to xmlsec-mscrypto



commit 34e5d043269971f807c49faf2b679396aee992b0
Author: Aleksey Sanin <aleksey aleksey com>
Date:   Sat May 8 01:12:13 2010 -0700

    adding AES KW support to xmlsec-mscrypto

 ChangeLog                        |    3 +
 TODO                             |   23 +--
 docs/xmlenc.html                 |   18 +-
 include/xmlsec/mscrypto/crypto.h |   27 +++
 src/kw_aes_des.c                 |   40 +++-
 src/kw_aes_des.h                 |   16 +-
 src/mscrypto/ciphers.c           |  468 +++++++++++++++++++++++++++++++++++++-
 src/mscrypto/crypto.c            |    3 +
 src/openssl/kw_aes.c             |   30 ++-
 tests/testEnc.sh                 |    6 +-
 win32/mycfg.bat                  |    2 +-
 11 files changed, 572 insertions(+), 64 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index c2bdfec..483f5b9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2010-05-08  Aleksey Sanin  <aleksey aleksey com>
+	* Added AES KW support for xmlsec-mscrypto
+
 2010-04-30  Aleksey Sanin  <aleksey aleksey com>
 	* Added RSA/OAEP support for xmlsec-mscrypto
 
diff --git a/TODO b/TODO
index d4939bf..67dd7f3 100644
--- a/TODO
+++ b/TODO
@@ -47,11 +47,10 @@ merlin-xmldsig-twenty-three/signature-x509-crt-crl
 
 
 -------------------------------------------------
-* xmlsec-mscrypto (April 26, 2010 using Windows XP SP3)
+* xmlsec-mscrypto (May 08, 2010 using Windows XP SP3)
 -------------------------------------------------
 
-** Skipped tests due to missing transforms: RIPEMD160, SHA224,
-AES and DES KW
+** Skipped tests due to missing transforms: RIPEMD160, SHA224, DES KW
 
 aleksey-xmldsig-01/enveloping-ripemd160-hmac-ripemd160
 aleksey-xmldsig-01/enveloping-ripemd160-hmac-ripemd160-64
@@ -59,27 +58,11 @@ aleksey-xmldsig-01/enveloping-sha224-hmac-sha224
 aleksey-xmldsig-01/enveloping-sha224-hmac-sha224-64
 aleksey-xmldsig-01/enveloping-ripemd160-rsa-ripemd160
 aleksey-xmldsig-01/enveloping-sha224-rsa-sha224
-
 merlin-xmlenc-five/encsig-ripemd160-hmac-ripemd160-kw-tripledes
-merlin-xmlenc-five/encsig-sha256-hmac-sha256-kw-aes128
-merlin-xmlenc-five/encsig-sha384-hmac-sha384-kw-aes192
-merlin-xmlenc-five/encsig-sha512-hmac-sha512-kw-aes256
-aleksey-xmlenc-01/enc-des3cbc-aes192-keyname
 merlin-xmlenc-five/encrypt-data-aes256-cbc-kw-tripledes
-merlin-xmlenc-five/encrypt-content-aes128-cbc-kw-aes192
-merlin-xmlenc-five/encrypt-data-aes192-cbc-kw-aes256
-merlin-xmlenc-five/encrypt-element-tripledes-cbc-kw-aes128
-merlin-xmlenc-five/encrypt-element-aes256-cbc-retrieved-kw-aes256
 01-phaos-xmlenc-3/enc-element-3des-kw-3des
 01-phaos-xmlenc-3/enc-content-aes128-kw-3des
-01-phaos-xmlenc-3/enc-element-aes128-kw-aes128
-01-phaos-xmlenc-3/enc-element-aes128-kw-aes256
-01-phaos-xmlenc-3/enc-content-3des-kw-aes192
-01-phaos-xmlenc-3/enc-content-aes192-kw-aes256
-01-phaos-xmlenc-3/enc-element-aes192-kw-aes192
-01-phaos-xmlenc-3/enc-element-aes256-kw-aes256
-01-phaos-xmlenc-3/enc-text-3des-kw-aes256
-01-phaos-xmlenc-3/enc-text-aes128-kw-aes192
+
 
 ** Failed tests due to no GOST crypto providers on test machine
 
diff --git a/docs/xmlenc.html b/docs/xmlenc.html
index 2d74b80..dc5739d 100644
--- a/docs/xmlenc.html
+++ b/docs/xmlenc.html
@@ -352,7 +352,7 @@ data. </li>
                   <td style="vertical-align: top;">Y</td>
                 </tr>
 <tr>
-<td style="width: 40%;" valign="top"> AES-192<br>
+<td style="width: 40%;" valign="top">AES-192<br>
 </td>
                   <td valign="top">Y<br>
 </td>
@@ -405,7 +405,7 @@ Wrap<br>
                   <td style="vertical-align: top;">N</td>
                 </tr>
 <tr>
-<td style="width: 40%;" valign="top"> AES-128 Key
+<td style="width: 40%;" valign="top">AES-128 Key
 Wrap (128 bit keys)<br>
 </td>
                   <td valign="top">Y<br>
@@ -413,30 +413,30 @@ Wrap (128 bit keys)<br>
                   <td style="vertical-align: top;">N</td>
                   <td style="vertical-align: top;">Y<br>
 </td>
-                  <td style="vertical-align: top;">N<br>
+                  <td style="vertical-align: top;">Y<br>
 </td>
                 </tr>
 <tr>
-<td style="width: 40%;" valign="top"> AES-256 Key
-Wrap (256 bit keys)<br>
+<td style="width: 40%;" valign="top"> AES-192 Key Wrap<br>
 </td>
                   <td valign="top">Y<br>
 </td>
                   <td style="vertical-align: top;">N</td>
                   <td style="vertical-align: top;">Y<br>
 </td>
-                  <td style="vertical-align: top;">N<br>
-</td>
+                  <td style="vertical-align: top;">Y</td>
                 </tr>
 <tr>
-<td style="width: 40%;" valign="top"> AES-192 Key Wrap<br>
+<td style="width: 40%;" valign="top"> AES-256 Key
+Wrap (256 bit keys)<br>
 </td>
                   <td valign="top">Y<br>
 </td>
                   <td style="vertical-align: top;">N</td>
                   <td style="vertical-align: top;">Y<br>
 </td>
-                  <td style="vertical-align: top;">N</td>
+                  <td style="vertical-align: top;">Y<br>
+</td>
                 </tr>
 <tr>
 <td style="width: 40%;" valign="top"> SHA1<br>
diff --git a/include/xmlsec/mscrypto/crypto.h b/include/xmlsec/mscrypto/crypto.h
index ab3a026..ad24322 100644
--- a/include/xmlsec/mscrypto/crypto.h
+++ b/include/xmlsec/mscrypto/crypto.h
@@ -361,6 +361,33 @@ XMLSEC_CRYPTO_EXPORT xmlSecTransformId  xmlSecMSCryptoTransformAes192CbcGetKlass
         xmlSecMSCryptoTransformAes256CbcGetKlass()
 XMLSEC_CRYPTO_EXPORT xmlSecTransformId  xmlSecMSCryptoTransformAes256CbcGetKlass(void);
 
+/**
+ * xmlSecMSCryptoTransformKWAes128Id:
+ *
+ * The AES 128 key wrap transform klass.
+ */
+#define xmlSecMSCryptoTransformKWAes128Id \
+        xmlSecMSCryptoTransformKWAes128GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecTransformId  xmlSecMSCryptoTransformKWAes128GetKlass(void);
+
+/**
+ * xmlSecMSCryptoTransformKWAes192Id:
+ *
+ * The AES 192 key wrap transform klass.
+ */
+#define xmlSecMSCryptoTransformKWAes192Id \
+        xmlSecMSCryptoTransformKWAes192GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecTransformId  xmlSecMSCryptoTransformKWAes192GetKlass(void);
+
+/**
+ * xmlSecMSCryptoTransformKWAes256Id:
+ *
+ * The AES 256 key wrap transform klass.
+ */
+#define xmlSecMSCryptoTransformKWAes256Id \
+        xmlSecMSCryptoTransformKWAes256GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecTransformId  xmlSecMSCryptoTransformKWAes256GetKlass(void);
+
 #endif /* XMLSEC_NO_AES */
 
 
diff --git a/src/kw_aes_des.c b/src/kw_aes_des.c
index ae6452e..638edd3 100644
--- a/src/kw_aes_des.c
+++ b/src/kw_aes_des.c
@@ -127,7 +127,15 @@ xmlSecKWAesEncode(xmlSecAesBlockEncryptCallback encryptCallback, void *key,
 
     N = (inSize / 8);
     if(N == 1) {
-        encryptCallback(out, out, key);
+        ret = encryptCallback(out, inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE, out, outSize, key);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "encryptCallback",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
     } else {
         for(j = 0; j <= 5; ++j) {
             for(i = 1; i <= N; ++i) {
@@ -137,7 +145,15 @@ xmlSecKWAesEncode(xmlSecAesBlockEncryptCallback encryptCallback, void *key,
                 memcpy(block, out, 8);
                 memcpy(block + 8, p, 8);
 
-                encryptCallback(block, block, key);
+                ret = encryptCallback(block, sizeof(block), block, sizeof(block), key);
+                if(ret < 0) {
+                    xmlSecError(XMLSEC_ERRORS_HERE,
+                                NULL,
+                                "encryptCallback",
+                                XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                                XMLSEC_ERRORS_NO_MESSAGE);
+                    return(-1);
+                }
                 block[7] ^=  t;
                 memcpy(out, block, 8);
                 memcpy(p, block + 8, 8);
@@ -171,7 +187,15 @@ xmlSecKWAesDecode(xmlSecAesBlockDecryptCallback decryptCallback, void *key,
 
     N = (inSize / 8) - 1;
     if(N == 1) {
-        decryptCallback(out, out, key);
+        ret = decryptCallback(out, inSize, out, outSize, key);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "decryptCallback",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
     } else {
         for(j = 5; j >= 0; --j) {
             for(i = N; i > 0; --i) {
@@ -182,7 +206,15 @@ xmlSecKWAesDecode(xmlSecAesBlockDecryptCallback decryptCallback, void *key,
                 memcpy(block + 8, p, 8);
                 block[7] ^= t;
 
-                decryptCallback(block, block, key);
+                ret = decryptCallback(block, sizeof(block), block, sizeof(block), key);
+                if(ret < 0) {
+                    xmlSecError(XMLSEC_ERRORS_HERE,
+                                NULL,
+                                "encryptCallback",
+                                XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                                XMLSEC_ERRORS_NO_MESSAGE);
+                    return(-1);
+                }
                 memcpy(out, block, 8);
                 memcpy(p, block + 8, 8);
             }
diff --git a/src/kw_aes_des.h b/src/kw_aes_des.h
index d6a7504..9283a18 100755
--- a/src/kw_aes_des.h
+++ b/src/kw_aes_des.h
@@ -34,12 +34,16 @@ extern "C" {
 #define XMLSEC_KW_AES192_KEY_SIZE                   24
 #define XMLSEC_KW_AES256_KEY_SIZE                   32
 
-typedef int  (*xmlSecAesBlockEncryptCallback)       (const xmlSecByte * in,
-                                                     xmlSecByte * out,
-                                                     void * key);
-typedef int  (*xmlSecAesBlockDecryptCallback)       (const xmlSecByte * in,
-                                                     xmlSecByte * out,
-                                                     void * key);
+typedef int  (*xmlSecAesBlockEncryptCallback)       (const xmlSecByte * in,
+                                                     xmlSecSize inSize,
+                                                     xmlSecByte * out,
+                                                     xmlSecSize outSize,
+                                                     void * key);
+typedef int  (*xmlSecAesBlockDecryptCallback)       (const xmlSecByte * in,
+                                                     xmlSecSize inSize,
+                                                     xmlSecByte * out,
+                                                     xmlSecSize outSize,
+                                                     void * key);
 
 
 XMLSEC_EXPORT int
diff --git a/src/mscrypto/ciphers.c b/src/mscrypto/ciphers.c
index 3c70474..0aa0fe7 100644
--- a/src/mscrypto/ciphers.c
+++ b/src/mscrypto/ciphers.c
@@ -20,14 +20,16 @@
 #include <xmlsec/errors.h>
 
 #include <xmlsec/mscrypto/crypto.h>
+
+#include "../kw_aes_des.h"
 #include "private.h"
 
+
 #if defined(__MINGW32__)
 #  include "xmlsec-mingw.h"
 #endif
 
 
-
 /**************************************************************************
  *
  * Internal MSCrypto Block cipher CTX
@@ -37,15 +39,15 @@ typedef struct _xmlSecMSCryptoBlockCipherCtx            xmlSecMSCryptoBlockCiphe
                                                         *xmlSecMSCryptoBlockCipherCtxPtr;
 struct _xmlSecMSCryptoBlockCipherCtx {
     ALG_ID                              algorithmIdentifier;
-    int                                 mode;
+    const xmlSecMSCryptoProviderInfo  * providers;
+    xmlSecKeyDataId                     keyId;
+    xmlSecSize                          keySize;
+
     HCRYPTPROV                          cryptProvider;
-    HCRYPTKEY                           cryptKey;
     HCRYPTKEY                           pubPrivKey;
-    xmlSecKeyDataId                     keyId;
-    const xmlSecMSCryptoProviderInfo  * providers;
-    int                                 keyInitialized;
+    HCRYPTKEY                           cryptKey;
+    xmlSecBuffer                        kwKeyBuffer; /* used only for KW algorithm - need to reset cryptKey for every operation to avoid CBC mode */
     int                                 ctxInitialized;
-    xmlSecSize                          keySize;
 };
 /* function declarations */
 static int      xmlSecMSCryptoBlockCipherCtxUpdate      (xmlSecMSCryptoBlockCipherCtxPtr ctx,
@@ -68,7 +70,7 @@ xmlSecMSCryptoBlockCipherCtxInit(xmlSecMSCryptoBlockCipherCtxPtr ctx,
     DWORD dwBlockLen, dwBlockLenLen;
 
     xmlSecAssert2(ctx != NULL, -1);
-    xmlSecAssert2(ctx->keyInitialized != 0, -1);
+    xmlSecAssert2(ctx->cryptKey != 0, -1);
     xmlSecAssert2(ctx->ctxInitialized == 0, -1);
     xmlSecAssert2(in != NULL, -1);
     xmlSecAssert2(out != NULL, -1);
@@ -496,6 +498,13 @@ xmlSecMSCryptoBlockCipherCheckId(xmlSecTransformPtr transform) {
 
        return(1);
     }
+
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWAes128Id) ||
+       xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWAes192Id) ||
+       xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformKWAes256Id)) {
+
+       return(1);
+    }
 #endif /* XMLSEC_NO_AES */
 
     return(0);
@@ -504,6 +513,7 @@ xmlSecMSCryptoBlockCipherCheckId(xmlSecTransformPtr transform) {
 static int
 xmlSecMSCryptoBlockCipherInitialize(xmlSecTransformPtr transform) {
     xmlSecMSCryptoBlockCipherCtxPtr ctx;
+    int ret;
 
     xmlSecAssert2(xmlSecMSCryptoBlockCipherCheckId(transform), -1);
     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoBlockCipherSize), -1);
@@ -513,6 +523,16 @@ xmlSecMSCryptoBlockCipherInitialize(xmlSecTransformPtr transform) {
 
     memset(ctx, 0, sizeof(xmlSecMSCryptoBlockCipherCtx));
 
+    ret = xmlSecBufferInitialize(&ctx->kwKeyBuffer, 0);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                    NULL,
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
 #ifndef XMLSEC_NO_DES
     if(transform->id == xmlSecMSCryptoTransformDes3CbcId) {
         ctx->algorithmIdentifier    = CALG_3DES;
@@ -538,7 +558,23 @@ xmlSecMSCryptoBlockCipherInitialize(xmlSecTransformPtr transform) {
         ctx->keyId                  = xmlSecMSCryptoKeyDataAesId;
         ctx->providers              = xmlSecMSCryptoProviderInfo_Aes;
         ctx->keySize                = 32;
+    } else if(transform->id == xmlSecMSCryptoTransformKWAes128Id) {
+        ctx->algorithmIdentifier    = CALG_AES_128;
+        ctx->keyId                  = xmlSecMSCryptoKeyDataAesId;
+        ctx->providers              = xmlSecMSCryptoProviderInfo_Aes;
+        ctx->keySize                = XMLSEC_KW_AES128_KEY_SIZE;
+    } else if(transform->id == xmlSecMSCryptoTransformKWAes192Id) {
+        ctx->algorithmIdentifier    = CALG_AES_192;
+        ctx->keyId                  = xmlSecMSCryptoKeyDataAesId;
+        ctx->providers              = xmlSecMSCryptoProviderInfo_Aes;
+        ctx->keySize                = XMLSEC_KW_AES192_KEY_SIZE;
+    } else if(transform->id == xmlSecMSCryptoTransformKWAes256Id) {
+        ctx->algorithmIdentifier    = CALG_AES_256;
+        ctx->keyId                  = xmlSecMSCryptoKeyDataAesId;
+        ctx->providers              = xmlSecMSCryptoProviderInfo_Aes;
+        ctx->keySize                = XMLSEC_KW_AES256_KEY_SIZE;
     } else
+
 #endif /* XMLSEC_NO_AES */
 
     {
@@ -595,6 +631,8 @@ xmlSecMSCryptoBlockCipherFinalize(xmlSecTransformPtr transform) {
     if (ctx->cryptProvider) {
         CryptReleaseContext(ctx->cryptProvider, 0);
     }
+    
+    xmlSecBufferFinalize(&ctx->kwKeyBuffer);
 
     memset(ctx, 0, sizeof(xmlSecMSCryptoBlockCipherCtx));
 }
@@ -637,7 +675,7 @@ xmlSecMSCryptoBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key)
 
     ctx = xmlSecMSCryptoBlockCipherGetCtx(transform);
     xmlSecAssert2(ctx != NULL, -1);
-    xmlSecAssert2(ctx->keyInitialized == 0, -1);
+    xmlSecAssert2(ctx->cryptKey == 0, -1);
     xmlSecAssert2(ctx->pubPrivKey != 0, -1);
     xmlSecAssert2(ctx->keyId != NULL, -1);
     xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
@@ -676,7 +714,6 @@ xmlSecMSCryptoBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key)
         return(-1);
     }
 
-    ctx->keyInitialized = 1;
     return(0);
 }
 
@@ -941,3 +978,414 @@ xmlSecMSCryptoTransformDes3CbcGetKlass(void) {
 }
 #endif /* XMLSEC_NO_DES */
 
+#ifndef XMLSEC_NO_AES
+static int 
+xmlSecMSCryptoAesBlockEncryptCallback(const xmlSecByte * in, xmlSecSize inSize,
+                                      xmlSecByte * out, xmlSecSize outSize,
+                                      void * key) {
+    xmlSecMSCryptoBlockCipherCtxPtr ctx = (xmlSecMSCryptoBlockCipherCtxPtr)key;
+    DWORD dwCLen;
+
+    xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+    xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(outSize >= inSize, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(ctx->pubPrivKey != 0, -1);
+    xmlSecAssert2(ctx->cryptKey == 0, -1);
+    xmlSecAssert2(xmlSecBufferGetSize(&ctx->kwKeyBuffer) == ctx->keySize, -1);
+
+    /* Import this key and get an HCRYPTKEY handle, we do it again and again 
+       to ensure we don't go into CBC mode */
+    if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->cryptProvider,
+        ctx->pubPrivKey,
+        ctx->algorithmIdentifier,
+        xmlSecBufferGetData(&ctx->kwKeyBuffer),
+        xmlSecBufferGetSize(&ctx->kwKeyBuffer),
+        TRUE,
+        &(ctx->cryptKey)))  {
+
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecMSCryptoImportPlainSessionBlob",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    /* Set process last block to false, since we handle padding ourselves, and MSCrypto padding
+     * can be skipped. I hope this will work .... */
+    memcpy(out, in, inSize);
+    dwCLen = inSize;
+    if(!CryptEncrypt(ctx->cryptKey, 0, FALSE, 0, out, &dwCLen, outSize)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "CryptEncrypt",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    /* cleanup */
+    if (ctx->cryptKey != 0) {
+        CryptDestroyKey(ctx->cryptKey);
+        ctx->cryptKey = 0;
+    }
+
+    return(0);
+}
+
+static int
+xmlSecMSCryptoAesBlockDecryptCallback(const xmlSecByte * in, xmlSecSize inSize,
+                                      xmlSecByte * out, xmlSecSize outSize,
+                                      void * key) {
+    xmlSecMSCryptoBlockCipherCtxPtr ctx = (xmlSecMSCryptoBlockCipherCtxPtr)key;
+    DWORD dwCLen;
+
+    xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(inSize >= XMLSEC_KW_AES_BLOCK_SIZE, -1);
+    xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(outSize >= inSize, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(ctx->pubPrivKey != 0, -1);
+    xmlSecAssert2(ctx->cryptKey == 0, -1);
+    xmlSecAssert2(xmlSecBufferGetSize(&ctx->kwKeyBuffer) == ctx->keySize, -1);
+
+    /* Import this key and get an HCRYPTKEY handle, we do it again and again 
+       to ensure we don't go into CBC mode */
+    if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->cryptProvider,
+        ctx->pubPrivKey,
+        ctx->algorithmIdentifier,
+        xmlSecBufferGetData(&ctx->kwKeyBuffer),
+        xmlSecBufferGetSize(&ctx->kwKeyBuffer),
+        TRUE,
+        &(ctx->cryptKey)))  {
+
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecMSCryptoImportPlainSessionBlob",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    /* Set process last block to false, since we handle padding ourselves, and MSCrypto padding
+     * can be skipped. I hope this will work .... */
+    memcpy(out, in, inSize);
+    dwCLen = inSize;
+    if(!CryptDecrypt(ctx->cryptKey, 0, FALSE, 0, out, &dwCLen)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "CryptEncrypt",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    /* cleanup */
+    if (ctx->cryptKey != 0) {
+        CryptDestroyKey(ctx->cryptKey);
+        ctx->cryptKey = 0;
+    }
+
+    return(0);
+}
+
+static int
+xmlSecMSCryptoKWAesSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
+    xmlSecMSCryptoBlockCipherCtxPtr ctx;
+    xmlSecBufferPtr buffer;
+    xmlSecSize keySize;
+    int ret;
+
+    xmlSecAssert2(xmlSecMSCryptoBlockCipherCheckId(transform), -1);
+    xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoBlockCipherSize), -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataAesId), -1);
+
+    ctx = xmlSecMSCryptoBlockCipherGetCtx(transform);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
+    xmlSecAssert2(buffer != NULL, -1);
+
+    keySize = xmlSecBufferGetSize(buffer);
+    if(keySize < ctx->keySize) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                    NULL,
+                    XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE,
+                    "key=%d;expected=%d",
+                    keySize, ctx->keySize);
+        return(-1);
+    }
+
+    ret = xmlSecBufferSetData(&(ctx->kwKeyBuffer),
+                            xmlSecBufferGetData(buffer),
+                            ctx->keySize);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                    "xmlSecBufferSetData",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "expected-size=%d", 
+                    ctx->keySize);
+        return(-1);
+    }
+
+    return(0);
+}
+
+static int
+xmlSecMSCryptoKWAesExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
+    xmlSecMSCryptoBlockCipherCtxPtr ctx;
+    xmlSecBufferPtr in, out;
+    xmlSecSize inSize, outSize;
+    int ret;
+
+    xmlSecAssert2(xmlSecMSCryptoBlockCipherCheckId(transform), -1);
+    xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
+    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoBlockCipherSize), -1);
+    xmlSecAssert2(transformCtx != NULL, -1);
+
+    ctx = xmlSecMSCryptoBlockCipherGetCtx(transform);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    in = &(transform->inBuf);
+    out = &(transform->outBuf);
+    inSize = xmlSecBufferGetSize(in);
+    outSize = xmlSecBufferGetSize(out);
+    xmlSecAssert2(outSize == 0, -1);
+
+    if(transform->status == xmlSecTransformStatusNone) {
+        transform->status = xmlSecTransformStatusWorking;
+    }
+
+    if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
+        /* just do nothing */
+    } else  if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
+        if((inSize % 8) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                        NULL,
+                        XMLSEC_ERRORS_R_INVALID_SIZE,
+                        "size=%d(not 8 bytes aligned)", inSize);
+            return(-1);
+        }
+
+        if(transform->operation == xmlSecTransformOperationEncrypt) {
+            /* the encoded key might be 8 bytes longer plus 8 bytes just in case */
+            outSize = inSize + XMLSEC_KW_AES_MAGIC_BLOCK_SIZE +
+                               XMLSEC_KW_AES_BLOCK_SIZE;
+        } else {
+            outSize = inSize + XMLSEC_KW_AES_BLOCK_SIZE;
+        }
+
+        ret = xmlSecBufferSetMaxSize(out, outSize);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                        "xmlSecBufferSetMaxSize",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "outSize=%d", outSize);
+            return(-1);
+        }
+
+        if(transform->operation == xmlSecTransformOperationEncrypt) {
+            ret = xmlSecKWAesEncode(xmlSecMSCryptoAesBlockEncryptCallback, ctx,
+                                    xmlSecBufferGetData(in), inSize,
+                                    xmlSecBufferGetData(out), outSize);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                            "xmlSecKWAesEncode",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                return(-1);
+            }
+            outSize = ret;
+        } else {
+            ret = xmlSecKWAesDecode(xmlSecMSCryptoAesBlockDecryptCallback, ctx,
+                                    xmlSecBufferGetData(in), inSize,
+                                    xmlSecBufferGetData(out), outSize);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                            "xmlSecKWAesEncode",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                return(-1);
+            }
+            outSize = ret;
+        }
+
+        ret = xmlSecBufferSetSize(out, outSize);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                        "xmlSecBufferSetSize",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "outSize=%d", outSize);
+            return(-1);
+        }
+
+        ret = xmlSecBufferRemoveHead(in, inSize);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                        "xmlSecBufferRemoveHead",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "inSize%d", inSize);
+            return(-1);
+        }
+
+        transform->status = xmlSecTransformStatusFinished;
+    } else if(transform->status == xmlSecTransformStatusFinished) {
+        /* the only way we can get here is if there is no input */
+        xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1);
+    } else {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+                    NULL,
+                    XMLSEC_ERRORS_R_INVALID_STATUS,
+                    "status=%d", transform->status);
+        return(-1);
+    }
+    return(0);
+}
+
+/*********************************************************************
+ *
+ * AES KW cipher transforms
+ *
+ ********************************************************************/
+
+/*
+ * The AES-128 kew wrapper transform klass.
+ */
+static xmlSecTransformKlass xmlSecMSCryptoKWAes128Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
+    xmlSecMSCryptoBlockCipherSize,              /* xmlSecSize objSize */
+
+    xmlSecNameKWAes128,                         /* const xmlChar* name; */
+    xmlSecHrefKWAes128,                         /* const xmlChar* href; */
+    xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
+
+    xmlSecMSCryptoBlockCipherInitialize,        /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecMSCryptoBlockCipherFinalize,          /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
+    xmlSecMSCryptoBlockCipherSetKeyReq,         /* xmlSecTransformSetKeyMethod setKeyReq; */
+    xmlSecMSCryptoKWAesSetKey,                  /* xmlSecTransformSetKeyMethod setKey; */
+    NULL,                                       /* xmlSecTransformValidateMethod validate; */
+    xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecMSCryptoKWAesExecute,                 /* xmlSecTransformExecuteMethod execute; */
+
+    NULL,                                       /* void* reserved0; */
+    NULL,                                       /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformKWAes128GetKlass:
+ *
+ * The AES-128 kew wrapper transform klass.
+ *
+ * Returns: AES-128 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformKWAes128GetKlass(void) {
+    return(&xmlSecMSCryptoKWAes128Klass);
+}
+
+
+/*
+ * The AES-192 kew wrapper transform klass.
+ */
+static xmlSecTransformKlass xmlSecMSCryptoKWAes192Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
+    xmlSecMSCryptoBlockCipherSize,              /* xmlSecSize objSize */
+
+    xmlSecNameKWAes192,                         /* const xmlChar* name; */
+    xmlSecHrefKWAes192,                         /* const xmlChar* href; */
+    xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
+
+    xmlSecMSCryptoBlockCipherInitialize,        /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecMSCryptoBlockCipherFinalize,          /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
+    xmlSecMSCryptoBlockCipherSetKeyReq,         /* xmlSecTransformSetKeyMethod setKeyReq; */
+    xmlSecMSCryptoKWAesSetKey,                  /* xmlSecTransformSetKeyMethod setKey; */
+    NULL,                                       /* xmlSecTransformValidateMethod validate; */
+    xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecMSCryptoKWAesExecute,                 /* xmlSecTransformExecuteMethod execute; */
+
+    NULL,                                       /* void* reserved0; */
+    NULL,                                       /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformKWAes192GetKlass:
+ *
+ * The AES-192 kew wrapper transform klass.
+ *
+ * Returns: AES-192 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformKWAes192GetKlass(void) {
+    return(&xmlSecMSCryptoKWAes192Klass);
+}
+
+/*
+ * The AES-256 kew wrapper transform klass.
+ */
+static xmlSecTransformKlass xmlSecMSCryptoKWAes256Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
+    xmlSecMSCryptoBlockCipherSize,              /* xmlSecSize objSize */
+
+    xmlSecNameKWAes256,                         /* const xmlChar* name; */
+    xmlSecHrefKWAes256,                         /* const xmlChar* href; */
+    xmlSecTransformUsageEncryptionMethod,       /* xmlSecAlgorithmUsage usage; */
+
+    xmlSecMSCryptoBlockCipherInitialize,        /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecMSCryptoBlockCipherFinalize,          /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
+    xmlSecMSCryptoBlockCipherSetKeyReq,         /* xmlSecTransformSetKeyMethod setKeyReq; */
+    xmlSecMSCryptoKWAesSetKey,                  /* xmlSecTransformSetKeyMethod setKey; */
+    NULL,                                       /* xmlSecTransformValidateMethod validate; */
+    xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                           /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecMSCryptoKWAesExecute,                 /* xmlSecTransformExecuteMethod execute; */
+
+    NULL,                                       /* void* reserved0; */
+    NULL,                                       /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformKWAes256GetKlass:
+ *
+ * The AES-256 kew wrapper transform klass.
+ *
+ * Returns: AES-256 kew wrapper transform klass.
+ */
+xmlSecTransformId
+xmlSecMSCryptoTransformKWAes256GetKlass(void) {
+    return(&xmlSecMSCryptoKWAes256Klass);
+}
+
+#endif /* XMLSEC_NO_AES */
diff --git a/src/mscrypto/crypto.c b/src/mscrypto/crypto.c
index 3fe8d4f..adeaff4 100644
--- a/src/mscrypto/crypto.c
+++ b/src/mscrypto/crypto.c
@@ -121,6 +121,9 @@ xmlSecCryptoGetFunctions_mscrypto(void) {
     gXmlSecMSCryptoFunctions->transformAes128CbcGetKlass        = xmlSecMSCryptoTransformAes128CbcGetKlass;
     gXmlSecMSCryptoFunctions->transformAes192CbcGetKlass        = xmlSecMSCryptoTransformAes192CbcGetKlass;
     gXmlSecMSCryptoFunctions->transformAes256CbcGetKlass        = xmlSecMSCryptoTransformAes256CbcGetKlass;
+    gXmlSecMSCryptoFunctions->transformKWAes128GetKlass         = xmlSecMSCryptoTransformKWAes128GetKlass;
+    gXmlSecMSCryptoFunctions->transformKWAes192GetKlass         = xmlSecMSCryptoTransformKWAes192GetKlass;
+    gXmlSecMSCryptoFunctions->transformKWAes256GetKlass         = xmlSecMSCryptoTransformKWAes256GetKlass;
 #endif /* XMLSEC_NO_AES */
 
     /******************************* DES ********************************/
diff --git a/src/openssl/kw_aes.c b/src/openssl/kw_aes.c
index aa76a29..69e99af 100644
--- a/src/openssl/kw_aes.c
+++ b/src/openssl/kw_aes.c
@@ -189,25 +189,33 @@ xmlSecOpenSSLTransformKWAes256GetKlass(void) {
 }
 
 
-static int 
-xmlSecOpenSSLAesBlockEncryptCallback(const xmlSecByte * in, xmlSecByte * out, void * key) {
+static int 
+xmlSecOpenSSLAesBlockEncryptCallback(const xmlSecByte * in, xmlSecSize inSize,
+                                     xmlSecByte * out, xmlSecSize outSize,
+                                     void * key) {
     xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(inSize >= AES_BLOCK_SIZE, -1);
     xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(outSize >= AES_BLOCK_SIZE, -1);
     xmlSecAssert2(key != NULL, -1);
-
+
     AES_encrypt(in, out, (AES_KEY*)key);
-    return(0);
-}
-
-static int
-xmlSecOpenSSLAesBlockDecryptCallback(const xmlSecByte * in, xmlSecByte * out, void * key) {
+    return(AES_BLOCK_SIZE);
+}
+
+static int
+xmlSecOpenSSLAesBlockDecryptCallback(const xmlSecByte * in, xmlSecSize inSize,
+                                     xmlSecByte * out, xmlSecSize outSize,
+                                     void * key) {
     xmlSecAssert2(in != NULL, -1);
+    xmlSecAssert2(inSize >= AES_BLOCK_SIZE, -1);
     xmlSecAssert2(out != NULL, -1);
+    xmlSecAssert2(outSize >= AES_BLOCK_SIZE, -1);
     xmlSecAssert2(key != NULL, -1);
-
+
     AES_decrypt(in, out, (AES_KEY*)key);
-    return(0);
-}
+    return(AES_BLOCK_SIZE);
+}
 
 static int
 xmlSecOpenSSLKWAesInitialize(xmlSecTransformPtr transform) {
diff --git a/tests/testEnc.sh b/tests/testEnc.sh
index 2d3b2df..54d1ca8 100755
--- a/tests/testEnc.sh
+++ b/tests/testEnc.sh
@@ -69,10 +69,10 @@ execEncTest $res_success \
     "--keys-file $keysfile --binary-data $topfolder/aleksey-xmlenc-01/enc-aes256cbc-keyname.data" \
     "--keys-file $keysfile"
 
-execEncTest "aleksey-xmlenc-01/enc-des3cbc-keyname-content" \
-    "tripled$res_success \
+execEncTest $res_success \
     "" \
-    es-cbc" \
+    "aleksey-xmlenc-01/enc-des3cbc-keyname-content" \
+    "tripledes-cbc" \
     "--keys-file $topfolder/keys/keys.xml" \
     "--keys-file $keysfile --xml-data $topfolder/aleksey-xmlenc-01/enc-des3cbc-keyname-content.data --node-id Test" \
     "--keys-file $keysfile"
diff --git a/win32/mycfg.bat b/win32/mycfg.bat
index b1ec8ad..9af468e 100644
--- a/win32/mycfg.bat
+++ b/win32/mycfg.bat
@@ -11,7 +11,7 @@ REM
 SET PREFIX=C:\cygwin\home\local
 SET XMLSEC_INCLUDE=%PREFIX%\include;%PREFIX%\include\mozilla;%PREFIX%\include\mozilla\nspr;%PREFIX%\include\mozilla\nss;%MSSDK_INCLUDE%
 SET XMLSEC_LIB=%PREFIX%\lib;%MSSDK_LIB%
-SET XMLSEC_OPTIONS=static=no iconv=no debug=yes xslt=yes crypto=openssl unicode=yes
+SET XMLSEC_OPTIONS=static=no iconv=no debug=yes xslt=yes crypto=mscrypto,openssl unicode=yes
 
 del /F Makefile configure.txt
 cscript configure.js prefix=%PREFIX% %XMLSEC_OPTIONS% include=%XMLSEC_INCLUDE% lib=%XMLSEC_LIB% 



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