[CRYPT32] Sync with Wine Staging 4.0. CORE-15682
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 25 Jan 2019 12:19:03 +0000 (13:19 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 25 Jan 2019 12:19:03 +0000 (13:19 +0100)
dll/win32/crypt32/cert.c
dll/win32/crypt32/crypt32.spec
dll/win32/crypt32/crypt32_private.h
dll/win32/crypt32/decode.c
dll/win32/crypt32/encode.c
dll/win32/crypt32/main.c
dll/win32/crypt32/msg.c
dll/win32/crypt32/oid.c
media/doc/README.WINE

index 0088f00..0065ba6 100644 (file)
@@ -28,6 +28,7 @@
 #include "wine/winternl.h"
 #define CRYPT_OID_INFO_HAS_EXTRA_FIELDS
 #include "wincrypt.h"
+#include "snmp.h"
 #include "bcrypt.h"
 #include "winnls.h"
 #include "rpc.h"
@@ -532,14 +533,19 @@ void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info)
     provNameLen = (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR);
     data += provNameLen;
 
-    info->rgProvParam = (PCRYPT_KEY_PROV_PARAM)data;
-    data += info->cProvParam * sizeof(CRYPT_KEY_PROV_PARAM);
-
-    for (i = 0; i < info->cProvParam; i++)
+    if (info->cProvParam)
     {
-        info->rgProvParam[i].pbData = data;
-        data += info->rgProvParam[i].cbData;
+        info->rgProvParam = (PCRYPT_KEY_PROV_PARAM)data;
+        data += info->cProvParam * sizeof(CRYPT_KEY_PROV_PARAM);
+
+        for (i = 0; i < info->cProvParam; i++)
+        {
+            info->rgProvParam[i].pbData = data;
+            data += info->rgProvParam[i].cbData;
+        }
     }
+    else
+        info->rgProvParam = NULL;
 }
 
 BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
@@ -1242,6 +1248,12 @@ BOOL WINAPI CertComparePublicKeyInfo(DWORD dwCertEncodingType,
 
     TRACE("(%08x, %p, %p)\n", dwCertEncodingType, pPublicKey1, pPublicKey2);
 
+    /* RSA public key data should start with ASN_SEQUENCE,
+     * otherwise it's not a RSA_CSP_PUBLICKEYBLOB.
+     */
+    if (!pPublicKey1->PublicKey.cbData || pPublicKey1->PublicKey.pbData[0] != ASN_SEQUENCE)
+        dwCertEncodingType = 0;
+
     switch (GET_CERT_ENCODING_TYPE(dwCertEncodingType))
     {
     case 0:    /* Seems to mean "raw binary bits" */
@@ -1267,32 +1279,21 @@ BOOL WINAPI CertComparePublicKeyInfo(DWORD dwCertEncodingType,
         ret = FALSE;
         if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
                     pPublicKey1->PublicKey.pbData, pPublicKey1->PublicKey.cbData,
-                    0, NULL, &length))
+                    CRYPT_DECODE_ALLOC_FLAG, &pblob1, &length))
         {
-            pblob1 = CryptMemAlloc(length);
             if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
-                    pPublicKey1->PublicKey.pbData, pPublicKey1->PublicKey.cbData,
-                    0, pblob1, &length))
+                        pPublicKey2->PublicKey.pbData, pPublicKey2->PublicKey.cbData,
+                        CRYPT_DECODE_ALLOC_FLAG, &pblob2, &length))
             {
-                if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
-                            pPublicKey2->PublicKey.pbData, pPublicKey2->PublicKey.cbData,
-                            0, NULL, &length))
-                {
-                    pblob2 = CryptMemAlloc(length);
-                    if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
-                            pPublicKey2->PublicKey.pbData, pPublicKey2->PublicKey.cbData,
-                            0, pblob2, &length))
-                    {
-                        /* The RSAPUBKEY structure directly follows the BLOBHEADER */
-                        RSAPUBKEY *pk1 = (LPVOID)(pblob1 + 1),
-                                  *pk2 = (LPVOID)(pblob2 + 1);
-                        ret = (pk1->bitlen == pk2->bitlen) && (pk1->pubexp == pk2->pubexp)
-                                 && !memcmp(pk1 + 1, pk2 + 1, pk1->bitlen/8);
-                    }
-                    CryptMemFree(pblob2);
-                }
+                /* The RSAPUBKEY structure directly follows the BLOBHEADER */
+                RSAPUBKEY *pk1 = (LPVOID)(pblob1 + 1),
+                          *pk2 = (LPVOID)(pblob2 + 1);
+                ret = (pk1->bitlen == pk2->bitlen) && (pk1->pubexp == pk2->pubexp)
+                         && !memcmp(pk1 + 1, pk2 + 1, pk1->bitlen/8);
+
+                LocalFree(pblob2);
             }
-            CryptMemFree(pblob1);
+            LocalFree(pblob1);
         }
 
         break;
@@ -1321,9 +1322,30 @@ DWORD WINAPI CertGetPublicKeyLength(DWORD dwCertEncodingType,
     }
     else
     {
+        PCCRYPT_OID_INFO info;
         DWORD size;
         PBYTE buf;
-        BOOL ret = CryptDecodeObjectEx(dwCertEncodingType,
+        BOOL ret;
+
+        info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pPublicKey->Algorithm.pszObjId, 0);
+        if (info)
+        {
+            HCRYPTKEY key;
+
+            TRACE("public key algid %#x (%s)\n", info->u.Algid, debugstr_a(pPublicKey->Algorithm.pszObjId));
+
+            ret = CryptImportPublicKeyInfo(I_CryptGetDefaultCryptProv(info->u.Algid), dwCertEncodingType, pPublicKey, &key);
+            if (ret)
+            {
+                size = sizeof(len);
+                ret = CryptGetKeyParam(key, KP_KEYLEN, (BYTE *)&len, &size, 0);
+                CryptDestroyKey(key);
+                return len;
+            }
+            /* fallback to RSA */
+        }
+
+        ret = CryptDecodeObjectEx(dwCertEncodingType,
          RSA_CSP_PUBLICKEYBLOB, pPublicKey->PublicKey.pbData,
          pPublicKey->PublicKey.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
          &size);
@@ -1794,7 +1816,7 @@ PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
     }
 
     if (find)
