[xmlsec] enable SHA2 verification support; misc. cleanups in mscrypto



commit 6ca808b68ab4a0acc1e2c3ec9ad707720cc8c56d
Author: Aleksey Sanin <aleksey aleksey com>
Date:   Sat Apr 24 14:58:32 2010 -0700

    enable SHA2 verification support; misc. cleanups in mscrypto

 include/xmlsec/mscrypto/certkeys.h |    7 +-
 include/xmlsec/mscrypto/crypto.h   |  113 ++++++++++++
 include/xmlsec/mscrypto/symbols.h  |   14 +-
 src/mscrypto/certkeys.c            |  248 +++++++++++++---------------
 src/mscrypto/ciphers.c             |  106 +++++-------
 src/mscrypto/crypto.c              |  107 ++++++++++++
 src/mscrypto/csp_calg.h            |    7 +-
 src/mscrypto/digests.c             |  228 ++++++++++++++++++++++---
 src/mscrypto/signatures.c          |  328 ++++++++++++++++++++++++++++++------
 9 files changed, 877 insertions(+), 281 deletions(-)
---
diff --git a/include/xmlsec/mscrypto/certkeys.h b/include/xmlsec/mscrypto/certkeys.h
index c2b5763..ba3ec28 100644
--- a/include/xmlsec/mscrypto/certkeys.h
+++ b/include/xmlsec/mscrypto/certkeys.h
@@ -20,13 +20,18 @@ extern "C" {
 #include <xmlsec/keys.h>
 #include <xmlsec/transforms.h>
 
+
 XMLSEC_CRYPTO_EXPORT PCCERT_CONTEXT     xmlSecMSCryptoKeyDataGetCert    (xmlSecKeyDataPtr data);
 XMLSEC_CRYPTO_EXPORT HCRYPTKEY          xmlSecMSCryptoKeyDataGetKey     (xmlSecKeyDataPtr data,
                                                                          xmlSecKeyDataType type);
-XMLSEC_CRYPTO_EXPORT HCRYPTKEY  xmlSecMSCryptoKeyDataGetDecryptKey(xmlSecKeyDataPtr data);
+XMLSEC_CRYPTO_EXPORT HCRYPTKEY          xmlSecMSCryptoKeyDataGetDecryptKey(xmlSecKeyDataPtr data);
 XMLSEC_CRYPTO_EXPORT PCCERT_CONTEXT     xmlSecMSCryptoCertDup           (PCCERT_CONTEXT pCert);
 XMLSEC_CRYPTO_EXPORT xmlSecKeyDataPtr   xmlSecMSCryptoCertAdopt         (PCCERT_CONTEXT pCert, xmlSecKeyDataType type);
 
+XMLSEC_CRYPTO_EXPORT HCRYPTPROV         xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data);
+XMLSEC_CRYPTO_EXPORT DWORD              xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/include/xmlsec/mscrypto/crypto.h b/include/xmlsec/mscrypto/crypto.h
index dbba84e..56d6863 100644
--- a/include/xmlsec/mscrypto/crypto.h
+++ b/include/xmlsec/mscrypto/crypto.h
@@ -48,6 +48,38 @@ XMLSEC_CRYPTO_EXPORT LPWSTR             xmlSecMSCryptoConvertUtf8ToUnicode  (con
 XMLSEC_CRYPTO_EXPORT LPWSTR             xmlSecMSCryptoConvertLocaleToUnicode(const char* str);
 
 
+/**
+ * Crypto Providers
+ */
+
+/* We need to redefine both to ensure that we can pick the right one at runtime (instead of compile time) */
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE_A     "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE_W     L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
+#ifdef UNICODE
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE_W
+#else
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE_A
+#endif
+
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_A               "Microsoft Enhanced RSA and AES Cryptographic Provider"
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_W               L"Microsoft Enhanced RSA and AES Cryptographic Provider"
+#ifdef UNICODE
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_W
+#else
+#define XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_A
+#endif
+
+typedef struct _xmlSecMSCryptoProviderInfo {
+    LPCTSTR                 providerName;
+    DWORD                   providerType;
+} xmlSecMSCryptoProviderInfo;
+
+XMLSEC_CRYPTO_EXPORT HCRYPTPROV         xmlSecMSCryptoFindProvider      (const xmlSecMSCryptoProviderInfo * providers,
+                                                                         LPCTSTR pszContainer,
+                                                                         DWORD dwFlags,
+                                                                         BOOL bUseXmlSecContainer);
+
+
 
 /********************************************************************
  *
@@ -131,6 +163,36 @@ XMLSEC_CRYPTO_EXPORT xmlSecKeyDataId xmlSecMSCryptoKeyDataRsaGetKlass(void);
 XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformRsaSha1GetKlass(void);
 
 /**
+ * xmlSecMSCryptoTransformRsaSha256Id:
+ * 
+ * The RSA-SHA256 signature transform klass.
+ */
+
+#define xmlSecMSCryptoTransformRsaSha256Id     \
+       xmlSecMSCryptoTransformRsaSha256GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformRsaSha256GetKlass(void);
+
+/**
+ * xmlSecMSCryptoTransformRsaSha384Id:
+ * 
+ * The RSA-SHA384 signature transform klass.
+ */
+
+#define xmlSecMSCryptoTransformRsaSha384Id     \
+       xmlSecMSCryptoTransformRsaSha384GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformRsaSha384GetKlass(void);
+
+/**
+ * xmlSecMSCryptoTransformRsaSha512Id:
+ * 
+ * The RSA-SHA512 signature transform klass.
+ */
+
+#define xmlSecMSCryptoTransformRsaSha512Id     \
+       xmlSecMSCryptoTransformRsaSha512GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformRsaSha512GetKlass(void);
+
+/**
  * xmlSecMSCryptoTransformRsaPkcs1Id:
  *
  * The RSA PKCS1 key transport transform klass.
@@ -170,6 +232,57 @@ XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformSha1GetKlass(void)
 
 /********************************************************************
  *
+ * SHA256 transform
+ *
+ *******************************************************************/
+#ifndef XMLSEC_NO_SHA256
+
+/**
+ * xmlSecMSCryptoTransformSha256Id:
+ * 
+ * The SHA256 digest transform klass.
+ */
+#define xmlSecMSCryptoTransformSha256Id \
+       xmlSecMSCryptoTransformSha256GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformSha256GetKlass(void);
+#endif /* XMLSEC_NO_SHA256 */
+
+/********************************************************************
+ *
+ * SHA384 transform
+ *
+ *******************************************************************/
+#ifndef XMLSEC_NO_SHA384
+
+/**
+ * xmlSecMSCryptoTransformSha384Id:
+ * 
+ * The SHA384 digest transform klass.
+ */
+#define xmlSecMSCryptoTransformSha384Id \
+       xmlSecMSCryptoTransformSha384GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformSha384GetKlass(void);
+#endif /* XMLSEC_NO_SHA384 */
+
+/********************************************************************
+ *
+ * SHA512 transform
+ *
+ *******************************************************************/
+#ifndef XMLSEC_NO_SHA512
+
+/**
+ * xmlSecMSCryptoTransformSha512Id:
+ * 
+ * The SHA512 digest transform klass.
+ */
+#define xmlSecMSCryptoTransformSha512Id \
+       xmlSecMSCryptoTransformSha512GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformSha512GetKlass(void);
+#endif /* XMLSEC_NO_SHA512 */
+
+/********************************************************************
+ *
  * GOSTR3411_94 transform
  *
  *******************************************************************/
diff --git a/include/xmlsec/mscrypto/symbols.h b/include/xmlsec/mscrypto/symbols.h
index 580e8cf..bb54d16 100644
--- a/include/xmlsec/mscrypto/symbols.h
+++ b/include/xmlsec/mscrypto/symbols.h
@@ -36,11 +36,11 @@ extern "C" {
 #define xmlSecKeyDataAesId                      xmlSecMSCryptoKeyDataAesId
 #define xmlSecKeyDataDesId                      xmlSecMSCryptoKeyDataDesId
 #define xmlSecKeyDataDsaId                      xmlSecMSCryptoKeyDataDsaId
-#define xmlSecKeyDataGost2001Id     xmlSecMSCryptoKeyDataGost2001Id
+#define xmlSecKeyDataGost2001Id                 xmlSecMSCryptoKeyDataGost2001Id
 #define xmlSecKeyDataHmacId                     xmlSecMSCryptoKeyDataHmacId
 #define xmlSecKeyDataRsaId                      xmlSecMSCryptoKeyDataRsaId
 #define xmlSecKeyDataX509Id                     xmlSecMSCryptoKeyDataX509Id
-#define xmlSecKeyDataRawX509CertId  xmlSecMSCryptoKeyDataRawX509CertId
+#define xmlSecKeyDataRawX509CertId              xmlSecMSCryptoKeyDataRawX509CertId
 
 /**
  * Key data store ids
@@ -59,16 +59,22 @@ extern "C" {
 #define xmlSecTransformDes3CbcId                xmlSecMSCryptoTransformDes3CbcId
 #define xmlSecTransformKWDes3Id                 xmlSecMSCryptoTransformKWDes3Id
 #define xmlSecTransformDsaSha1Id                xmlSecMSCryptoTransformDsaSha1Id
-#define xmlSecTransformGost2001GostR3411_94Id           xmlSecMSCryptoTransformGost2001GostR3411_94Id
+#define xmlSecTransformGost2001GostR3411_94Id   xmlSecMSCryptoTransformGost2001GostR3411_94Id
 #define xmlSecTransformHmacMd5Id                xmlSecMSCryptoTransformHmacMd5Id
 #define xmlSecTransformHmacRipemd160Id          xmlSecMSCryptoTransformHmacRipemd160Id
 #define xmlSecTransformHmacSha1Id               xmlSecMSCryptoTransformHmacSha1Id
 #define xmlSecTransformRipemd160Id              xmlSecMSCryptoTransformRipemd160Id
 #define xmlSecTransformRsaSha1Id                xmlSecMSCryptoTransformRsaSha1Id
+#define xmlSecTransformRsaSha256Id              xmlSecMSCryptoTransformRsaSha256Id
+#define xmlSecTransformRsaSha384Id              xmlSecMSCryptoTransformRsaSha384Id
+#define xmlSecTransformRsaSha512Id              xmlSecMSCryptoTransformRsaSha512Id
 #define xmlSecTransformRsaPkcs1Id               xmlSecMSCryptoTransformRsaPkcs1Id
 #define xmlSecTransformRsaOaepId                xmlSecMSCryptoTransformRsaOaepId
 #define xmlSecTransformSha1Id                   xmlSecMSCryptoTransformSha1Id
-#define xmlSecTransformGostR3411_94Id                   xmlSecMSCryptoTransformGostR3411_94Id
+#define xmlSecTransformSha256Id                 xmlSecMSCryptoTransformSha256Id
+#define xmlSecTransformSha384Id                 xmlSecMSCryptoTransformSha384Id
+#define xmlSecTransformSha512Id                 xmlSecMSCryptoTransformSha512Id
+#define xmlSecTransformGostR3411_94Id           xmlSecMSCryptoTransformGostR3411_94Id
 
 /**
  * High level routines form xmlsec command line utility
diff --git a/src/mscrypto/certkeys.c b/src/mscrypto/certkeys.c
index 6fe3aa4..b76519e 100644
--- a/src/mscrypto/certkeys.c
+++ b/src/mscrypto/certkeys.c
@@ -42,7 +42,6 @@
 #endif
 #endif
 
-#define XMLSEC_CONTAINER_NAME "xmlsec-key-container"
 
 /**************************************************************************
  *
@@ -84,17 +83,16 @@ struct _mscrypt_prov {
  */
 struct _xmlSecMSCryptoKeyDataCtx {
 #ifndef XMLSEC_MSCRYPTO_NT4
-    HCRYPTPROV          hProv;
-    BOOL                    fCallerFreeProv;
-    HCRYPTKEY           hKey;
+    HCRYPTPROV                          hProv;
+    BOOL                                fCallerFreeProv;
+    HCRYPTKEY                           hKey;
 #else /* XMLSEC_MSCRYPTO_NT4 */
-        struct _mscrypt_prov* p_prov ;
-    struct _mscrypt_key*  p_key ;
+    struct _mscrypt_prov*               p_prov ;
+    struct _mscrypt_key*                p_key ;
 #endif /* XMLSEC_MSCRYPTO_NT4 */
-    PCCERT_CONTEXT      pCert;
-    LPCTSTR                 providerName;
-    DWORD                   providerType;
-    DWORD                   dwKeySpec;
+    PCCERT_CONTEXT                      pCert;
+    const xmlSecMSCryptoProviderInfo  * providers;
+    DWORD                               dwKeySpec;
     xmlSecKeyDataType   type;
 };
 
@@ -155,6 +153,7 @@ xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xm
     return(0);
 }
 
+
 /******************************** Key *****************************************/
 #define xmlSecMSCryptoKeyDataCtxGetKey(ctx)            ((ctx)->hKey)
 
@@ -444,7 +443,7 @@ xmlSecMSCryptoKeyDataAdoptCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT pCert, xmlS
         BOOL fCallerFreeProv = FALSE;
 
         if (!CryptAcquireCertificatePrivateKey(pCert,
-                                               CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
+                                               CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
                                                NULL,
                                                &hProv,
                                                &(ctx->dwKeySpec),
@@ -455,31 +454,29 @@ xmlSecMSCryptoKeyDataAdoptCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT pCert, xmlS
                             XMLSEC_ERRORS_R_CRYPTO_FAILED,
                             XMLSEC_ERRORS_NO_MESSAGE);
                 return(-1);
-            }
+        }
         xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv);
     } else if((type & xmlSecKeyDataTypePublic) != 0){
-        HCRYPTPROV hProv = 0;
-        if (!CryptAcquireContext(&hProv,
-                                    NULL,
-                                    NULL, /* ctx->providerName, */
-                                    ctx->providerType,
-                                    CRYPT_VERIFYCONTEXT)) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                            NULL,
-                            "CryptAcquireContext",
-                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                            XMLSEC_ERRORS_NO_MESSAGE);
-                return(-1);
-            }
-        xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, TRUE);
-            ctx->dwKeySpec = 0;
-    } else {
+        HCRYPTPROV hProv;
+
+        hProv = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, FALSE);
+        if (hProv == 0) {
             xmlSecError(XMLSEC_ERRORS_HERE,
                         NULL,
-                        NULL,
+                        "xmlSecMSCryptoFindProvider",
                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                        "Unsupported keytype");
+                        XMLSEC_ERRORS_NO_MESSAGE);
             return(-1);
