winmm/wineoss: Win64 printf format warning fixes.
[wine] / dlls / rsaenh / rsaenh.c
index dc63ef5..996047d 100644 (file)
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include "config.h"
@@ -36,6 +36,7 @@
 #include "lmcons.h"
 #include "handle.h"
 #include "implglue.h"
+#include "objbase.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 
@@ -334,6 +335,7 @@ int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
     switch (fdwReason)
     {
         case DLL_PROCESS_ATTACH:
+            DisableThreadLibraryCalls(hInstance);
             init_handle_table(&handle_table);
             break;
 
@@ -857,8 +859,7 @@ static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTK
 /******************************************************************************
  * destroy_key_container [Internal]
  *
- * Destructor for key containers. The user's signature and key exchange private
- * keys are stored in the registry _IN_PLAINTEXT_.
+ * Destructor for key containers.
  * 
  * PARAMS
  *  pObjectHdr [I] Pointer to the key container to be destroyed.
@@ -866,6 +867,7 @@ static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTK
 static void destroy_key_container(OBJECTHDR *pObjectHdr)
 {
     KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr;
+    DATA_BLOB blobIn, blobOut;
     CRYPTKEY *pKey;
     CHAR szRSABase[MAX_PATH];
     HKEY hKey, hRootKey;
@@ -884,6 +886,8 @@ static void destroy_key_container(OBJECTHDR *pObjectHdr)
             hRootKey = HKEY_CURRENT_USER;
         }
         
+        /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
+        /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
         if (RegCreateKeyExA(hRootKey, szRSABase, 0, NULL, REG_OPTION_NON_VOLATILE, 
                             KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
         {
@@ -899,7 +903,18 @@ static void destroy_key_container(OBJECTHDR *pObjectHdr)
                         if (RSAENH_CPExportKey(pKey->hProv, pKeyContainer->hKeyExchangeKeyPair, 0,
                                                PRIVATEKEYBLOB, 0, pbKey, &dwLen))
                         {
-                            RegSetValueExA(hKey, "KeyExchangeKeyPair", 0, REG_BINARY, pbKey, dwLen);
+                            blobIn.pbData = pbKey;
+                            blobIn.cbData = dwLen;
+                                    
+                            if (CryptProtectData(&blobIn, NULL, NULL, NULL, NULL, 
+                                 (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET) ? 
+                                   CRYPTPROTECT_LOCAL_MACHINE : 0, 
+                                 &blobOut)) 
+                            {
+                                RegSetValueExA(hKey, "KeyExchangeKeyPair", 0, REG_BINARY,
+                                               blobOut.pbData, blobOut.cbData);
+                                HeapFree(GetProcessHeap(), 0, blobOut.pbData);
+                            }
                         }
                         HeapFree(GetProcessHeap(), 0, pbKey);
                     }
@@ -920,7 +935,18 @@ static void destroy_key_container(OBJECTHDR *pObjectHdr)
                         if (RSAENH_CPExportKey(pKey->hProv, pKeyContainer->hSignatureKeyPair, 0, 
                                                PRIVATEKEYBLOB, 0, pbKey, &dwLen))
                         {
-                            RegSetValueExA(hKey, "SignatureKeyPair", 0, REG_BINARY, pbKey, dwLen);
+                            blobIn.pbData = pbKey;
+                            blobIn.cbData = dwLen;
+                                    
+                            if (CryptProtectData(&blobIn, NULL, NULL, NULL, NULL, 
+                                 (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET) ? 
+                                   CRYPTPROTECT_LOCAL_MACHINE : 0, 
+                                 &blobOut)) 
+                            {
+                                RegSetValueExA(hKey, "SignatureKeyPair", 0, REG_BINARY, 
+                                               blobOut.pbData, blobOut.cbData);
+                                HeapFree(GetProcessHeap(), 0, blobOut.pbData);
+                            }
                         }
                         HeapFree(GetProcessHeap(), 0, pbKey);
                     }
@@ -950,7 +976,7 @@ static void destroy_key_container(OBJECTHDR *pObjectHdr)
  *  Success: Handle to the new key container.
  *  Failure: INVALID_HANDLE_VALUE
  */
-static HCRYPTPROV new_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTableProvStruc pVTable)
+static HCRYPTPROV new_key_container(PCCH pszContainerName, DWORD dwFlags, PVTableProvStruc pVTable)
 {
     KEYCONTAINER *pKeyContainer;
     HCRYPTPROV hKeyContainer;
@@ -959,15 +985,13 @@ static HCRYPTPROV new_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTab
                                            destroy_key_container, (OBJECTHDR**)&pKeyContainer);
     if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
     {
-        strncpy(pKeyContainer->szName, pszContainerName, MAX_PATH);
-        pKeyContainer->szName[MAX_PATH-1] = '\0';
+        lstrcpynA(pKeyContainer->szName, pszContainerName, MAX_PATH);
         pKeyContainer->dwFlags = dwFlags;
         pKeyContainer->dwEnumAlgsCtr = 0;
         pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
         pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
         if (pVTable && pVTable->pszProvName) {
-            strncpy(pKeyContainer->szProvName, pVTable->pszProvName, MAX_PATH);
-            pKeyContainer->szProvName[MAX_PATH-1] = '\0';
+            lstrcpynA(pKeyContainer->szProvName, pVTable->pszProvName, MAX_PATH);
             if (!strcmp(pVTable->pszProvName, MS_DEF_PROV_A)) {
                 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_BASE;
             } else if (!strcmp(pVTable->pszProvName, MS_ENHANCED_PROV_A)) {
@@ -982,7 +1006,7 @@ static HCRYPTPROV new_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTab
         /* The new key container has to be inserted into the CSP immediately 
          * after creation to be available for CPGetProvParam's PP_ENUMCONTAINERS. */
         if (!(dwFlags & CRYPT_VERIFYCONTEXT)) {
-            BYTE szRSABase[MAX_PATH];
+            CHAR szRSABase[MAX_PATH];
             HKEY hRootKey, hKey;
 
             sprintf(szRSABase, RSAENH_REGKEY, pKeyContainer->szName);
@@ -993,6 +1017,8 @@ static HCRYPTPROV new_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTab
                 hRootKey = HKEY_CURRENT_USER;
             }
 
+            /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
+            /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
             RegCreateKeyA(hRootKey, szRSABase, &hKey);
             RegCloseKey(hKey);
         }
@@ -1023,6 +1049,7 @@ static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTa
     DWORD dwValueType, dwLen;
     KEYCONTAINER *pKeyContainer;
     HCRYPTPROV hKeyContainer;
+    DATA_BLOB blobIn, blobOut;
     
     sprintf(szRSABase, RSAENH_REGKEY, pszContainerName);
 
@@ -1032,6 +1059,8 @@ static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTa
         hRootKey = HKEY_CURRENT_USER;
     }
 
+    /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
+    /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
     if (RegOpenKeyExA(hRootKey, szRSABase, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
     {
         SetLastError(NTE_BAD_KEYSET);
@@ -1054,8 +1083,16 @@ static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTa
                 if (RegQueryValueExA(hKey, "KeyExchangeKeyPair", 0, &dwValueType, pbKey, &dwLen) ==
                     ERROR_SUCCESS)
                 {
-                    RSAENH_CPImportKey(hKeyContainer, pbKey, dwLen, 0, 0, 
-                                       &pKeyContainer->hKeyExchangeKeyPair);
+                    blobIn.pbData = pbKey;
+                    blobIn.cbData = dwLen;
+
+                    if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, 
+                         (dwFlags & CRYPT_MACHINE_KEYSET) ? CRYPTPROTECT_LOCAL_MACHINE : 0, &blobOut))
+                    {
+                        RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0,
+                                           &pKeyContainer->hKeyExchangeKeyPair);
+                        HeapFree(GetProcessHeap(), 0, blobOut.pbData);
+                    }
                 }
                 HeapFree(GetProcessHeap(), 0, pbKey);
             }