-        ret = find(hCertStore, dwFlags, dwType, pvPara, pPrevCertContext);
+        ret = find(hCertStore, dwType, dwFlags, pvPara, pPrevCertContext);
     else if (compare)
         ret = cert_compare_certs_in_store(hCertStore, pPrevCertContext,
          compare, dwType, dwFlags, pvPara);
@@ -2173,7 +2195,7 @@ BOOL WINAPI CryptHashCertificate(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid,
      pbEncoded, cbEncoded, pbComputedHash, pcbComputedHash);
 
     if (!hCryptProv)
-        hCryptProv = CRYPT_GetDefaultProvider();
+        hCryptProv = I_CryptGetDefaultCryptProv(0);
     if (!Algid)
         Algid = CALG_SHA1;
     if (ret)
@@ -2202,7 +2224,7 @@ BOOL WINAPI CryptHashPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid,
      dwCertEncodingType, pInfo, pbComputedHash, pcbComputedHash);
 
     if (!hCryptProv)
-        hCryptProv = CRYPT_GetDefaultProvider();
+        hCryptProv = I_CryptGetDefaultCryptProv(0);
     if (!Algid)
         Algid = CALG_MD5;
     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
@@ -2254,7 +2276,7 @@ BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv,
         HCRYPTHASH hHash;
 
         if (!hCryptProv)
-            hCryptProv = CRYPT_GetDefaultProvider();
+            hCryptProv = I_CryptGetDefaultCryptProv(0);
         oidInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
          info->SignatureAlgorithm.pszObjId, 0);
         if (!oidInfo)
@@ -2303,7 +2325,7 @@ BOOL WINAPI CryptSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
     if (info->dwGroupId == CRYPT_HASH_ALG_OID_GROUP_ID)
     {
         if (!hCryptProv)
-            hCryptProv = CRYPT_GetDefaultProvider();
+            hCryptProv = I_CryptGetDefaultCryptProv(0);
         ret = CryptCreateHash(hCryptProv, info->u.Algid, 0, 0, &hHash);
         if (ret)
         {
@@ -2427,7 +2449,7 @@ static BOOL CRYPT_VerifySignature(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEnco
         pubKeyID = hashID;
     /* Load the default provider if necessary */
     if (!hCryptProv)
-        hCryptProv = CRYPT_GetDefaultProvider();
+        hCryptProv = I_CryptGetDefaultCryptProv(0);
     ret = CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType,
      pubKeyInfo, pubKeyID, 0, NULL, &key);
     if (ret)
@@ -3685,3 +3707,11 @@ const void * WINAPI CertCreateContext(DWORD dwContextType, DWORD dwEncodingType,
         return NULL;
     }
 }
+
+BOOL WINAPI CryptSetKeyIdentifierProperty(const CRYPT_HASH_BLOB *pKeyIdentifier, DWORD dwPropId,
+    DWORD dwFlags, LPCWSTR pwszComputerName, void *pvReserved, const void *pvData)
+{
+    FIXME("(%p, 0x%x, 0x%x, %s, %p, %p): stub\n", pKeyIdentifier, dwPropId, dwFlags,
+        debugstr_w(pwszComputerName), pvReserved, pvData);
+    return FALSE;
+}
index 0bc78a1..fc32570 100644 (file)
 @ stdcall CryptSIPRetrieveSubjectGuidForCatalogFile(wstr long ptr)
 @ stdcall CryptSIPVerifyIndirectData(ptr ptr)
 @ stub CryptSetAsyncParam
+@ stdcall CryptSetKeyIdentifierProperty(ptr long long wstr ptr ptr)
 @ stdcall CryptSetOIDFunctionValue(long str str wstr long ptr long)
 @ stub CryptSetProviderU
 @ stdcall CryptSignAndEncodeCertificate(long long long str ptr ptr ptr ptr ptr)
 @ stdcall CryptUnprotectMemory(ptr long long)
 @ stdcall CryptUnregisterDefaultOIDFunction(long str wstr)
 @ stdcall CryptUnregisterOIDFunction(long str str)
-@ stub CryptUnregisterOIDInfo
+@ stdcall CryptUnregisterOIDInfo(ptr)
 @ stdcall CryptVerifyCertificateSignature(long long ptr long ptr)
 @ stdcall CryptVerifyCertificateSignatureEx(long long long ptr long ptr long ptr)
 @ stdcall CryptVerifyDetachedMessageHash(ptr ptr long long ptr ptr ptr ptr)
index e58db98..ac70fe0 100644 (file)
@@ -116,6 +116,7 @@ typedef struct _CRYPT_SIGNED_INFO
     CRYPT_CONTENT_INFO    content;
     DWORD                 cSignerInfo;
     PCMSG_CMS_SIGNER_INFO rgSignerInfo;
+    PDWORD                signerKeySpec;
 } CRYPT_SIGNED_INFO;
 
 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *, void *pvData,
@@ -149,7 +150,7 @@ BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,
 /* Returns a handle to the default crypto provider; loads it if necessary.
  * Returns NULL on failure.
  */
-HCRYPTPROV CRYPT_GetDefaultProvider(void) DECLSPEC_HIDDEN;
+HCRYPTPROV WINAPI I_CryptGetDefaultCryptProv(ALG_ID);
 
 HINSTANCE hInstance DECLSPEC_HIDDEN;
 
index f77393e..6f51632 100644 (file)
@@ -215,7 +215,7 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
         if (pDecodePara && pDecodePara->pfnAlloc)
             *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
         else