+        }
+        xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, TRUE);
+        ctx->dwKeySpec = 0;
+    } else {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    NULL,
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "Unsupported keytype");
+        return(-1);
     }
 
     /* CryptImportPublicKeyInfo is only needed when a real key handle
@@ -609,6 +606,14 @@ xmlSecMSCryptoKeyDataGetCert(xmlSecKeyDataPtr data) {
     return(xmlSecMSCryptoKeyDataCtxGetCert(ctx));
 }
 
+/**
+ * xmlSecMSCryptoKeyDataGetMSCryptoProvider:
+ * @data:              the key data 
+ *
+ * Gets crypto provider handle
+ *
+ * Returns the crypto provider handler or 0 if there is an error.
+ */
 HCRYPTPROV
 xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data) {
     xmlSecMSCryptoKeyDataCtxPtr ctx;
@@ -622,6 +627,14 @@ xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data) {
     return(xmlSecMSCryptoKeyDataCtxGetProvider(ctx));
 }
 
+/**
+ * xmlSecMSCryptoKeyDataGetMSCryptoKeySpec:
+ * @data:              the key data 
+ *
+ * Gets key spec info.
+ *
+ * Returns the key spec info from key data
+ */
 DWORD
 xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data) {
     xmlSecMSCryptoKeyDataCtxPtr ctx;
@@ -679,8 +692,7 @@ xmlSecMSCryptoKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
     }
 
     ctxDst->dwKeySpec       = ctxSrc->dwKeySpec;
-    ctxDst->providerName    = ctxSrc->providerName;
-    ctxDst->providerType    = ctxSrc->providerType;
+    ctxDst->providers       = ctxSrc->providers;
     ctxDst->type            = ctxSrc->type;
 
     return(0);
@@ -985,6 +997,19 @@ static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataRsaKlass = {
     NULL,                                       /* void* reserved1; */
 };
 