@@ -1070,8 +1107,16 @@ static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTa
                 if (RegQueryValueExA(hKey, "SignatureKeyPair", 0, &dwValueType, pbKey, &dwLen) == 
                     ERROR_SUCCESS)
                 {
-                    RSAENH_CPImportKey(hKeyContainer, pbKey, dwLen, 0, 0, 
-                                       &pKeyContainer->hSignatureKeyPair);
+                    blobIn.pbData = pbKey;
+                    blobIn.cbData = dwLen;
+
+                    if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, 
+                         (dwFlags & CRYPT_MACHINE_KEYSET) ? CRYPTPROTECT_LOCAL_MACHINE : 0, &blobOut))
+                    {
+                        RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0,
+                                           &pKeyContainer->hSignatureKeyPair);
+                        HeapFree(GetProcessHeap(), 0, blobOut.pbData);
+                    }
                 }
                 HeapFree(GetProcessHeap(), 0, pbKey);
             }
@@ -1401,24 +1446,22 @@ static BOOL unpad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWOR
 BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
                    DWORD dwFlags, PVTableProvStruc pVTable)
 {
-    DWORD dwLen;
-    CHAR szKeyContainerName[MAX_PATH] = "";
+    CHAR szKeyContainerName[MAX_PATH];
     CHAR szRegKey[MAX_PATH];
 
     TRACE("(phProv=%p, pszContainer=%s, dwFlags=%08lx, pVTable=%p)\n", phProv, 
           debugstr_a(pszContainer), dwFlags, pVTable);
 
-    if (pszContainer ? strlen(pszContainer) : 0) 
+    if (pszContainer && *pszContainer)
     {
-        strncpy(szKeyContainerName, pszContainer, MAX_PATH);
-        szKeyContainerName[MAX_PATH-1] = '\0';
+        lstrcpynA(szKeyContainerName, pszContainer, MAX_PATH);
     } 
     else
     {
-        dwLen = MAX_PATH;
+        DWORD dwLen = sizeof(szKeyContainerName);
         if (!GetUserNameA(szKeyContainerName, &dwLen)) return FALSE;
     }
-        
+
     switch (dwFlags & (CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT|CRYPT_DELETEKEYSET)) 
     {
         case 0:
@@ -1426,13 +1469,17 @@ BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
             break;
 
         case CRYPT_DELETEKEYSET:
-            if (snprintf(szRegKey, MAX_PATH, RSAENH_REGKEY, pszContainer) >= MAX_PATH) {
+            if (snprintf(szRegKey, MAX_PATH, RSAENH_REGKEY, szKeyContainerName) >= MAX_PATH) {
                 SetLastError(NTE_BAD_KEYSET_PARAM);
                 return FALSE;
             } else {
-                RegDeleteKeyA(HKEY_CURRENT_USER, szRegKey);
-                SetLastError(ERROR_SUCCESS);
-                return TRUE;
+                if (!RegDeleteKeyA(HKEY_CURRENT_USER, szRegKey)) {
+                    SetLastError(ERROR_SUCCESS);
+                    return TRUE;
+                } else {
+                    SetLastError(NTE_BAD_KEYSET);
+                    return FALSE;
+                }
             }
             break;
 
@@ -1441,6 +1488,7 @@ BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
             if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) 
             {
                 release_handle(&handle_table, (unsigned int)*phProv, RSAENH_MAGIC_CONTAINER);
+                TRACE("Can't create new keyset, already exists\n");
                 SetLastError(NTE_EXISTS);
                 return FALSE;
             }
@@ -1449,6 +1497,7 @@ BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
 
         case CRYPT_VERIFYCONTEXT:
             if (pszContainer) {
+                TRACE("pszContainer should be NULL\n");
                 SetLastError(NTE_BAD_FLAGS);
                 return FALSE;
             }
@@ -1548,11 +1597,19 @@ BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
     init_data_blob(&pCryptHash->tpPRFParams.blobSeed);
 
     if (Algid == CALG_SCHANNEL_MASTER_HASH) {
-        CRYPT_DATA_BLOB blobRandom, blobKeyExpansion = { 13, "key expansion" };
+        static const char keyex[] = "key expansion";
+        BYTE key_expansion[sizeof keyex];
+        CRYPT_DATA_BLOB blobRandom, blobKeyExpansion = { 13, key_expansion };
+
+        memcpy( key_expansion, keyex, sizeof keyex );
         
         if (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY) {
-            CRYPT_DATA_BLOB blobLabel = { 13, "master secret" };
+            static const char msec[] = "master secret";
+            BYTE master_secret[sizeof msec];
+            CRYPT_DATA_BLOB blobLabel = { 13, master_secret };
             BYTE abKeyValue[48];
+
+            memcpy( master_secret, msec, sizeof msec );
     
             /* See RFC 2246, chapter 8.1 */
             if (!concat_data_blobs(&blobRandom, 
@@ -1838,7 +1895,13 @@ BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
         }
 
         dwEncryptedLen = (*pdwDataLen/pCryptKey->dwBlockLen+(Final?1:0))*pCryptKey->dwBlockLen;
-        for (i=*pdwDataLen; i<dwEncryptedLen; i++) pbData[i] = dwEncryptedLen - *pdwDataLen;
+
+        if (pbData == NULL) {
+            *pdwDataLen = dwEncryptedLen;
+            return TRUE;
+        }
+
+        for (i=*pdwDataLen; i<dwEncryptedLen && i<dwBufLen; i++) pbData[i] = dwEncryptedLen - *pdwDataLen;
         *pdwDataLen = dwEncryptedLen; 
 
         if (*pdwDataLen > dwBufLen) 
@@ -1850,20 +1913,20 @@ BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
         for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
             switch (pCryptKey->dwMode) {
                 case CRYPT_MODE_ECB:
-                    encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, in, out, 
+                    encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 
                                        RSAENH_ENCRYPT);
                     break;
                 
                 case CRYPT_MODE_CBC:
                     for (j=0; j<pCryptKey->dwBlockLen; j++) in[j] ^= pCryptKey->abChainVector[j];
-                    encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, in, out, 
+                    encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 
                                        RSAENH_ENCRYPT);
                     memcpy(pCryptKey->abChainVector, out, pCryptKey->dwBlockLen);
                     break;
 
                 case CRYPT_MODE_CFB:
                     for (j=0; j<pCryptKey->dwBlockLen; j++) {
-                        encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, 
+                        encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, 
                                            pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
                         out[j] = in[j] ^ o[0];
                         for (k=0; k<pCryptKey->dwBlockLen-1; k++) 
@@ -1879,18 +1942,26 @@ BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
             memcpy(in, out, pCryptKey->dwBlockLen); 
         }
     } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
+        if (pbData == NULL) {
+            *pdwDataLen = dwBufLen;
+            return TRUE;
+        }
         encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
     } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
         if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
             SetLastError(NTE_BAD_KEY);
             return FALSE;
         }
+        if (!pbData) {
+            *pdwDataLen = pCryptKey->dwBlockLen;
+            return TRUE;
+        }
         if (dwBufLen < pCryptKey->dwBlockLen) {
             SetLastError(ERROR_MORE_DATA);
             return FALSE;
         }
         if (!pad_data(pbData, *pdwDataLen, pbData, pCryptKey->dwBlockLen, dwFlags)) return FALSE;
-        encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, pbData, RSAENH_ENCRYPT);
+        encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbData, pbData, RSAENH_ENCRYPT);
         *pdwDataLen = pCryptKey->dwBlockLen;
         Final = TRUE;
     } else {
@@ -1933,6 +2004,7 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
     CRYPTKEY *pCryptKey;
     BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
     DWORD i, j, k;
+    DWORD dwMax;
 
     TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08lx, pbData=%p, "
           "pdwDataLen=%p)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
@@ -1963,17 +2035,19 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
         SetLastError(NTE_BAD_DATA);
         return FALSE;
     }