-            *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
+            *(BYTE **)pvStructInfo = LocalAlloc(LPTR, bytesNeeded);
         if (!*(BYTE **)pvStructInfo)
             ret = FALSE;
         else
@@ -1550,7 +1550,7 @@ static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
         case ASN_UTF8STRING:
             valueType = CERT_RDN_UTF8_STRING;
             bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
-             (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
+             (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * sizeof(WCHAR);
             break;
         default:
             SetLastError(CRYPT_E_ASN1_BADTAG);
@@ -6279,48 +6279,8 @@ BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
  DWORD *pcbStructInfo)
 {
-    BOOL ret = FALSE;
-    CryptDecodeObjectFunc pCryptDecodeObject = NULL;
-    CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
-    HCRYPTOIDFUNCADDR hFunc = NULL;
-
-    TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
-     debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
-     pvStructInfo, pcbStructInfo);
-
-    if (!pvStructInfo && !pcbStructInfo)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-    if (cbEncoded > MAX_ENCODED_LEN)
-    {
-        SetLastError(CRYPT_E_ASN1_LARGE);
-        return FALSE;
-    }
-
-    if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
-     lpszStructType)))
-    {
-        TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
-         debugstr_a(lpszStructType));
-        pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
-         lpszStructType, &hFunc);
-        if (!pCryptDecodeObject)
-            pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
-             lpszStructType, &hFunc);
-    }
-    if (pCryptDecodeObject)
-        ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
-         pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
-    else if (pCryptDecodeObjectEx)
-        ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
-         pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
-         pvStructInfo, pcbStructInfo);
-    if (hFunc)
-        CryptFreeOIDFunctionAddress(hFunc, 0);
-    TRACE_(crypt)("returning %d\n", ret);
-    return ret;
+    return CryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
+        pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
 }
 
 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
index 62d2bc9..9d052b6 100644 (file)
@@ -4779,20 +4779,22 @@ BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
      NULL, 0, NULL, pInfo, pcbInfo);
 }
 
-static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
+typedef BOOL (WINAPI *EncodePublicKeyAndParametersFunc)(DWORD dwCertEncodingType,
+ LPSTR pszPublicKeyObjId, BYTE *pbPubKey, DWORD cbPubKey, DWORD dwFlags, void *pvAuxInfo,
+ BYTE **ppPublicKey, DWORD *pcbPublicKey, BYTE **ppbParams, DWORD *pcbParams);
+
+static BOOL WINAPI CRYPT_ExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
  DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
  DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
 {
     BOOL ret;
     HCRYPTKEY key;
-    static CHAR oid[] = szOID_RSA_RSA;
+    static CHAR rsa_oid[] = szOID_RSA_RSA;
 
     TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
      dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
      pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
 
-    if (!pszPublicKeyObjId)
-        pszPublicKeyObjId = oid;
     if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
     {
         DWORD keySize = 0;
@@ -4800,16 +4802,86 @@ static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDL
         ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
         if (ret)
         {
-            LPBYTE pubKey = CryptMemAlloc(keySize);
+            PUBLICKEYSTRUC *pubKey = CryptMemAlloc(keySize);
 
             if (pubKey)
             {
-                ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
-                 &keySize);
+                ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, (BYTE *)pubKey, &keySize);
                 if (ret)
                 {
-                    DWORD encodedLen = 0;
+                    DWORD encodedLen;
+
+                    if (!pszPublicKeyObjId)
+                    {
+                        static HCRYPTOIDFUNCSET set;
+                        EncodePublicKeyAndParametersFunc encodeFunc = NULL;
+                        HCRYPTOIDFUNCADDR hFunc = NULL;
+
+                        pszPublicKeyObjId = (LPSTR)CertAlgIdToOID(pubKey->aiKeyAlg);
+                        TRACE("public key algid %#x (%s)\n", pubKey->aiKeyAlg, debugstr_a(pszPublicKeyObjId));
+
+                        if (!set) /* FIXME: there is no a public macro */
+                            set = CryptInitOIDFunctionSet("CryptDllEncodePublicKeyAndParameters", 0);
+
+                        CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId, 0, (void **)&encodeFunc, &hFunc);
+                        if (encodeFunc)
+                        {
+                            BYTE *key_data = NULL;
+                            DWORD key_size = 0;
+                            BYTE *params = NULL;
+                            DWORD params_size = 0;
 
+                            ret = encodeFunc(dwCertEncodingType, pszPublicKeyObjId, (BYTE *)pubKey, keySize,
+                                             dwFlags, pvAuxInfo, &key_data, &key_size, &params, &params_size);
+                            if (ret)
+                            {
+                                DWORD oid_size = strlen(pszPublicKeyObjId) + 1;
+                                DWORD size_needed = sizeof(*pInfo) + oid_size + key_size + params_size;
+
+                                if (!pInfo)
+                                    *pcbInfo = size_needed;
+                                else if (*pcbInfo < size_needed)
+                                {
+                                    *pcbInfo = size_needed;
+                                    SetLastError(ERROR_MORE_DATA);
+                                    ret = FALSE;
+                                }
+                                else
+                                {
+                                    *pcbInfo = size_needed;
+                                    pInfo->Algorithm.pszObjId = (char *)(pInfo + 1);
+                                    lstrcpyA(pInfo->Algorithm.pszObjId, pszPublicKeyObjId);
+                                    if (params)
+                                    {
+                                        pInfo->Algorithm.Parameters.cbData = params_size;
+                                        pInfo->Algorithm.Parameters.pbData = (BYTE *)pInfo->Algorithm.pszObjId + oid_size;
+                                        memcpy(pInfo->Algorithm.Parameters.pbData, params, params_size);
+                                    }
+                                    else
+                                    {
+                                        pInfo->Algorithm.Parameters.cbData = 0;
+                                        pInfo->Algorithm.Parameters.pbData = NULL;
+                                    }
+                                    pInfo->PublicKey.pbData = (BYTE *)pInfo->Algorithm.pszObjId + oid_size + params_size;
+                                    pInfo->PublicKey.cbData = key_size;
+                                    memcpy(pInfo->PublicKey.pbData, key_data, key_size);
+                                    pInfo->PublicKey.cUnusedBits = 0;
+                                }
+
+                                CryptMemFree(key_data);
+                                CryptMemFree(params);
+                            }
+
+                            CryptMemFree(pubKey);
+                            CryptFreeOIDFunctionAddress(hFunc, 0);
+                            return ret;
+                        }
+
+                        /* fallback to RSA */
+                        pszPublicKeyObjId = rsa_oid;
+                    }
+
+                    encodedLen = 0;
                     ret = CryptEncodeObject(dwCertEncodingType,
                      RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
                     if (ret)
@@ -4887,7 +4959,7 @@ BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptPro
          0, (void **)&exportFunc, &hFunc);
     }
     if (!exportFunc)
-        exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
+        exportFunc = CRYPT_ExportPublicKeyInfoEx;
     ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
      pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
     if (hFunc)
@@ -4902,21 +4974,48 @@ BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
      0, 0, NULL, phKey);
 }
 