+/* Ordered list of providers to search for algorithm implementation using 
+ * xmlSecMSCryptoFindProvider() function
+ * 
+ * MUST END with { NULL, 0 } !!! 
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Rsa[] = {
+    { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV,    PROV_RSA_AES},      
+    { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE,       PROV_RSA_AES },    
+    { MS_STRONG_PROV,               PROV_RSA_FULL }, 
+    { MS_ENHANCED_PROV,             PROV_RSA_FULL }, 
+    { NULL, 0 }
+};
+
 /**
  * xmlSecMSCryptoKeyDataRsaGetKlass:
  *
@@ -1008,9 +1033,7 @@ xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
     xmlSecAssert2(ctx != NULL, -1);
 
-    ctx->providerName = MS_ENHANCED_PROV;
-    ctx->providerType = PROV_RSA_FULL;
-
+    ctx->providers = xmlSecMSCryptoProviderInfo_Rsa;
     return(0);
 }
 
@@ -1197,26 +1220,16 @@ xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
     memcpy(modulusBlob, xmlSecBnGetData(&modulus), xmlSecBnGetSize(&modulus));
 
     /* Now that we have the blob, import */
-    if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) {
-        if(NTE_BAD_KEYSET == GetLastError()) {
-            if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                            xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
-                            "CryptAcquireContext",
-                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                            XMLSEC_ERRORS_NO_MESSAGE);
-                goto done;
-            }
-        } else {
-            xmlSecError(XMLSEC_ERRORS_HERE,
-                        xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
-                        "CryptAcquireContext",
-                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                        XMLSEC_ERRORS_NO_MESSAGE);
-            goto done;
-        }
+    hProv = xmlSecMSCryptoFindProvider(xmlSecMSCryptoProviderInfo_Rsa, NULL, 0, TRUE);
+    if(hProv == 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                    "xmlSecMSCryptoFindProvider",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        goto done;
     }
-
+    
     if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
@@ -1469,26 +1482,15 @@ xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits,
     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
     xmlSecAssert2(ctx != NULL, -1);
 
-    if (!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, MS_STRONG_PROV, PROV_RSA_FULL, 0)) {
-        if (NTE_BAD_KEYSET == GetLastError()) {
-            if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                            xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
-                            "CryptAcquireContext",
-                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                            XMLSEC_ERRORS_NO_MESSAGE);
-
-                return(-1);
-            }
-        } else {
-            xmlSecError(XMLSEC_ERRORS_HERE,
-                            xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
-                            "CryptAcquireContext",
-                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                            XMLSEC_ERRORS_NO_MESSAGE);
-
-            return(-1);
-        }
+    /* get provider */
+    hProv = xmlSecMSCryptoFindProvider(xmlSecMSCryptoProviderInfo_Rsa, NULL, 0, TRUE);
+    if(hProv == 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecMSCryptoFindProvider",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        goto done;
     }
 
     dwKeySpec = AT_KEYEXCHANGE | AT_SIGNATURE;
@@ -1696,6 +1698,17 @@ static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataDsaKlass = {
     NULL,                               /* void* reserved1; */
 };
 
+/* Ordered list of providers to search for algorithm implementation using 
+ * xmlSecMSCryptoFindProvider() function
+ * 
+ * MUST END with { NULL, 0 } !!! 
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Dss[] = {
+    { MS_DEF_DSS_PROV,              PROV_DSS }, 
+    { NULL, 0 }
+};
+
+
 /**
  * xmlSecMSCryptoKeyDataDsaGetKlass:
  *
@@ -1720,9 +1733,7 @@ xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
     xmlSecAssert2(ctx != NULL, -1);
 
-    ctx->providerName = MS_DEF_DSS_PROV;
-    ctx->providerType = PROV_DSS;
-
+    ctx->providers = xmlSecMSCryptoProviderInfo_Dss;
     return(0);
 }
 
@@ -2049,24 +2060,14 @@ xmlSecMSCryptoKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
     memset(seed, 0, sizeof(*seed));
     seed->counter = 0xFFFFFFFF; /* SEED Counter set to 0xFFFFFFFF will cause seed to be ignored */
 
-    if (!CryptAcquireContext(&hProv, NULL, MS_DEF_DSS_PROV, PROV_DSS, 0)) {
-        if (NTE_BAD_KEYSET == GetLastError()) {
-            if (!CryptAcquireContext(&hProv, NULL, MS_DEF_DSS_PROV, PROV_DSS, CRYPT_NEWKEYSET)) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                            xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
-                            "CryptAcquireContext",
-                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                            XMLSEC_ERRORS_NO_MESSAGE);
-                goto done;
-            }
-        } else {
-            xmlSecError(XMLSEC_ERRORS_HERE,
-                        xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
-                        "CryptAcquireContext",
-                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                        XMLSEC_ERRORS_NO_MESSAGE);
-            goto done;
-        }
+    hProv = xmlSecMSCryptoFindProvider(xmlSecMSCryptoProviderInfo_Dss, NULL, 0, TRUE);
+    if(hProv == 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                    "xmlSecMSCryptoFindProvider",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        goto done;
     }
 
     /* import the key blob */
@@ -2380,24 +2381,14 @@ xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xml
 
     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
 
-    if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, ctx->providerName, ctx->providerType, 0)) {
-            if (NTE_BAD_KEYSET == GetLastError()) {
-                if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, ctx->providerName, ctx->providerType, CRYPT_NEWKEYSET)) {
-                        xmlSecError(XMLSEC_ERRORS_HERE,
-                                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
-                                    "CryptAcquireContext",
-                                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                                    XMLSEC_ERRORS_NO_MESSAGE);
-                        return(-1);
-                }
-            } else {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                            xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
-                            "CryptAcquireContext",
-                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                            XMLSEC_ERRORS_NO_MESSAGE);
-                return(-1);
-            }
+    hProv = xmlSecMSCryptoFindProvider(ctx->providers, NULL, 0, TRUE);
+    if(hProv == 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecMSCryptoFindProvider",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
     }
 
     dwKeySpec = AT_SIGNATURE;
@@ -2539,6 +2530,17 @@ static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataGost2001Klass = {
     NULL,                               /* void* reserved1; */
 };
 