-    
+
+    dwMax=*pdwDataLen;
+
     if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
         for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
             switch (pCryptKey->dwMode) {
                 case CRYPT_MODE_ECB:
-                    encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, in, out, 
+                    encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 
                                        RSAENH_DECRYPT);
                     break;
                 
                 case CRYPT_MODE_CBC:
-                    encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, in, out, 
+                    encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 
                                        RSAENH_DECRYPT);
                     for (j=0; j<pCryptKey->dwBlockLen; j++) out[j] ^= pCryptKey->abChainVector[j];
                     memcpy(pCryptKey->abChainVector, in, pCryptKey->dwBlockLen);
@@ -1981,7 +2055,7 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
 
                 case CRYPT_MODE_CFB:
                     for (j=0; j<pCryptKey->dwBlockLen; j++) {
-                        encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, 
+                        encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, 
                                            pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
                         out[j] = in[j] ^ o[0];
                         for (k=0; k<pCryptKey->dwBlockLen-1; k++) 
@@ -2005,7 +2079,7 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
             SetLastError(NTE_BAD_KEY);
             return FALSE;
         }
-        encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT);
+        encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT);
         if (!unpad_data(pbData, pCryptKey->dwBlockLen, pbData, pdwDataLen, dwFlags)) return FALSE;
         Final = TRUE;
     } else {
@@ -2016,7 +2090,8 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash,
     if (Final) setup_key(pCryptKey);
 
     if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
-        if (!RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
+        if (*pdwDataLen>dwMax ||
+            !RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
     }
     
     return TRUE;
@@ -2105,7 +2180,7 @@ BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubK
                     return FALSE;
                 }
                 
-                encrypt_block_impl(pPubKey->aiAlgid, &pPubKey->context, (BYTE*)(pAlgid+1), 
+                encrypt_block_impl(pPubKey->aiAlgid, PK_PUBLIC, &pPubKey->context, (BYTE*)(pAlgid+1), 
                                    (BYTE*)(pAlgid+1), RSAENH_ENCRYPT); 
             }
             *pdwDataLen = dwDataLen;
@@ -2199,18 +2274,22 @@ BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubK
 BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, 
                                HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
 {
+    KEYCONTAINER *pKeyContainer;
     CRYPTKEY *pCryptKey, *pPubKey;
     CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
     CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
     CONST ALG_ID *pAlgid = (CONST ALG_ID*)(pBlobHeader+1);
     CONST BYTE *pbKeyStream = (CONST BYTE*)(pAlgid + 1);
+    ALG_ID algID;
     BYTE *pbDecrypted;
     DWORD dwKeyLen;
+    BOOL ret;
 
     TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%ld, hPubKey=%08lx, dwFlags=%08lx, phKey=%p)\n", 
         hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
     
-    if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
+    if (!lookup_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER, 
+                       (OBJECTHDR**)&pKeyContainer)) 
     {
         SetLastError(NTE_BAD_UID);
         return FALSE;
@@ -2239,8 +2318,28 @@ BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDat
             *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
             if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
             setup_key(pCryptKey);
-            return import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
+            ret = import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
                                            pRSAPubKey->bitlen/8, pRSAPubKey->pubexp);