-static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
+typedef BOOL (WINAPI *ConvertPublicKeyInfoFunc)(DWORD dwCertEncodingType,
+ PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, DWORD dwFlags,
+ BYTE **ppbData, DWORD *dwDataLen);
+
+static BOOL WINAPI CRYPT_ImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
  DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
  DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
 {
+    static HCRYPTOIDFUNCSET set = NULL;
+    ConvertPublicKeyInfoFunc convertFunc = NULL;
+    HCRYPTOIDFUNCADDR hFunc = NULL;
     BOOL ret;
-    DWORD pubKeySize = 0;
+    DWORD pubKeySize;
+    LPBYTE pubKey;
 
     TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
      dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
 
+    if (!set)
+        set = CryptInitOIDFunctionSet(CRYPT_OID_CONVERT_PUBLIC_KEY_INFO_FUNC, 0);
+    CryptGetOIDFunctionAddress(set, dwCertEncodingType, pInfo->Algorithm.pszObjId,
+                               0, (void **)&convertFunc, &hFunc);
+    if (convertFunc)
+    {
+        pubKey = NULL;
+        pubKeySize = 0;
+        ret = convertFunc(dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, &pubKey, &pubKeySize);
+        if (ret)
+        {
+            ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0, phKey);
+            CryptMemFree(pubKey);
+        }
+
+        CryptFreeOIDFunctionAddress(hFunc, 0);
+        return ret;
+    }
+
     ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
      pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
     if (ret)
     {
-        LPBYTE pubKey = CryptMemAlloc(pubKeySize);
+        pubKey = CryptMemAlloc(pubKeySize);
 
         if (pubKey)
         {
@@ -4959,7 +5058,7 @@ BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
     CryptGetOIDFunctionAddress(set, dwCertEncodingType,
      pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
     if (!importFunc)
-        importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
+        importFunc = CRYPT_ImportPublicKeyInfoEx;
     ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
      pvAuxInfo, phKey);
     if (hFunc)
index 79a0ce1..d0643f4 100644 (file)
@@ -35,6 +35,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 static HCRYPTPROV hDefProv;
 HINSTANCE hInstance;
 
+static CRITICAL_SECTION prov_param_cs;
+static CRITICAL_SECTION_DEBUG prov_param_cs_debug =
+{
+    0, 0, &prov_param_cs,
+    { &prov_param_cs_debug.ProcessLocksList,
+    &prov_param_cs_debug.ProcessLocksList },
+    0, 0, { (DWORD_PTR)(__FILE__ ": prov_param_cs") }
+};
+static CRITICAL_SECTION prov_param_cs = { &prov_param_cs_debug, -1, 0, 0, 0, 0 };
+
 BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, PVOID pvReserved)
 {
     switch (fdwReason)
@@ -56,7 +66,7 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, PVOID pvReserved)
     return TRUE;
 }
 