+/* Ordered list of providers to search for algorithm implementation using 
+ * xmlSecMSCryptoFindProvider() function
+ * 
+ * MUST END with { NULL, 0 } !!! 
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Gost[] = {
+    { MAGPRO_CSP,                   PROV_MAGPRO_GOST }, 
+    { CRYPTOPRO_CSP,                PROV_CRYPTOPRO_GOST }, 
+    { NULL, 0 }
+};
+
 /**
  * xmlSecMSCryptoKeyDataGost2001GetKlass:
  *
@@ -2555,7 +2557,6 @@ xmlSecMSCryptoKeyDataGost2001GetKlass(void) {
 static int
 xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data) {
     xmlSecMSCryptoKeyDataCtxPtr ctx;
-    HCRYPTPROV tmp_ctx = 0;
 
     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), xmlSecKeyDataTypeUnknown);
 
@@ -2564,24 +2565,7 @@ xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data) {
     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
     xmlSecAssert2(ctx != NULL, -1);
 
-    /* GOST Algorithm is provided by several CSP's, so we try to find any installed */
-    if (CryptAcquireContext(&tmp_ctx, NULL, NULL, PROV_MAGPRO_GOST, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
-      ctx->providerName = "MagPro CSP";
-      ctx->providerType = PROV_MAGPRO_GOST;
-    } else {
-      if (CryptAcquireContext(&tmp_ctx, NULL, NULL, PROV_CRYPTOPRO_GOST, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
-        ctx->providerName = "CryptoPro CSP";
-        ctx->providerType = PROV_CRYPTOPRO_GOST;
-      } else {
-          xmlSecError(XMLSEC_ERRORS_HERE,
-                      xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
-                      "xmlSecMSCryptoKeyDataGost2001Initialize",
-                      XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                      XMLSEC_ERRORS_NO_MESSAGE);
-                    return -1;
-     }
-    }
-    CryptReleaseContext(tmp_ctx, 0);
+    ctx->providers = xmlSecMSCryptoProviderInfo_Gost;
     return(0);
 }
 
diff --git a/src/mscrypto/ciphers.c b/src/mscrypto/ciphers.c
index 54b8321..948d496 100644
--- a/src/mscrypto/ciphers.c
+++ b/src/mscrypto/ciphers.c
@@ -25,9 +25,6 @@
 #  include "xmlsec-mingw.h"
 #endif
 
-#ifndef MS_ENH_RSA_AES_PROV_PROTO
-#define MS_ENH_RSA_AES_PROV_PROTO "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
-#endif /* MS_ENH_RSA_AES_PROV_PROTO */
 
 static BOOL xmlSecMSCryptoCreatePrivateExponentOneKey   (HCRYPTPROV hProv,
                                                          HCRYPTKEY *hPrivateKey);
@@ -46,17 +43,16 @@ static BOOL xmlSecMSCryptoImportPlainSessionBlob        (HCRYPTPROV hProv,
 typedef struct _xmlSecMSCryptoBlockCipherCtx            xmlSecMSCryptoBlockCipherCtx,
                                                         *xmlSecMSCryptoBlockCipherCtxPtr;
 struct _xmlSecMSCryptoBlockCipherCtx {
-    ALG_ID              algorithmIdentifier;
-    int                 mode;
-    HCRYPTPROV          cryptProvider;
-    HCRYPTKEY           cryptKey;
-    HCRYPTKEY           pubPrivKey;
-    xmlSecKeyDataId     keyId;
-    LPCTSTR             providerName;
-    int                 providerType;
-    int                 keyInitialized;
-    int                 ctxInitialized;
-    xmlSecSize          keySize;
+    ALG_ID                              algorithmIdentifier;
+    int                                 mode;
+    HCRYPTPROV                          cryptProvider;
+    HCRYPTKEY                           cryptKey;
+    HCRYPTKEY                           pubPrivKey;
+    xmlSecKeyDataId                     keyId;
+    const xmlSecMSCryptoProviderInfo  * providers;
+    int                                 keyInitialized;
+    int                                 ctxInitialized;
+    xmlSecSize                          keySize;
 };
 /* function declarations */
 static int      xmlSecMSCryptoBlockCipherCtxUpdate      (xmlSecMSCryptoBlockCipherCtxPtr ctx,
@@ -469,6 +465,29 @@ static int      xmlSecMSCryptoBlockCipherExecute        (xmlSecTransformPtr tran
                                                          xmlSecTransformCtxPtr transformCtx);
 static int      xmlSecMSCryptoBlockCipherCheckId        (xmlSecTransformPtr transform);
 
+
+
+/* Ordered list of providers to search for algorithm implementation using 
+ * xmlSecMSCryptoFindProvider() function
+ * 
+ * MUST END with { NULL, 0 } !!! 
+ */
+#ifndef XMLSEC_NO_DES
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Des[] = {
+    { MS_STRONG_PROV,               PROV_RSA_FULL }, 
+    { MS_ENHANCED_PROV,             PROV_RSA_FULL }, 
+    { NULL, 0 }
+};
+#endif /* XMLSEC_NO_DES */
+
+#ifndef XMLSEC_NO_AES
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Aes[] = {
+    { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV,    PROV_RSA_AES},      
+    { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE,       PROV_RSA_AES },
+    { NULL, 0 }
+};
+#endif /* XMLSEC_NO_AES */
+
 static int
 xmlSecMSCryptoBlockCipherCheckId(xmlSecTransformPtr transform) {
 #ifndef XMLSEC_NO_DES
@@ -505,8 +524,7 @@ xmlSecMSCryptoBlockCipherInitialize(xmlSecTransformPtr transform) {
     if(transform->id == xmlSecMSCryptoTransformDes3CbcId) {
         ctx->algorithmIdentifier    = CALG_3DES;
         ctx->keyId                  = xmlSecMSCryptoKeyDataDesId;
-        ctx->providerName           = MS_ENHANCED_PROV;
-        ctx->providerType           = PROV_RSA_FULL;
+        ctx->providers              = xmlSecMSCryptoProviderInfo_Des;
         ctx->keySize                = 24;
     } else
 #endif /* XMLSEC_NO_DES */
@@ -515,25 +533,22 @@ xmlSecMSCryptoBlockCipherInitialize(xmlSecTransformPtr transform) {
     if(transform->id == xmlSecMSCryptoTransformAes128CbcId) {
         ctx->algorithmIdentifier    = CALG_AES_128;
         ctx->keyId                  = xmlSecMSCryptoKeyDataAesId;
-        ctx->providerName           = MS_ENH_RSA_AES_PROV_PROTO;
-        ctx->providerType           = PROV_RSA_AES;
+        ctx->providers              = xmlSecMSCryptoProviderInfo_Aes;
         ctx->keySize                = 16;
     } else if(transform->id == xmlSecMSCryptoTransformAes192CbcId) {
         ctx->algorithmIdentifier    = CALG_AES_192;
         ctx->keyId                  = xmlSecMSCryptoKeyDataAesId;
-        ctx->providerName           = MS_ENH_RSA_AES_PROV_PROTO;
-        ctx->providerType           = PROV_RSA_AES;
+        ctx->providers              = xmlSecMSCryptoProviderInfo_Aes;
         ctx->keySize                = 24;
     } else if(transform->id == xmlSecMSCryptoTransformAes256CbcId) {
         ctx->algorithmIdentifier    = CALG_AES_256;
         ctx->keyId                  = xmlSecMSCryptoKeyDataAesId;
-        ctx->providerName           = MS_ENH_RSA_AES_PROV_PROTO;
-        ctx->providerType           = PROV_RSA_AES;
+        ctx->providers              = xmlSecMSCryptoProviderInfo_Aes;
         ctx->keySize                = 32;
     } else
 #endif /* XMLSEC_NO_AES */
 
-    if(1) {
+    {
         xmlSecError(XMLSEC_ERRORS_HERE,
             xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
             NULL,
@@ -542,44 +557,15 @@ xmlSecMSCryptoBlockCipherInitialize(xmlSecTransformPtr transform) {
         return(-1);
     }
 
-    if(!CryptAcquireContext(&ctx->cryptProvider, NULL /*"xmlSecMSCryptoTempContainer"*/,
-                             ctx->providerName, ctx->providerType, 0)) {
-        DWORD dwError = GetLastError();
-        if (dwError == NTE_EXISTS) {
-            if (!CryptAcquireContext(&ctx->cryptProvider, "xmlSecMSCryptoTempContainer",
-                                     ctx->providerName, ctx->providerType, 0)) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                            xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
-                            "CryptAcquireContext",
-                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                            XMLSEC_ERRORS_NO_MESSAGE);
-
-                return(-1);
-            }
-        } else if (dwError == NTE_BAD_KEYSET) {
-          /* This error can indicate that a newly installed provider
-           * does not have a usable key container yet. It needs to be
-           * created, and then we have to try again CryptAcquireContext.
-           * This is also referenced in
-           * http://www.microsoft.com/mind/0697/crypto.asp (inituser)
-           */
-            if(!CryptAcquireContext(&ctx->cryptProvider, NULL, ctx->providerName,
-                                    ctx->providerType, CRYPT_NEWKEYSET)) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
+    ctx->cryptProvider = xmlSecMSCryptoFindProvider(ctx->providers, NULL, 0, TRUE);
+    if(ctx->cryptProvider == 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
-                    "CryptAcquireContext",
-                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    "xmlSecMSCryptoFindProvider",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                     XMLSEC_ERRORS_NO_MESSAGE);
-                return(-1);
-            }
-        } else {
-            xmlSecError(XMLSEC_ERRORS_HERE,
-                        xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
-                        "CryptAcquireContext",
-                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                        XMLSEC_ERRORS_NO_MESSAGE);
-            return(-1);
-        }
+
+        return(-1);
     }
 
     /* Create dummy key to be able to import plain session keys */
@@ -615,8 +601,6 @@ xmlSecMSCryptoBlockCipherFinalize(xmlSecTransformPtr transform) {
     }
     if (ctx->cryptProvider) {
         CryptReleaseContext(ctx->cryptProvider, 0);
-        CryptAcquireContext(&ctx->cryptProvider, "xmlSecMSCryptoTempContainer",
-                            MS_ENHANCED_PROV, ctx->providerType, CRYPT_DELETEKEYSET);
     }
 
     memset(ctx, 0, sizeof(xmlSecMSCryptoBlockCipherCtx));
diff --git a/src/mscrypto/crypto.c b/src/mscrypto/crypto.c
index 73eb900..82e46dc 100644
--- a/src/mscrypto/crypto.c
+++ b/src/mscrypto/crypto.c
@@ -28,6 +28,8 @@
 #  include "xmlsec-mingw.h"
 #endif
 
+#define XMLSEC_CONTAINER_NAME "xmlsec-key-container"
+
 static xmlSecCryptoDLFunctionsPtr gXmlSecMSCryptoFunctions = NULL;
 
 /**
@@ -68,6 +70,17 @@ xmlSecCryptoGetFunctions_mscrypto(void) {
 
 #ifndef XMLSEC_NO_RSA
     gXmlSecMSCryptoFunctions->keyDataRsaGetKlass                = xmlSecMSCryptoKeyDataRsaGetKlass;
+
+#ifndef XMLSEC_NO_SHA256
+    gXmlSecMSCryptoFunctions->transformRsaSha256GetKlass       = xmlSecMSCryptoTransformRsaSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+#ifndef XMLSEC_NO_SHA384
+    gXmlSecMSCryptoFunctions->transformRsaSha384GetKlass       = xmlSecMSCryptoTransformRsaSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+#ifndef XMLSEC_NO_SHA512
+    gXmlSecMSCryptoFunctions->transformRsaSha512GetKlass       = xmlSecMSCryptoTransformRsaSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
+
 #endif /* XMLSEC_NO_RSA */
 
 #ifndef XMLSEC_NO_DSA
@@ -119,6 +132,15 @@ xmlSecCryptoGetFunctions_mscrypto(void) {
 #ifndef XMLSEC_NO_SHA1
     gXmlSecMSCryptoFunctions->transformSha1GetKlass             = xmlSecMSCryptoTransformSha1GetKlass;
 #endif /* XMLSEC_NO_SHA1 */
+#ifndef XMLSEC_NO_SHA256    
+    gXmlSecMSCryptoFunctions->transformSha256GetKlass          = xmlSecMSCryptoTransformSha256GetKlass;
+#endif /* XMLSEC_NO_SHA256 */
+#ifndef XMLSEC_NO_SHA384    
+    gXmlSecMSCryptoFunctions->transformSha384GetKlass          = xmlSecMSCryptoTransformSha384GetKlass;
+#endif /* XMLSEC_NO_SHA384 */
+#ifndef XMLSEC_NO_SHA512    
+    gXmlSecMSCryptoFunctions->transformSha512GetKlass          = xmlSecMSCryptoTransformSha512GetKlass;
+#endif /* XMLSEC_NO_SHA512 */
 
 #ifndef XMLSEC_NO_GOST
     gXmlSecMSCryptoFunctions->transformGostR3411_94GetKlass             = xmlSecMSCryptoTransformGostR3411_94GetKlass;
@@ -423,6 +445,91 @@ xmlSecMSCryptoConvertLocaleToUnicode(const char* str) {
         return(res);
 }
 
+/**
+ * xmlSecMSCryptoFindProvider:
+ * @providers:           the pointer to list of providers, last provider should have NULL for name.
+ * @pszContainer:        the container name for CryptAcquireContext call
+ * @dwFlags:             the flags for CryptAcquireContext call
+ * @bUseXmlSecContainer: the flag to indicate whether we should try to use XmlSec container if default fails
+ *
+ * Finds the first provider from the list
+ *
+ * Returns: provider handle on success or NULL for error.
+ */
+HCRYPTPROV 
+xmlSecMSCryptoFindProvider(const xmlSecMSCryptoProviderInfo * providers, 
+                           LPCTSTR pszContainer, 
+                           DWORD dwFlags, 
+                           BOOL bUseXmlSecContainer) 
+{
+    HCRYPTPROV res = 0;
+    DWORD dwLastError;
+    BOOL ret;
+    int ii;
+
+    xmlSecAssert2(providers != NULL, 0);
+    
+    for(ii = 0; (res == 0) && (providers[ii].providerName != NULL) && (providers[ii].providerType != 0); ++ii) {
+        /* first try */
+        ret = CryptAcquireContext(&res, 
+                    pszContainer, 
+                    providers[ii].providerName, 
+                    providers[ii].providerType, 
+                    dwFlags);
+        if((ret == TRUE) && (res != 0)) {
+            return (res);
+        } 
+            
+        /* check errors */
+        dwLastError = GetLastError();
+        switch(dwLastError) {
+        case NTE_BAD_KEYSET:
+            /* This error can indicate that a newly installed provider
+             * does not have a usable key container yet. It needs to be
+             * created, and then we have to try again CryptAcquireContext.
+             * This is also referenced in
+             * http://www.microsoft.com/mind/0697/crypto.asp (inituser)
+             */
+            ret = CryptAcquireContext(&res, 
+                        pszContainer, 
+                        providers[ii].providerName, 
+                        providers[ii].providerType, 
+                        CRYPT_NEWKEYSET | dwFlags);
+            if((ret == TRUE) && (res != 0)) {
+                return (res);
+            }
+            break;
+
+        case NTE_EXISTS:
+            /* If we can, try our container */
+            if(bUseXmlSecContainer == TRUE) {
+                ret = CryptAcquireContext(&res, 
+                            XMLSEC_CONTAINER_NAME, 
+                            providers[ii].providerName, 
+                            providers[ii].providerType, 
+                            CRYPT_NEWKEYSET | dwFlags);
+                if((ret == TRUE) && (res != 0)) {
+                    /* ALEKSEY TODO - NEED TO DELETE ALL THE TEMP CONTEXTS ON SHUTDOWN 
+
+                        CryptAcquireContext(&tmp, XMLSEC_CONTAINER_NAME,
+                            providers[ii].providerName, 
+                            providers[ii].providerType, 
+                            CRYPT_DELETEKEYSET);
+
+                     */
+                    return (res);
+                }
+            }                    
+            break;
+
+        default:
+            /* ignore */
+            break;
+        }
+    }
+
+    return (0);
+}
 
 
 
diff --git a/src/mscrypto/csp_calg.h b/src/mscrypto/csp_calg.h
index c780ecb..c100984 100644
--- a/src/mscrypto/csp_calg.h
+++ b/src/mscrypto/csp_calg.h
@@ -72,10 +72,11 @@
  *
  * @{
  */
+#define MAGPRO_CSP                  "MagPro CSP"
+#define PROV_MAGPRO_GOST            501
 
-#define PROV_MAGPRO_GOST 501
-
-#define PROV_CRYPTOPRO_GOST 75
+#define CRYPTOPRO_CSP               "CryptoPro CSP"
+#define PROV_CRYPTOPRO_GOST         75
 
 /*! @} */
 /*! \defgroup PP_MAGPRO PP_MAGPRO
diff --git a/src/mscrypto/digests.c b/src/mscrypto/digests.c
index 5c4a074..b237b69 100644
--- a/src/mscrypto/digests.c
+++ b/src/mscrypto/digests.c
@@ -29,6 +29,7 @@ typedef struct _xmlSecMSCryptoDigestCtx xmlSecMSCryptoDigestCtx, *xmlSecMSCrypto
 struct _xmlSecMSCryptoDigestCtx {
     HCRYPTPROV      provider;
     ALG_ID          alg_id;
+    const xmlSecMSCryptoProviderInfo  * providers;
     HCRYPTHASH      mscHash;
     unsigned char   dgst[MSCRYPTO_MAX_HASH_SIZE];
     size_t          dgstSize;   /* dgst size in bytes */
@@ -59,6 +60,25 @@ static int      xmlSecMSCryptoDigestExecute     (xmlSecTransformPtr transform,
 static int      xmlSecMSCryptoDigestCheckId     (xmlSecTransformPtr transform);
 
 
+/* Ordered list of providers to search for algorithm implementation using 
+ * xmlSecMSCryptoFindProvider() function
+ * 
+ * MUST END with { NULL, 0 } !!! 
+ */
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Sha[] = {
+    { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV,    PROV_RSA_AES},      
+    { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE,       PROV_RSA_AES },    
+    { MS_STRONG_PROV,               PROV_RSA_FULL }, 
+    { MS_ENHANCED_PROV,             PROV_RSA_FULL }, 
+    { NULL, 0 }
+};
+
+static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Gost[] = {
+    { MAGPRO_CSP,                   PROV_MAGPRO_GOST }, 
+    { CRYPTOPRO_CSP,                PROV_CRYPTOPRO_GOST }, 
+    { NULL, 0 }
+};
+
 static int
 xmlSecMSCryptoDigestCheckId(xmlSecTransformPtr transform) {
 #ifndef XMLSEC_NO_SHA1
@@ -67,6 +87,24 @@ xmlSecMSCryptoDigestCheckId(xmlSecTransformPtr transform) {
     }
 #endif /* XMLSEC_NO_SHA1 */
 
+#ifndef XMLSEC_NO_SHA256
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha256Id)) {
+        return(1);
+    }
+#endif /* XMLSEC_NO_SHA256 */    
+
+#ifndef XMLSEC_NO_SHA384
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha384Id)) {
+        return(1);
+    }
+#endif /* XMLSEC_NO_SHA384 */    
+
+#ifndef XMLSEC_NO_SHA512
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha512Id)) {
+        return(1);
+    }
+#endif /* XMLSEC_NO_SHA512 */    
+
 #ifndef XMLSEC_NO_GOST
     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGostR3411_94Id)) {
         return(1);
@@ -92,25 +130,35 @@ xmlSecMSCryptoDigestInitialize(xmlSecTransformPtr transform) {
 #ifndef XMLSEC_NO_SHA1
     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha1Id)) {
         ctx->alg_id = CALG_SHA;
+        ctx->providers = xmlSecMSCryptoProviderInfo_Sha;
     } else
 #endif /* XMLSEC_NO_SHA1 */
 
+#ifndef XMLSEC_NO_SHA256
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha256Id)) {
+        ctx->alg_id = CALG_SHA_256;
+        ctx->providers = xmlSecMSCryptoProviderInfo_Sha;
+    } else 
+#endif /* XMLSEC_NO_SHA256 */    
+
+#ifndef XMLSEC_NO_SHA384
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha384Id)) {
+        ctx->alg_id = CALG_SHA_384;
+        ctx->providers = xmlSecMSCryptoProviderInfo_Sha;
+    } else 
+#endif /* XMLSEC_NO_SHA384 */    
+
+#ifndef XMLSEC_NO_SHA512
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha512Id)) {
+        ctx->alg_id = CALG_SHA_512;
+        ctx->providers = xmlSecMSCryptoProviderInfo_Sha;
+    } else 
+#endif /* XMLSEC_NO_SHA512 */
+
 #ifndef XMLSEC_NO_GOST
     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGostR3411_94Id)) {
-                ctx->alg_id = CALG_MAGPRO_HASH_R3411_94;
-
-    /* TODO: Check what provider is best suited here.... */
-    if (!CryptAcquireContext(&ctx->provider, NULL, 0, PROV_MAGPRO_GOST, CRYPT_VERIFYCONTEXT)) {
-      if (!CryptAcquireContext(&ctx->provider, NULL, 0, PROV_CRYPTOPRO_GOST, CRYPT_VERIFYCONTEXT)) {
-        xmlSecError(XMLSEC_ERRORS_HERE,
-                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
-                    NULL,
-                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                    XMLSEC_ERRORS_NO_MESSAGE);
-        return(-1);
-    }
-    }
-    return(0);
+        ctx->alg_id = CALG_MAGPRO_HASH_R3411_94;
+        ctx->providers = xmlSecMSCryptoProviderInfo_Gost;
     } else
 #endif /* XMLSEC_NO_GOST*/
 
