crypt32: Implement CertCreateCertificateChainEngine and CertFreeCertificateChainEngine.
This commit is contained in:
parent
fd3fcc0bdd
commit
b633d6a382
|
@ -10,6 +10,7 @@ IMPORTS = user32 advapi32 kernel32 ntdll
|
|||
C_SRCS = \
|
||||
base64.c \
|
||||
cert.c \
|
||||
chain.c \
|
||||
crl.c \
|
||||
context.c \
|
||||
decode.c \
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright 2006 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wincrypt.h"
|
||||
#include "wine/debug.h"
|
||||
#include "crypt32_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
||||
|
||||
/* This represents a subset of a certificate chain engine: it doesn't include
|
||||
* the "hOther" store described by MSDN, because I'm not sure how that's used.
|
||||
* It also doesn't include the "hTrust" store, because I don't yet implement
|
||||
* CTLs or complex certificate chains.
|
||||
*/
|
||||
typedef struct _CertificateChainEngine
|
||||
{
|
||||
LONG ref;
|
||||
HCERTSTORE hRoot;
|
||||
HCERTSTORE hWorld;
|
||||
DWORD dwFlags;
|
||||
DWORD dwUrlRetrievalTimeout;
|
||||
DWORD MaximumCachedCertificates;
|
||||
DWORD CycleDetectionModulus;
|
||||
} CertificateChainEngine, *PCertificateChainEngine;
|
||||
|
||||
static inline void CRYPT_AddStoresToCollection(HCERTSTORE collection,
|
||||
DWORD cStores, HCERTSTORE *stores)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
for (i = 0; i < cStores; i++)
|
||||
CertAddStoreToCollection(collection, stores[i], 0, 0);
|
||||
}
|
||||
|
||||
static inline void CRYPT_CloseStores(DWORD cStores, HCERTSTORE *stores)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
for (i = 0; i < cStores; i++)
|
||||
CertCloseStore(stores[i], 0);
|
||||
}
|
||||
|
||||
static const WCHAR rootW[] = { 'R','o','o','t',0 };
|
||||
|
||||
BOOL CRYPT_CheckRestrictedRoot(HCERTSTORE store)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
|
||||
if (store)
|
||||
{
|
||||
HCERTSTORE rootStore = CertOpenSystemStoreW(0, rootW);
|
||||
PCCERT_CONTEXT cert = NULL, check;
|
||||
BYTE hash[20];
|
||||
DWORD size;
|
||||
|
||||
do {
|
||||
cert = CertEnumCertificatesInStore(store, cert);
|
||||
if (cert)
|
||||
{
|
||||
size = sizeof(hash);
|
||||
|
||||
ret = CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID,
|
||||
hash, &size);
|
||||
if (ret)
|
||||
{
|
||||
CRYPT_HASH_BLOB blob = { sizeof(hash), hash };
|
||||
|
||||
check = CertFindCertificateInStore(rootStore,
|
||||
cert->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
|
||||
NULL);
|
||||
if (!check)
|
||||
ret = FALSE;
|
||||
else
|
||||
CertFreeCertificateContext(check);
|
||||
}
|
||||
}
|
||||
} while (ret && cert);
|
||||
if (cert)
|
||||
CertFreeCertificateContext(cert);
|
||||
CertCloseStore(rootStore, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI CertCreateCertificateChainEngine(PCERT_CHAIN_ENGINE_CONFIG pConfig,
|
||||
HCERTCHAINENGINE *phChainEngine)
|
||||
{
|
||||
static const WCHAR caW[] = { 'C','A',0 };
|
||||
static const WCHAR myW[] = { 'M','y',0 };
|
||||
static const WCHAR trustW[] = { 'T','r','u','s','t',0 };
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %p)\n", pConfig, phChainEngine);
|
||||
|
||||
if (pConfig->cbSize != sizeof(*pConfig))
|
||||
{
|
||||
SetLastError(E_INVALIDARG);
|
||||
return FALSE;
|
||||
}
|
||||
*phChainEngine = NULL;
|
||||
ret = CRYPT_CheckRestrictedRoot(pConfig->hRestrictedRoot);
|
||||
if (ret)
|
||||
{
|
||||
PCertificateChainEngine engine =
|
||||
CryptMemAlloc(sizeof(CertificateChainEngine));
|
||||
|
||||
if (engine)
|
||||
{
|
||||
HCERTSTORE worldStores[4];
|
||||
|
||||
engine->ref = 1;
|
||||
if (pConfig->hRestrictedRoot)
|
||||
engine->hRoot = CertDuplicateStore(pConfig->hRestrictedRoot);
|
||||
else
|
||||
engine->hRoot = CertOpenSystemStoreW(0, rootW);
|
||||
engine->hWorld = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
worldStores[0] = CertDuplicateStore(engine->hRoot);
|
||||
worldStores[1] = CertOpenSystemStoreW(0, caW);
|
||||
worldStores[2] = CertOpenSystemStoreW(0, myW);
|
||||
worldStores[3] = CertOpenSystemStoreW(0, trustW);
|
||||
CRYPT_AddStoresToCollection(engine->hWorld,
|
||||
sizeof(worldStores) / sizeof(worldStores[0]), worldStores);
|
||||
CRYPT_AddStoresToCollection(engine->hWorld,
|
||||
pConfig->cAdditionalStore, pConfig->rghAdditionalStore);
|
||||
CRYPT_CloseStores(sizeof(worldStores) / sizeof(worldStores[0]),
|
||||
worldStores);
|
||||
engine->dwFlags = pConfig->dwFlags;
|
||||
engine->dwUrlRetrievalTimeout = pConfig->dwUrlRetrievalTimeout;
|
||||
engine->MaximumCachedCertificates =
|
||||
pConfig->MaximumCachedCertificates;
|
||||
engine->CycleDetectionModulus = pConfig->CycleDetectionModulus;
|
||||
*phChainEngine = (HCERTCHAINENGINE)engine;
|
||||
ret = TRUE;
|
||||
}
|
||||
else
|
||||
ret = FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WINAPI CertFreeCertificateChainEngine(HCERTCHAINENGINE hChainEngine)
|
||||
{
|
||||
PCertificateChainEngine engine = (PCertificateChainEngine)hChainEngine;
|
||||
|
||||
TRACE("(%p)\n", hChainEngine);
|
||||
|
||||
if (InterlockedDecrement(&engine->ref) == 0)
|
||||
{
|
||||
CertCloseStore(engine->hWorld, 0);
|
||||
CertCloseStore(engine->hRoot, 0);
|
||||
CryptMemFree(engine);
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
@ stdcall CertControlStore(long long long ptr)
|
||||
@ stdcall CertCreateCRLContext(long ptr long)
|
||||
@ stdcall CertCreateCTLContext(long ptr long)
|
||||
@ stub CertCreateCertificateChainEngine
|
||||
@ stdcall CertCreateCertificateChainEngine(ptr ptr)
|
||||
@ stdcall CertCreateCertificateContext(long ptr long)
|
||||
@ stdcall CertCreateSelfSignCertificate(long ptr long ptr ptr ptr ptr ptr)
|
||||
@ stdcall CertDeleteCRLFromStore(ptr)
|
||||
|
@ -45,7 +45,7 @@
|
|||
@ stdcall CertFreeCRLContext(ptr)
|
||||
@ stdcall CertFreeCTLContext(ptr)
|
||||
@ stub CertFreeCertificateChain
|
||||
@ stub CertFreeCertificateChainEngine
|
||||
@ stdcall CertFreeCertificateChainEngine(ptr)
|
||||
@ stdcall CertFreeCertificateContext(ptr)
|
||||
@ stdcall CertGetCRLContextProperty(ptr long ptr ptr)
|
||||
@ stdcall CertGetCRLFromStore(ptr ptr ptr ptr)
|
||||
|
|
|
@ -8,6 +8,7 @@ IMPORTS = crypt32 advapi32 kernel32
|
|||
CTESTS = \
|
||||
base64.c \
|
||||
cert.c \
|
||||
chain.c \
|
||||
crl.c \
|
||||
encode.c \
|
||||
main.c \
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* crypt32 certificate chain functions tests
|
||||
*
|
||||
* Copyright 2006 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
static const BYTE selfSignedCert[] = {
|
||||
0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
|
||||
0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
|
||||
0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
|
||||
0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
|
||||
0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
|
||||
0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
|
||||
0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
|
||||
0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
|
||||
0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
|
||||
0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
|
||||
0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
|
||||
0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
|
||||
0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
|
||||
0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
|
||||
0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
|
||||
0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
|
||||
0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
|
||||
0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
|
||||
0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
|
||||
0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
|
||||
0xa8, 0x76, 0x57, 0x92, 0x36 };
|
||||
|
||||
static void testCreateCertChainEngine(void)
|
||||
{
|
||||
BOOL ret;
|
||||
CERT_CHAIN_ENGINE_CONFIG config = { 0 };
|
||||
HCERTCHAINENGINE engine;
|
||||
HCERTSTORE store;
|
||||
|
||||
/* Crash
|
||||
ret = CertCreateCertificateChainEngine(NULL, NULL);
|
||||
ret = CertCreateCertificateChainEngine(NULL, &engine);
|
||||
*/
|
||||
ret = CertCreateCertificateChainEngine(&config, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
ret = CertCreateCertificateChainEngine(&config, &engine);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
/* Crashes
|
||||
config.cbSize = sizeof(config);
|
||||
ret = CertCreateCertificateChainEngine(&config, NULL);
|
||||
*/
|
||||
config.cbSize = sizeof(config);
|
||||
ret = CertCreateCertificateChainEngine(&config, &engine);
|
||||
ok(ret, "CertCreateCertificateChainEngine failed: %08lx\n", GetLastError());
|
||||
CertFreeCertificateChainEngine(engine);
|
||||
config.dwFlags = 0xff000000;
|
||||
ret = CertCreateCertificateChainEngine(&config, &engine);
|
||||
ok(ret, "CertCreateCertificateChainEngine failed: %08lx\n", GetLastError());
|
||||
CertFreeCertificateChainEngine(engine);
|
||||
|
||||
/* Creating a cert with no root certs at all is allowed.. */
|
||||
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
config.hRestrictedRoot = store;
|
||||
ret = CertCreateCertificateChainEngine(&config, &engine);
|
||||
ok(ret, "CertCreateCertificateChainEngine failed: %08lx\n", GetLastError());
|
||||
CertFreeCertificateChainEngine(engine);
|
||||
|
||||
/* but creating one with a restricted root with a cert that isn't a member
|
||||
* of the Root store isn't allowed.
|
||||
*/
|
||||
CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, selfSignedCert,
|
||||
sizeof(selfSignedCert), CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ret = CertCreateCertificateChainEngine(&config, &engine);
|
||||
ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
|
||||
"Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
|
||||
|
||||
CertCloseStore(store, 0);
|
||||
}
|
||||
|
||||
START_TEST(chain)
|
||||
{
|
||||
testCreateCertChainEngine();
|
||||
}
|
Loading…
Reference in New Issue