-HCRYPTPROV CRYPT_GetDefaultProvider(void)
+static HCRYPTPROV CRYPT_GetDefaultProvider(void)
 {
     if (!hDefProv)
     {
@@ -174,20 +184,69 @@ BOOL WINAPI I_CryptGetOssGlobal(DWORD x)
     return FALSE;
 }
 
-HCRYPTPROV WINAPI I_CryptGetDefaultCryptProv(DWORD reserved)
+static BOOL is_supported_algid(HCRYPTPROV prov, ALG_ID algid)
+{
+    PROV_ENUMALGS prov_algs;
+    DWORD size = sizeof(prov_algs);
+    BOOL ret = FALSE;
+
+    /* This enumeration is not thread safe */
+    EnterCriticalSection(&prov_param_cs);
+    if (CryptGetProvParam(prov, PP_ENUMALGS, (BYTE *)&prov_algs, &size, CRYPT_FIRST))
+    {
+        do
+        {
+            if (prov_algs.aiAlgid == algid)
+            {
+                ret = TRUE;
+                break;
+            }
+        } while (CryptGetProvParam(prov, PP_ENUMALGS, (BYTE *)&prov_algs, &size, CRYPT_NEXT));
+    }
+    LeaveCriticalSection(&prov_param_cs);
+    return ret;
+}
+
+HCRYPTPROV WINAPI DECLSPEC_HOTPATCH I_CryptGetDefaultCryptProv(ALG_ID algid)
 {
-    HCRYPTPROV ret;
+    HCRYPTPROV prov, defprov;
+
+    TRACE("(%08x)\n", algid);
 
-    TRACE("(%08x)\n", reserved);
+    defprov = CRYPT_GetDefaultProvider();
 
-    if (reserved)
+    if (algid && !is_supported_algid(defprov, algid))
     {
+        DWORD i = 0, type, size;
+
+        while (CryptEnumProvidersW(i, NULL, 0, &type, NULL, &size))
+        {
+            WCHAR *name = CryptMemAlloc(size);
+            if (name)
+            {
+                if (CryptEnumProvidersW(i, NULL, 0, &type, name, &size))
+                {
+                    if (CryptAcquireContextW(&prov, NULL, name, type, CRYPT_VERIFYCONTEXT))
+                    {
+                        if (is_supported_algid(prov, algid))
+                        {
+                            CryptMemFree(name);
+                            return prov;
+                        }
+                        CryptReleaseContext(prov, 0);
+                    }
+                }
+                CryptMemFree(name);
+            }
+            i++;
+        }
+
         SetLastError(E_INVALIDARG);
         return 0;
     }
-    ret = CRYPT_GetDefaultProvider();
-    CryptContextAddRef(ret, NULL, 0);
-    return ret;
+
+    CryptContextAddRef(defprov, NULL, 0);
+    return defprov;
 }
 
 BOOL WINAPI I_CryptReadTrustedPublisherDWORDValueFromRegistry(LPCWSTR name,
index 005fbf2..4132390 100644 (file)
@@ -567,7 +567,12 @@ static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
         prov = info->hCryptProv;
     else
     {
-        prov = CRYPT_GetDefaultProvider();
+        prov = I_CryptGetDefaultCryptProv(algID);
+        if (!prov)
+        {
+            SetLastError(E_INVALIDARG);
+            return NULL;
+        }
         dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
     }
     msg = CryptMemAlloc(sizeof(CHashEncodeMsg));
@@ -921,17 +926,25 @@ typedef struct _CSignedMsgData
  * been constructed.
  */
 static BOOL CSignedMsgData_ConstructSignerHandles(CSignedMsgData *msg_data,
- DWORD signerIndex, HCRYPTPROV crypt_prov)
+ DWORD signerIndex, HCRYPTPROV *crypt_prov, DWORD *flags)
 {
     ALG_ID algID;
     BOOL ret;
 
     algID = CertOIDToAlgId(
      msg_data->info->rgSignerInfo[signerIndex].HashAlgorithm.pszObjId);
-    ret = CryptCreateHash(crypt_prov, algID, 0, 0,
+
+    if (!*crypt_prov)
+    {
+        *crypt_prov = I_CryptGetDefaultCryptProv(algID);
+        if (!*crypt_prov) return FALSE;
+        *flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
+    }
+
+    ret = CryptCreateHash(*crypt_prov, algID, 0, 0,
      &msg_data->signerHandles->contentHash);
     if (ret && msg_data->info->rgSignerInfo[signerIndex].AuthAttrs.cAttr > 0)
-        ret = CryptCreateHash(crypt_prov, algID, 0, 0,
+        ret = CryptCreateHash(*crypt_prov, algID, 0, 0,
          &msg_data->signerHandles->authAttrHash);
     return ret;
 }
@@ -1125,12 +1138,15 @@ static BOOL CSignedMsgData_Sign(CSignedMsgData *msg_data)
     for (i = 0; ret && i < msg_data->info->cSignerInfo; i++)
     {
         HCRYPTHASH hash;
+        DWORD keySpec = msg_data->info->signerKeySpec[i];
 
+        if (!keySpec)
+            keySpec = AT_SIGNATURE;
         if (msg_data->info->rgSignerInfo[i].AuthAttrs.cAttr)
             hash = msg_data->signerHandles[i].authAttrHash;
         else
             hash = msg_data->signerHandles[i].contentHash;
-        ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0, NULL,
+        ret = CryptSignHashW(hash, keySpec, NULL, 0, NULL,
          &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData);
         if (ret)
         {
@@ -1139,7 +1155,7 @@ static BOOL CSignedMsgData_Sign(CSignedMsgData *msg_data)
              msg_data->info->rgSignerInfo[i].EncryptedHash.cbData);
             if (msg_data->info->rgSignerInfo[i].EncryptedHash.pbData)
             {
-                ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0,
+                ret = CryptSignHashW(hash, keySpec, NULL, 0,
                  msg_data->info->rgSignerInfo[i].EncryptedHash.pbData,
                  &msg_data->info->rgSignerInfo[i].EncryptedHash.cbData);
                 if (ret)
@@ -1189,6 +1205,7 @@ static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg)
     for (i = 0; i < msg->msg_data.info->cSignerInfo; i++)
         CSignerInfo_Free(&msg->msg_data.info->rgSignerInfo[i]);
     CSignedMsgData_CloseHandles(&msg->msg_data);
+    CryptMemFree(msg->msg_data.info->signerKeySpec);
     CryptMemFree(msg->msg_data.info->rgSignerInfo);
     CryptMemFree(msg->msg_data.info);
 }
@@ -1411,6 +1428,9 @@ static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags,
                      msg->msg_data.info->cSignerInfo *
                      sizeof(CMSG_CMS_SIGNER_INFO));
                     ret = CSignedMsgData_AllocateHandles(&msg->msg_data);
+                    msg->msg_data.info->signerKeySpec = CryptMemAlloc(info->cSigners * sizeof(DWORD));
+                    if (!msg->msg_data.info->signerKeySpec)
+                        ret = FALSE;
                     for (i = 0; ret && i < msg->msg_data.info->cSignerInfo; i++)
                     {
                         if (info->rgSigners[i].SignerId.dwIdChoice ==
@@ -1422,11 +1442,13 @@ static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags,
                         if (ret)
                         {
                             ret = CSignedMsgData_ConstructSignerHandles(
-                             &msg->msg_data, i, info->rgSigners[i].hCryptProv);
+                             &msg->msg_data, i, &info->rgSigners[i].hCryptProv, &dwFlags);
                             if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
                                 CryptReleaseContext(info->rgSigners[i].hCryptProv,
                                  0);
                         }
+                        msg->msg_data.info->signerKeySpec[i] =
+                         info->rgSigners[i].dwKeySpec;
                     }
                 }
                 else
@@ -1956,7 +1978,7 @@ static HCRYPTMSG CEnvelopedEncodeMsg_Open(DWORD dwFlags,
         prov = info->hCryptProv;
     else
     {
-        prov = CRYPT_GetDefaultProvider();
+        prov = I_CryptGetDefaultCryptProv(0);
         dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
     }
     msg = CryptMemAlloc(sizeof(CEnvelopedEncodeMsg));
@@ -2078,7 +2100,7 @@ static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg)
 {
     CDecodeMsg *msg = hCryptMsg;
 
-    if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
+    if (msg->crypt_prov && msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
         CryptReleaseContext(msg->crypt_prov, 0);
     switch (msg->type)
     {
@@ -2329,6 +2351,14 @@ static BOOL CDecodeMsg_FinalizeHashedContent(CDecodeMsg *msg,
      &size);
     if (ret)
         algID = CertOIDToAlgId(hashAlgoID->pszObjId);
+
+    if (!msg->crypt_prov)
+    {
+        msg->crypt_prov = I_CryptGetDefaultCryptProv(algID);
+        if (msg->crypt_prov)
+            msg->base.open_flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
+    }
+
     ret = CryptCreateHash(msg->crypt_prov, algID, 0, 0, &msg->u.hash);
     if (ret)
     {
@@ -2375,7 +2405,7 @@ static BOOL CDecodeMsg_FinalizeSignedContent(CDecodeMsg *msg,
     ret = CSignedMsgData_AllocateHandles(&msg->u.signed_data);
     for (i = 0; ret && i < msg->u.signed_data.info->cSignerInfo; i++)
         ret = CSignedMsgData_ConstructSignerHandles(&msg->u.signed_data, i,
-         msg->crypt_prov);
+         &msg->crypt_prov, &msg->base.open_flags);
     if (ret)
     {
         CRYPT_DATA_BLOB *content;
@@ -3541,13 +3571,7 @@ HCRYPTMSG WINAPI CryptMsgOpenToDecode(DWORD dwMsgEncodingType, DWORD dwFlags,
          CDecodeMsg_Close, CDecodeMsg_GetParam, CDecodeMsg_Update,
          CDecodeMsg_Control);
         msg->type = dwMsgType;
-        if (hCryptProv)
-            msg->crypt_prov = hCryptProv;
-        else
-        {
-            msg->crypt_prov = CRYPT_GetDefaultProvider();
-            msg->base.open_flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
-        }
+        msg->crypt_prov = hCryptProv;
         memset(&msg->u, 0, sizeof(msg->u));
         msg->msg_data.cbData = 0;
         msg->msg_data.pbData = NULL;
index c9b0b41..773264d 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright 2002 Mike McCormack for CodeWeavers
  * Copyright 2005-2006 Juan Lang
+ * Copyright 2018 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,6 +23,9 @@
 
 #include <stdio.h>
 #include <stdarg.h>
+#ifdef __REACTOS__
+#include <stdlib.h>
+#endif
 #define NONAMELESSUNION
 #include "windef.h"
 #include "winbase.h"
@@ -58,6 +62,7 @@ struct OIDFunctionSet
 
 struct OIDFunction
 {
+    HMODULE hModule;
     DWORD encoding;
     CRYPT_OID_FUNC_ENTRY entry;
     struct list next;
@@ -72,6 +77,13 @@ static const WCHAR DISALLOWED[] = {'D','i','s','a','l','l','o','w','e','d',0};
 static const LPCWSTR LocalizedKeys[] = {ROOT,MY,CA,ADDRESSBOOK,TRUSTEDPUBLISHER,DISALLOWED};
 static WCHAR LocalizedNames[ARRAY_SIZE(LocalizedKeys)][256];
 
+static const WCHAR nameW[] = { 'N','a','m','e',0 };
+static const WCHAR algidW[] = { 'A','l','g','i','d',0 };
+static const WCHAR extraW[] = { 'E','x','t','r','a','I','n','f','o',0 };
+static const WCHAR cngalgidW[] = { 'C','N','G','A','l','g','i','d',0 };
+static const WCHAR cngextraalgidW[] = { 'C','N','G','E','x','t','r','a','A','l','g','i','d',0 };
+static const WCHAR flagsW[] = { 'F','l','a','g','s',0 };
+
 static void free_function_sets(void)
 {
     struct OIDFunctionSet *setCursor, *setNext;
@@ -242,6 +254,8 @@ BOOL WINAPI CryptInstallOIDFunctionAddress(HMODULE hModule,
         {
             struct OIDFunction *func;
 
+            TRACE("OID %s, func %p\n", debugstr_a(rgFuncEntry[i].pszOID), rgFuncEntry[i].pvFuncAddr);
+
             if (!IS_INTOID(rgFuncEntry[i].pszOID))
                 func = CryptMemAlloc(sizeof(struct OIDFunction)
                  + strlen(rgFuncEntry[i].pszOID) + 1);
@@ -261,6 +275,7 @@ BOOL WINAPI CryptInstallOIDFunctionAddress(HMODULE hModule,
                 else
                     func->entry.pszOID = rgFuncEntry[i].pszOID;
                 func->entry.pvFuncAddr = rgFuncEntry[i].pvFuncAddr;
+                func->hModule = hModule;
                 list_add_tail(&set->functions, &func->next);
             }
             else
@@ -418,6 +433,38 @@ BOOL WINAPI CryptGetOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
     return ret;
 }
 
+static BOOL is_module_registered(HMODULE hModule)
+{
+    struct OIDFunctionSet *set;
+    BOOL ret = FALSE;
+
+    EnterCriticalSection(&funcSetCS);
+
+    LIST_FOR_EACH_ENTRY(set, &funcSets, struct OIDFunctionSet, next)
+    {
+        struct OIDFunction *function;
+
+        EnterCriticalSection(&set->cs);
+
+        LIST_FOR_EACH_ENTRY(function, &set->functions, struct OIDFunction, next)
+        {
+            if (function->hModule == hModule)
+            {
+                ret = TRUE;
+                break;
+            }
+        }
+
+        LeaveCriticalSection(&set->cs);
+
+        if (ret) break;
+    }
+
+    LeaveCriticalSection(&funcSetCS);
+
+    return ret;
+}
+
 BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr,
  DWORD dwFlags)
 {
@@ -431,9 +478,12 @@ BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr,
     {
         struct FuncAddr *addr = hFuncAddr;
 
-        CryptMemFree(addr->dllList);
-        FreeLibrary(addr->lib);
-        CryptMemFree(addr);
+        if (!is_module_registered(addr->lib))
+        {
+            CryptMemFree(addr->dllList);
+            FreeLibrary(addr->lib);
+            CryptMemFree(addr);
+        }
     }
     return TRUE;
 }
@@ -652,14 +702,127 @@ error_close_key:
     return TRUE;
 }
 
+/***********************************************************************
+ *             CryptUnregisterOIDInfo (CRYPT32.@)
+ */
+BOOL WINAPI CryptUnregisterOIDInfo(PCCRYPT_OID_INFO info)
+{
+    char *key_name;
+    HKEY root;
+    DWORD err;
+
+    TRACE("(%p)\n", info);
+
+    if (!info || info->cbSize != sizeof(*info) || !info->pszOID)
+    {
+        SetLastError(E_INVALIDARG);
+        return FALSE;
+    }
+
+    err = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllFindOIDInfo", 0, KEY_ALL_ACCESS, &root);
+    if (err != ERROR_SUCCESS)
+    {
+        SetLastError(err);
+        return FALSE;
+    }
+
+    key_name = CryptMemAlloc(strlen(info->pszOID) + 16);
+    if (key_name)
+    {
+        sprintf(key_name, "%s!%u", info->pszOID, info->dwGroupId);
+        err = RegDeleteKeyA(root, key_name);
+    }
+    else
+        err = ERROR_OUTOFMEMORY;
+
+    CryptMemFree(key_name);
+    RegCloseKey(root);
+
+    if (err)
+        SetLastError(err);
+
+    return !err;
+}
+
 /***********************************************************************
  *             CryptRegisterOIDInfo (CRYPT32.@)
  */
-BOOL WINAPI CryptRegisterOIDInfo(PCCRYPT_OID_INFO pInfo, DWORD dwFlags)
+BOOL WINAPI CryptRegisterOIDInfo(PCCRYPT_OID_INFO info, DWORD flags)
 {
-    FIXME("(%p, %x): stub\n", pInfo, dwFlags );
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    char *key_name;
+    HKEY root = 0, key = 0;
+    DWORD err;
+
+    TRACE("(%p, %x)\n", info, flags );
+
+    if (!info || info->cbSize != sizeof(*info) || !info->pszOID)
+    {
+        SetLastError(E_INVALIDARG);
+        return FALSE;
+    }
+
+    if (!info->dwGroupId) return TRUE;
+
+    key_name = CryptMemAlloc(strlen(info->pszOID) + 16);
+    if (!key_name)
+    {
+        err = ERROR_OUTOFMEMORY;
+        goto done;
+    }
+
+    err = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllFindOIDInfo",
+                          0, NULL, 0, KEY_ALL_ACCESS, NULL, &root, NULL);
+    if (err != ERROR_SUCCESS) goto done;
+
+    sprintf(key_name, "%s!%u", info->pszOID, info->dwGroupId);
+    err = RegCreateKeyA(root, key_name, &key);
+    if (err != ERROR_SUCCESS) goto done;
+
+    if (flags)
+    {
+        err = RegSetValueExW(key, flagsW, 0, REG_DWORD, (const BYTE *)&flags, sizeof(flags));
+        if (err != ERROR_SUCCESS) goto done;
+    }
+
+    if (info->pwszName)
+    {
+        err = RegSetValueExW(key, nameW, 0, REG_SZ, (const BYTE *)info->pwszName, (lstrlenW(info->pwszName) + 1) * sizeof(WCHAR));
+        if (err != ERROR_SUCCESS) goto done;
+    }
+
+    if (info->u.Algid)
+    {
+        err = RegSetValueExW(key, algidW, 0, REG_DWORD, (const BYTE *)&info->u.Algid, sizeof(info->u.Algid));
+        if (err != ERROR_SUCCESS) goto done;
+    }
+
+    if (info->ExtraInfo.cbData && info->ExtraInfo.pbData)
+    {
+        err = RegSetValueExW(key, extraW, 0, REG_BINARY, info->ExtraInfo.pbData, info->ExtraInfo.cbData);
+        if (err != ERROR_SUCCESS) goto done;
+    }
+
+    if (info->pwszCNGAlgid)
+    {
+        err = RegSetValueExW(key, cngalgidW, 0, REG_SZ, (const BYTE *)info->pwszCNGAlgid, (lstrlenW(info->pwszCNGAlgid) + 1) * sizeof(WCHAR));
+        if (err != ERROR_SUCCESS) goto done;
+    }
+
+    if (info->pwszCNGExtraAlgid)
+    {
+        err = RegSetValueExW(key, cngextraalgidW, 0, REG_SZ, (const BYTE *)info->pwszCNGExtraAlgid, (lstrlenW(info->pwszCNGExtraAlgid) + 1) * sizeof(WCHAR));
+        if (err != ERROR_SUCCESS) goto done;
+    }
+
+done:
+    CryptMemFree(key_name);
+    if (key) RegCloseKey(key);
+    if (root) RegCloseKey(root);
+
+    if (err)
+        SetLastError(err);
+
+    return !err;
 }
 
 /***********************************************************************
@@ -1405,6 +1568,125 @@ struct OIDInfo {
     struct list entry;
 };
 
+static struct OIDInfo *read_oid_info(HKEY root, char *key_name, DWORD *flags)
+{
+    HKEY key;
+    DWORD len, oid_len, name_len = 0, extra_len = 0, cngalgid_len = 0, cngextra_len = 0, group_id = 0;
+    struct OIDInfo *info;
+    char *p;
+
+    if (RegOpenKeyExA(root, key_name, 0, KEY_READ, &key))
+        return NULL;
+
+    p = strchr(key_name, '!');
+    if (p)
+    {
+        group_id = strtol(p + 1, NULL, 10);
+        *p = 0;
+    }
+
+    oid_len = strlen(key_name) + 1;
+
+    RegQueryValueExW(key, nameW, NULL, NULL, NULL, &name_len);
+    RegQueryValueExW(key, extraW, NULL, NULL, NULL, &extra_len);
+    RegQueryValueExW(key, cngalgidW, NULL, NULL, NULL, &cngalgid_len);
+    RegQueryValueExW(key, cngextraalgidW, NULL, NULL, NULL, &cngextra_len);
+
+    info = CryptMemAlloc(sizeof(*info) + oid_len + name_len + extra_len + cngalgid_len + cngextra_len);
+    if (info)
+    {
+        *flags = 0;
+        len = sizeof(*flags);
+        RegQueryValueExW(key, flagsW, NULL, NULL, (BYTE *)flags, &len);
+
+        memset(info, 0, sizeof(*info));
+        info->info.cbSize = sizeof(info->info);
+
+        p = (char *)(info + 1);
+
+        info->info.pszOID = p;
+        strcpy((char *)info->info.pszOID, key_name);
+        p += oid_len;
+
+        if (name_len)
+        {
+            info->info.pwszName = (WCHAR *)p;
+            RegQueryValueExW(key, nameW, NULL, NULL, (BYTE *)info->info.pwszName, &name_len);
+            p += name_len;
+        }
+
+        info->info.dwGroupId = group_id;
+
+        len = sizeof(info->info.u.Algid);
+        RegQueryValueExW(key, algidW, NULL, NULL, (BYTE *)&info->info.u.Algid, &len);
+
+        if (extra_len)
+        {
+            info->info.ExtraInfo.cbData = extra_len;
+            info->info.ExtraInfo.pbData = (BYTE *)p;
+            RegQueryValueExW(key, extraW, NULL, NULL, info->info.ExtraInfo.pbData, &extra_len);
+            p += extra_len;
+        }
+
+        if (cngalgid_len)
+        {
+            info->info.pwszCNGAlgid = (WCHAR *)p;
+            RegQueryValueExW(key, cngalgidW, NULL, NULL, (BYTE *)info->info.pwszCNGAlgid, &cngalgid_len);
+            p += cngalgid_len;
+        }
+
+        if (cngextra_len)
+        {
+            info->info.pwszCNGExtraAlgid = (WCHAR *)p;
+            RegQueryValueExW(key, cngextraalgidW, NULL, NULL, (BYTE *)info->info.pwszCNGExtraAlgid, &cngalgid_len);
+        }
+    }
+
+    RegCloseKey(key);
+
+    return info;
+}
+
+static void init_registered_oid_info(void)
+{
+    DWORD err, idx;
+    HKEY root;
+
+    err = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllFindOIDInfo",
+                        0, KEY_ALL_ACCESS, &root);
+    if (err != ERROR_SUCCESS) return;
+
+    idx = 0;
+    for (;;)
+    {
+        char key_name[MAX_PATH];
+        struct OIDInfo *info;
+        DWORD flags;
+
+        err = RegEnumKeyA(root, idx++, key_name, MAX_PATH);
+        if (err == ERROR_NO_MORE_ITEMS)
+            break;
+
+        if (err == ERROR_SUCCESS)
+        {
+            if ((info = read_oid_info(root, key_name, &flags)))
+            {
+                TRACE("adding oid %s, name %s, groupid %u, algid %u, extra %u, CNG algid %s, CNG extra %s\n",
+                      debugstr_a(info->info.pszOID), debugstr_w(info->info.pwszName),
+                      info->info.dwGroupId, info->info.u.Algid, info->info.ExtraInfo.cbData,
+                      debugstr_w(info->info.pwszCNGAlgid), debugstr_w(info->info.pwszCNGExtraAlgid));
+
+                if (flags & CRYPT_INSTALL_OID_INFO_BEFORE_FLAG)
+                    list_add_head(&oidInfo, &info->entry);
+                else
+                    list_add_tail(&oidInfo, &info->entry);
+            }
+        }
+    }
+
+    RegCloseKey(root);
+}
+
 static void init_oid_info(void)
 {
     DWORD i;
@@ -1632,6 +1914,7 @@ DWORD WINAPI CertOIDToAlgId(LPCSTR pszObjId)
 void crypt_oid_init(void)
 {
     init_oid_info();
+    init_registered_oid_info();
 }
 
 void crypt_oid_free(void)
index 532d520..cdf4cda 100644 (file)
@@ -58,7 +58,7 @@ reactos/dll/win32/comctl32            # Synced to Wine-3.0
 reactos/dll/win32/comdlg32            # Synced to WineStaging-4.0
 reactos/dll/win32/compstui            # Synced to WineStaging-3.3
 reactos/dll/win32/credui              # Synced to WineStaging-4.0
-reactos/dll/win32/crypt32             # Synced to WineStaging-3.17
+reactos/dll/win32/crypt32             # Synced to WineStaging-4.0
 reactos/dll/win32/cryptdlg            # Synced to WineStaging-3.3
 reactos/dll/win32/cryptdll            # Synced to WineStaging-3.3
 reactos/dll/win32/cryptnet            # Synced to WineStaging-3.3