@@ -123,16 +171,14 @@ xmlSecMSCryptoDigestInitialize(xmlSecTransformPtr transform) {
         return(-1);
     }
 
-    /* TODO: Check what provider is best suited here.... */
-    if (!CryptAcquireContext(&ctx->provider, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
-        if (!CryptAcquireContext(&ctx->provider, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
-                    NULL,
-                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                    XMLSEC_ERRORS_NO_MESSAGE);
-                return(-1);
-        }
+    ctx->provider = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
+    if(ctx->provider == 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+            xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
+            "xmlSecMSCryptoFindProvider",
+            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+            XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
     }
 
     return(0);
@@ -230,7 +276,7 @@ xmlSecMSCryptoDigestExecute(xmlSecTransformPtr transform,
         if((ret == 0) || (ctx->mscHash == 0)) {
             xmlSecError(XMLSEC_ERRORS_HERE,
                         xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
-                        "CryptHashData",
+                        "CryptCreateHash",
                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
                         XMLSEC_ERRORS_NO_MESSAGE);
             return(-1);
@@ -367,6 +413,138 @@ xmlSecMSCryptoTransformSha1GetKlass(void) {
 }
 #endif /* XMLSEC_NO_SHA1 */
 
+#ifndef XMLSEC_NO_SHA256
+/******************************************************************************
+ *
+ * SHA256
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoSha256Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),              /* size_t klassSize */
+    xmlSecMSCryptoDigestSize,                  /* size_t objSize */
+
+    xmlSecNameSha256,                          /* const xmlChar* name; */
+    xmlSecHrefSha256,                          /* const xmlChar* href; */
+    xmlSecTransformUsageDigestMethod,          /* xmlSecTransformUsage usage; */
+    xmlSecMSCryptoDigestInitialize,            /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecMSCryptoDigestFinalize,              /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                      /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                      /* xmlSecTransformNodeWriteMethod writeNode; */
+    NULL,                                      /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+    NULL,                                      /* xmlSecTransformSetKeyMethod setKey; */
+    xmlSecMSCryptoDigestVerify,                        /* xmlSecTransformVerifyMethod verify; */
+    xmlSecTransformDefaultGetDataType,         /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,             /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,              /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                      /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                      /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecMSCryptoDigestExecute,               /* xmlSecTransformExecuteMethod execute; */    
+    NULL,                                      /* void* reserved0; */
+    NULL,                                      /* void* reserved1; */
+};
+
+/** 
+ * xmlSecMSCryptoTransformSha256GetKlass:
+ *
+ * SHA-256 digest transform klass.
+ *
+ * Returns pointer to SHA-256 digest transform klass.
+ */
+xmlSecTransformId 
+xmlSecMSCryptoTransformSha256GetKlass(void) {
+    return(&xmlSecMSCryptoSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/******************************************************************************
+ *
+ * SHA384
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoSha384Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),              /* size_t klassSize */
+    xmlSecMSCryptoDigestSize,                  /* size_t objSize */
+
+    xmlSecNameSha384,                          /* const xmlChar* name; */
+    xmlSecHrefSha384,                          /* const xmlChar* href; */
+    xmlSecTransformUsageDigestMethod,          /* xmlSecTransformUsage usage; */
+    xmlSecMSCryptoDigestInitialize,            /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecMSCryptoDigestFinalize,              /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                      /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                      /* xmlSecTransformNodeWriteMethod writeNode; */
+    NULL,                                      /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+    NULL,                                      /* xmlSecTransformSetKeyMethod setKey; */
+    xmlSecMSCryptoDigestVerify,                        /* xmlSecTransformVerifyMethod verify; */
+    xmlSecTransformDefaultGetDataType,         /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,             /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,              /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                      /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                      /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecMSCryptoDigestExecute,               /* xmlSecTransformExecuteMethod execute; */    
+    NULL,                                      /* void* reserved0; */
+    NULL,                                      /* void* reserved1; */
+};
+
+/** 
+ * xmlSecMSCryptoTransformSha384GetKlass:
+ *
+ * SHA-384 digest transform klass.
+ *
+ * Returns pointer to SHA-384 digest transform klass.
+ */
+xmlSecTransformId 
+xmlSecMSCryptoTransformSha384GetKlass(void) {
+    return(&xmlSecMSCryptoSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/******************************************************************************
+ *
+ * SHA512
+ *
+ *****************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoSha512Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),              /* size_t klassSize */
+    xmlSecMSCryptoDigestSize,                  /* size_t objSize */
+
+    xmlSecNameSha512,                          /* const xmlChar* name; */
+    xmlSecHrefSha512,                          /* const xmlChar* href; */
+    xmlSecTransformUsageDigestMethod,          /* xmlSecTransformUsage usage; */
+    xmlSecMSCryptoDigestInitialize,            /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecMSCryptoDigestFinalize,              /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                      /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                      /* xmlSecTransformNodeWriteMethod writeNode; */
+    NULL,                                      /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+    NULL,                                      /* xmlSecTransformSetKeyMethod setKey; */
+    xmlSecMSCryptoDigestVerify,                        /* xmlSecTransformVerifyMethod verify; */
+    xmlSecTransformDefaultGetDataType,         /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,             /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,              /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                      /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                      /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecMSCryptoDigestExecute,               /* xmlSecTransformExecuteMethod execute; */    
+    NULL,                                      /* void* reserved0; */
+    NULL,                                      /* void* reserved1; */
+};
+
+/** 
+ * xmlSecMSCryptoTransformSha512GetKlass:
+ *
+ * SHA-512 digest transform klass.
+ *
+ * Returns pointer to SHA-512 digest transform klass.
+ */
+xmlSecTransformId 
+xmlSecMSCryptoTransformSha512GetKlass(void) {
+    return(&xmlSecMSCryptoSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
 #ifndef XMLSEC_NO_GOST
 /******************************************************************************
  *
diff --git a/src/mscrypto/signatures.c b/src/mscrypto/signatures.c
index ee52800..a003e43 100644
--- a/src/mscrypto/signatures.c
+++ b/src/mscrypto/signatures.c
@@ -28,10 +28,6 @@
 #include <xmlsec/mscrypto/certkeys.h>
 #include <xmlsec/mscrypto/x509.h>
 
-/*FIXME: include header files*/
-extern HCRYPTPROV xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data);
-extern DWORD xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data);
-
 #if defined(__MINGW32__)
 #  include "xmlsec-mingw.h"
 #endif
@@ -97,6 +93,21 @@ static int xmlSecMSCryptoSignatureCheckId(xmlSecTransformPtr transform) {
     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
         return(1);
     }
+#ifndef XMLSEC_NO_SHA256
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) {
+       return(1);
+    }
+#endif /* XMLSEC_NO_SHA256 */
+#ifndef XMLSEC_NO_SHA384
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha384Id)) {
+       return(1);
+    }
+#endif /* XMLSEC_NO_SHA384 */
+#ifndef XMLSEC_NO_SHA512
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha512Id)) {
+       return(1);
+    }
+#endif /* XMLSEC_NO_SHA512 */
 #endif /* XMLSEC_NO_RSA */
 
     return(0);