+            if (ret) {
+                switch (pBlobHeader->aiKeyAlg)
+                {
+                case AT_SIGNATURE:
+                case CALG_RSA_SIGN:
+                    TRACE("installing signing key\n");
+                    RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
+                    copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
+                            (unsigned int*)&pKeyContainer->hSignatureKeyPair);
+                    break;
+                case AT_KEYEXCHANGE:
+                case CALG_RSA_KEYX:
+                    TRACE("installing key exchange key\n");
+                    RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
+                    copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
+                                (unsigned int*)&pKeyContainer->hKeyExchangeKeyPair);
+                    break;
+                }
+            }
+            return ret;
                 
         case PUBLICKEYBLOB:
             if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) || 
@@ -2251,11 +2350,28 @@ BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDat
                 return FALSE;
             }
     
-            *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey); 
+            /* Since this is a public key blob, only the public key is
+             * available, so only signature verification is possible.
+             */
+            algID = pBlobHeader->aiKeyAlg;
+            *phKey = new_key(hProv, algID, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey); 
             if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE; 
             setup_key(pCryptKey);
-            return import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
+            ret = import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
                                           pRSAPubKey->bitlen >> 3, pRSAPubKey->pubexp);
+            if (ret) {
+                switch (pBlobHeader->aiKeyAlg)
+                {
+                case AT_KEYEXCHANGE:
+                case CALG_RSA_KEYX:
+                    TRACE("installing public key\n");
+                    RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
+                    copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
+                                (unsigned int*)&pKeyContainer->hKeyExchangeKeyPair);
+                    break;
+                }
+            }
+            return ret;
                 
         case SIMPLEBLOB:
             if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey) ||