@@ -118,6 +129,28 @@ static int xmlSecMSCryptoSignatureInitialize(xmlSecTransformPtr transform) {
         ctx->digestAlgId    = CALG_SHA1;
         ctx->keyId          = xmlSecMSCryptoKeyDataRsaId;
     } else
+
+#ifndef XMLSEC_NO_SHA256 
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) {
+        ctx->digestAlgId    = CALG_SHA_256;
+        ctx->keyId          = xmlSecMSCryptoKeyDataRsaId;
+    } else
+#endif /* XMLSEC_NO_SHA256 */ 
+
+#ifndef XMLSEC_NO_SHA384
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha384Id)) {
+        ctx->digestAlgId    = CALG_SHA_384;
+        ctx->keyId          = xmlSecMSCryptoKeyDataRsaId;
+    } else
+#endif /* XMLSEC_NO_SHA384 */ 
+
+#ifndef XMLSEC_NO_SHA512
+    if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha512Id)) {
+        ctx->digestAlgId    = CALG_SHA_512;
+        ctx->keyId          = xmlSecMSCryptoKeyDataRsaId;
+    } else
+#endif /* XMLSEC_NO_SHA512 */ 
+
 #endif /* XMLSEC_NO_RSA */
 
 #ifndef XMLSEC_NO_GOST