@@ -2273,7 +2389,7 @@ BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDat
 
             pbDecrypted = HeapAlloc(GetProcessHeap(), 0, pPubKey->dwBlockLen);
             if (!pbDecrypted) return FALSE;
-            encrypt_block_impl(pPubKey->aiAlgid, &pPubKey->context, pbKeyStream, pbDecrypted, 
+            encrypt_block_impl(pPubKey->aiAlgid, PK_PRIVATE, &pPubKey->context, pbKeyStream, pbDecrypted, 
                                RSAENH_DECRYPT);
 
             dwKeyLen = RSAENH_MAX_KEY_SIZE;
@@ -2499,7 +2615,12 @@ BOOL WINAPI RSAENH_CPGetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwPa
                 return tls1_prf(hProv, pCryptHash->hKey, &pCryptHash->tpPRFParams.blobLabel,
                                 &pCryptHash->tpPRFParams.blobSeed, pbData, *pdwDataLen);
             }
-            
+
+            if ( pbData == NULL ) {
+                *pdwDataLen = pCryptHash->dwHashSize;
+                return TRUE;
+            }
+
             if (pCryptHash->dwState == RSAENH_HASHSTATE_IDLE) {
                 SetLastError(NTE_BAD_HASH_STATE);
                 return FALSE;
@@ -2736,7 +2857,7 @@ BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
     KEYCONTAINER *pKeyContainer;
     PROV_ENUMALGS provEnumalgs;
     DWORD dwTemp;
-    BYTE szRSABase[MAX_PATH];
+    CHAR szRSABase[MAX_PATH];
     HKEY hKey, hRootKey;
    
     /* This is for dwParam 41, which does not seem to be documented
@@ -2821,7 +2942,7 @@ BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
             }
 
             dwTemp = *pdwDataLen;
-            switch (RegEnumKeyExA(hKey, pKeyContainer->dwEnumContainersCtr, pbData, &dwTemp,
+            switch (RegEnumKeyExA(hKey, pKeyContainer->dwEnumContainersCtr, (LPSTR)pbData, &dwTemp,
                     NULL, NULL, NULL, NULL))
             {
                 case ERROR_MORE_DATA:
@@ -3411,7 +3532,7 @@ BOOL WINAPI RSAENH_CPSignHash(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpe
         return FALSE;
     }
 
-    return encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT);
+    return encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT);
 }
 
 /******************************************************************************
@@ -3491,7 +3612,7 @@ BOOL WINAPI RSAENH_CPVerifySignature(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST B
         goto cleanup;
     }
 
-    if (!encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbSignature, pbDecrypted, 
+    if (!encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbSignature, pbDecrypted, 
                             RSAENH_DECRYPT)) 
     {
         goto cleanup;
@@ -3572,7 +3693,7 @@ static const WCHAR szDefaultKeys[2][65] = {
  *       Microsoft Strong Cryptographpic Provider
  *   - HKLM\Software\Microsoft\Cryptography\Defaults\Provider Types\Type 001
  */
-HRESULT WINAPI RSAENH_DllRegisterServer()
+HRESULT WINAPI DllRegisterServer(void)
 {
     HKEY key;
     DWORD dp;
@@ -3593,7 +3714,7 @@ HRESULT WINAPI RSAENH_DllRegisterServer()
                 static const WCHAR szSignature[] = { 'S','i','g','n','a','t','u','r','e',0 };
                 DWORD type = (i == 3) ? PROV_RSA_SCHANNEL : PROV_RSA_FULL;
                 DWORD sign = 0xdeadbeef;
-                RegSetValueExW(key, szImagePath, 0, REG_SZ, (LPBYTE)szRSABase, 
+                RegSetValueExW(key, szImagePath, 0, REG_SZ, (const BYTE *)szRSABase,
                                (lstrlenW(szRSABase) + 1) * sizeof(WCHAR));
                 RegSetValueExW(key, szType, 0, REG_DWORD, (LPBYTE)&type, sizeof(type));
                 RegSetValueExW(key, szSignature, 0, REG_BINARY, (LPBYTE)&sign, sizeof(sign));
@@ -3625,9 +3746,10 @@ HRESULT WINAPI RSAENH_DllRegisterServer()
                     'K','e','y',' ','E','x','c','h','a','n','g','e',')',0 },
                   { 'R','S','A',' ','S','C','h','a','n','n','e','l',0 } };
 
-                RegSetValueExW(key, szName, 0, REG_SZ, (LPBYTE)szRSAName[i], sizeof(szRSAName));
+                RegSetValueExW(key, szName, 0, REG_SZ, 
+                                (const BYTE *)szRSAName[i], lstrlenW(szRSAName[i])*sizeof(WCHAR)+sizeof(WCHAR));
                 RegSetValueExW(key, szTypeName, 0, REG_SZ, 
-                                (LPBYTE)szRSATypeName[i],sizeof(szRSATypeName));
+                                (const BYTE *)szRSATypeName[i], lstrlenW(szRSATypeName[i])*sizeof(WCHAR)+sizeof(WCHAR));
             }
         }
         RegCloseKey(key);
@@ -3649,7 +3771,7 @@ HRESULT WINAPI RSAENH_DllRegisterServer()
  * NOTES
  *  For the relevant keys see DllRegisterServer.
  */
-HRESULT WINAPI RSAENH_DllUnregisterServer()
+HRESULT WINAPI DllUnregisterServer(void)
 {
     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[0]);
     RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[1]);