@@ -221,6 +254,21 @@ static int xmlSecMSCryptoSignatureSetKeyReq(xmlSecTransformPtr transform,  xmlSe
     return(0);
 }
 
+static int ConvertEndian(const xmlSecByte * src, xmlSecByte * dst, int size) {
+    BYTE * p;
+
+    xmlSecAssert2(src != NULL, -1);
+    xmlSecAssert2(dst != NULL, -1);
+    xmlSecAssert2(size > 0, -1);
+
+    p = dst + size - 1;
+    while (p >= dst) {
+        *(p--) = *(src++);
+    }
+
+    return (0);
+}
+
 
 static int xmlSecMSCryptoSignatureVerify(xmlSecTransformPtr transform,
                                          const xmlSecByte* data,
@@ -228,9 +276,9 @@ static int xmlSecMSCryptoSignatureVerify(xmlSecTransformPtr transform,
                                          xmlSecTransformCtxPtr transformCtx) {
     xmlSecMSCryptoSignatureCtxPtr ctx;
     xmlSecBuffer tmp;
+    xmlSecByte *tmpBuf;
     HCRYPTKEY hKey;
     DWORD dwError;
-    BYTE *tmpBuf, *j, *k, *l, *m;
     int ret;
 
     xmlSecAssert2(xmlSecMSCryptoSignatureCheckId(transform), -1);
@@ -259,30 +307,45 @@ static int xmlSecMSCryptoSignatureVerify(xmlSecTransformPtr transform,
 
     /* Reverse the sig - Windows stores integers as octet streams in little endian
      * order.  The I2OSP algorithm used by XMLDSig to store integers is big endian */
-    if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id)) {
-        j = (BYTE *)data;
-        k = (BYTE *)data + 20;
-        l = tmpBuf + 19;
-        m = tmpBuf + 39;
-        while (l >= tmpBuf) {
-            *l-- = *j++;
-            *m-- = *k++;
-        }
+#ifndef XMLSEC_NO_RSA
+    if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+        ConvertEndian(data, tmpBuf, dataSize);
+    } else 
+
+#ifndef XMLSEC_NO_SHA256
+    if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) {
+        ConvertEndian(data, tmpBuf, dataSize);
+    } else 
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+    if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha384Id)) {
+        ConvertEndian(data, tmpBuf, dataSize);
+    } else 
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+    if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha512Id)) {
+        ConvertEndian(data, tmpBuf, dataSize);
+    } else 
+#endif /* XMLSEC_NO_SHA512 */
+
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_DSA
+    if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id) && (dataSize == 40)) {
+        ConvertEndian(data, tmpBuf, 20);
+        ConvertEndian(data + 20, tmpBuf + 20, 20);
+    } else 
+#endif /*endif XMLSEC_NO_DSA */
+
 #ifndef XMLSEC_NO_GOST
-    } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
-        j = (BYTE *)data;
-        l = tmpBuf + dataSize - 1;
-        while (l >= tmpBuf) {
-            *l-- = *j++;
-        }
-#endif /*ndef XMLSEC_NO_GOST*/
-    } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
-        j = (BYTE *)data;
-        l = tmpBuf + dataSize - 1;
-        while (l >= tmpBuf) {
-            *l-- = *j++;
-        }
-    } else {
+    if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
+        ConvertEndian(data, tmpBuf, dataSize);
+    } else 
+#endif /* XMLSEC_NO_GOST*/
+
+    {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                     NULL,
@@ -333,6 +396,8 @@ static int xmlSecMSCryptoSignatureVerify(xmlSecTransformPtr transform,
     return(0);
 }
 
+
+
 static int
 xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
     xmlSecMSCryptoSignatureCtxPtr ctx;
@@ -372,6 +437,7 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra
                         XMLSEC_ERRORS_NO_MESSAGE);
             return (-1);
         }
+
         if (!CryptCreateHash(hProv, ctx->digestAlgId, 0, 0, &(ctx->mscHash))) {
             xmlSecError(XMLSEC_ERRORS_HERE,
                         NULL,
@@ -460,34 +526,48 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra
             outBuf = xmlSecBufferGetData(out);
             xmlSecAssert2(outBuf != NULL, -1);
 
-            /* Now encode into a signature block,
-             * convert signature value to big endian */
-            if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id)) {
-                i = tmpBuf;
-                j = tmpBuf + 20;
-                m = outBuf + 19;
-                n = outBuf + 39;
-                while (m >= outBuf) {
-                    *m-- = *i++;
-                    *n-- = *j++;
-                }
+            /* Reverse the sig - Windows stores integers as octet streams in little endian
+             * order.  The I2OSP algorithm used by XMLDSig to store integers is big endian */
+#ifndef XMLSEC_NO_RSA
+            if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
+                ConvertEndian(tmpBuf, outBuf, outSize);
+            } else 
+
+#ifndef XMLSEC_NO_SHA256
+            if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) {
+                ConvertEndian(tmpBuf, outBuf, outSize);
+            } else 
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+            if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha384Id)) {
+                ConvertEndian(tmpBuf, outBuf, outSize);
+            } else 
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+            if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha512Id)) {
+                ConvertEndian(tmpBuf, outBuf, outSize);
+            } else 
+#endif /* XMLSEC_NO_SHA512 */
+
+
+#endif /* XMLSEC_NO_RSA*/
+
+#ifndef XMLSEC_NO_DSA
+            if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformDsaSha1Id) && (outSize == 40)) {
+                ConvertEndian(tmpBuf, outBuf, 20);
+                ConvertEndian(tmpBuf + 20, outBuf + 20, 20);
+            } else 
+#endif /* XMLSEC_NO_DSA*/
+
 #ifndef XMLSEC_NO_GOST
-    } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
-                i = tmpBuf;
-                j = outBuf + dwSigLen - 1;
-
-                while (j >= outBuf) {
-                    *j-- = *i++;
-                }
-#endif /*ndef XMLSEC_NO_GOST*/
-            } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) {
-                i = tmpBuf;
-                j = outBuf + dwSigLen - 1;
-
-                while (j >= outBuf) {
-                    *j-- = *i++;
-                }
-            } else {
+            if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2001GostR3411_94Id)) {
+                ConvertEndian(tmpBuf, outBuf, outSize);
+            } else 
+#endif /* XMLSEC_NO_GOST*/
+
+            {
                 /* We shouldn't get at this place */
                 xmlSecError(XMLSEC_ERRORS_HERE,
                             xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
@@ -563,6 +643,144 @@ xmlSecMSCryptoTransformRsaSha1GetKlass(void) {
     return(&xmlSecMSCryptoRsaSha1Klass);
 }
 
+#ifndef XMLSEC_NO_SHA256
+/****************************************************************************
+ *
+ * RSA-SHA256 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoRsaSha256Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),              /* xmlSecSize klassSize */
+    xmlSecMSCryptoSignatureSize,               /* xmlSecSize objSize */
+
+    xmlSecNameRsaSha256,                       /* const xmlChar* name; */
+    xmlSecHrefRsaSha256,                       /* const xmlChar* href; */
+    xmlSecTransformUsageSignatureMethod,       /* xmlSecTransformUsage usage; */
+    
+    xmlSecMSCryptoSignatureInitialize,         /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecMSCryptoSignatureFinalize,           /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                      /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                      /* xmlSecTransformNodeWriteMethod writeNode; */
+    xmlSecMSCryptoSignatureSetKeyReq,          /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+    xmlSecMSCryptoSignatureSetKey,             /* xmlSecTransformSetKeyMethod setKey; */
+    xmlSecMSCryptoSignatureVerify,             /* xmlSecTransformVerifyMethod verify; */
+    xmlSecTransformDefaultGetDataType,         /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,             /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,              /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                      /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                      /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecMSCryptoSignatureExecute,            /* xmlSecTransformExecuteMethod execute; */
+    
+    NULL,                                      /* void* reserved0; */
+    NULL,                                      /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformRsaSha256GetKlass:
+ * 
+ * The RSA-SHA256 signature transform klass.
+ *
+ * Returns RSA-SHA256 signature transform klass.
+ */
+xmlSecTransformId 
+xmlSecMSCryptoTransformRsaSha256GetKlass(void) {
+    return(&xmlSecMSCryptoRsaSha256Klass);
+}
+#endif /* XMLSEC_NO_SHA256 */
+
+#ifndef XMLSEC_NO_SHA384
+/****************************************************************************
+ *
+ * RSA-SHA384 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoRsaSha384Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),              /* xmlSecSize klassSize */
+    xmlSecMSCryptoSignatureSize,               /* xmlSecSize objSize */
+
+    xmlSecNameRsaSha384,                       /* const xmlChar* name; */
+    xmlSecHrefRsaSha384,                       /* const xmlChar* href; */
+    xmlSecTransformUsageSignatureMethod,       /* xmlSecTransformUsage usage; */
+    
+    xmlSecMSCryptoSignatureInitialize,         /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecMSCryptoSignatureFinalize,           /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                      /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                      /* xmlSecTransformNodeWriteMethod writeNode; */
+    xmlSecMSCryptoSignatureSetKeyReq,          /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+    xmlSecMSCryptoSignatureSetKey,             /* xmlSecTransformSetKeyMethod setKey; */
+    xmlSecMSCryptoSignatureVerify,             /* xmlSecTransformVerifyMethod verify; */
+    xmlSecTransformDefaultGetDataType,         /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,             /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,              /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                      /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                      /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecMSCryptoSignatureExecute,            /* xmlSecTransformExecuteMethod execute; */
+    
+    NULL,                                      /* void* reserved0; */
+    NULL,                                      /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformRsaSha384GetKlass:
+ * 
+ * The RSA-SHA384 signature transform klass.
+ *
+ * Returns RSA-SHA384 signature transform klass.
+ */
+xmlSecTransformId 
+xmlSecMSCryptoTransformRsaSha384GetKlass(void) {
+    return(&xmlSecMSCryptoRsaSha384Klass);
+}
+#endif /* XMLSEC_NO_SHA384 */
+
+#ifndef XMLSEC_NO_SHA512
+/****************************************************************************
+ *
+ * RSA-SHA2512 signature transform
+ *
+ ***************************************************************************/
+static xmlSecTransformKlass xmlSecMSCryptoRsaSha512Klass = {
+    /* klass/object sizes */
+    sizeof(xmlSecTransformKlass),              /* xmlSecSize klassSize */
+    xmlSecMSCryptoSignatureSize,               /* xmlSecSize objSize */
+
+    xmlSecNameRsaSha512,                       /* const xmlChar* name; */
+    xmlSecHrefRsaSha512,                       /* const xmlChar* href; */
+    xmlSecTransformUsageSignatureMethod,       /* xmlSecTransformUsage usage; */
+    
+    xmlSecMSCryptoSignatureInitialize,         /* xmlSecTransformInitializeMethod initialize; */
+    xmlSecMSCryptoSignatureFinalize,           /* xmlSecTransformFinalizeMethod finalize; */
+    NULL,                                      /* xmlSecTransformNodeReadMethod readNode; */
+    NULL,                                      /* xmlSecTransformNodeWriteMethod writeNode; */
+    xmlSecMSCryptoSignatureSetKeyReq,          /* xmlSecTransformSetKeyReqMethod setKeyReq; */
+    xmlSecMSCryptoSignatureSetKey,             /* xmlSecTransformSetKeyMethod setKey; */
+    xmlSecMSCryptoSignatureVerify,             /* xmlSecTransformVerifyMethod verify; */
+    xmlSecTransformDefaultGetDataType,         /* xmlSecTransformGetDataTypeMethod getDataType; */
+    xmlSecTransformDefaultPushBin,             /* xmlSecTransformPushBinMethod pushBin; */
+    xmlSecTransformDefaultPopBin,              /* xmlSecTransformPopBinMethod popBin; */
+    NULL,                                      /* xmlSecTransformPushXmlMethod pushXml; */
+    NULL,                                      /* xmlSecTransformPopXmlMethod popXml; */
+    xmlSecMSCryptoSignatureExecute,            /* xmlSecTransformExecuteMethod execute; */
+    
+    NULL,                                      /* void* reserved0; */
+    NULL,                                      /* void* reserved1; */
+};
+
+/**
+ * xmlSecMSCryptoTransformRsaSha512GetKlass:
+ * 
+ * The RSA-SHA512 signature transform klass.
+ *
+ * Returns RSA-SHA512 signature transform klass.
+ */
+xmlSecTransformId 
+xmlSecMSCryptoTransformRsaSha512GetKlass(void) {
+    return(&xmlSecMSCryptoRsaSha512Klass);
+}
+#endif /* XMLSEC_NO_SHA512 */
+
 #endif /* XMLSEC_NO_RSA */
 
 #ifndef XMLSEC_NO_DSA



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