From fb3d16f5b76a6785247dbe9a23e7c1c6ef3298a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Thu, 17 Nov 2005 20:59:05 +0000 Subject: [PATCH] Remove in preparation for proper vendor drop svn path=/trunk/; revision=19309 --- reactos/lib/crypt32/cert.c | 3315 -------------- reactos/lib/crypt32/crypt32.def | 36 - reactos/lib/crypt32/crypt32.rc | 7 - reactos/lib/crypt32/crypt32.xml | 14 - reactos/lib/crypt32/crypt32_private.h | 27 - reactos/lib/crypt32/encode.c | 5688 ------------------------- reactos/lib/crypt32/main.c | 341 -- reactos/lib/crypt32/precomp.h | 20 - reactos/lib/crypt32/protectdata.c | 1128 ----- 9 files changed, 10576 deletions(-) delete mode 100644 reactos/lib/crypt32/cert.c delete mode 100644 reactos/lib/crypt32/crypt32.def delete mode 100644 reactos/lib/crypt32/crypt32.rc delete mode 100644 reactos/lib/crypt32/crypt32.xml delete mode 100644 reactos/lib/crypt32/crypt32_private.h delete mode 100644 reactos/lib/crypt32/encode.c delete mode 100644 reactos/lib/crypt32/main.c delete mode 100644 reactos/lib/crypt32/precomp.h delete mode 100644 reactos/lib/crypt32/protectdata.c diff --git a/reactos/lib/crypt32/cert.c b/reactos/lib/crypt32/cert.c deleted file mode 100644 index 744f9c3cb53..00000000000 --- a/reactos/lib/crypt32/cert.c +++ /dev/null @@ -1,3315 +0,0 @@ -/* - * Copyright 2002 - Mike McCormack for CodeWeavers - * Copyright 2004,2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * FIXME: - * - As you can see in the stubs below, support for CRLs and CTLs is missing. - * Mostly this should be copy-paste work, and some code (e.g. extended - * properties) could be shared between them. - * - Opening a cert store provider should be morphed to support loading - * external DLLs. - * - The concept of physical stores and locations isn't implemented. (This - * doesn't mean registry stores et al aren't implemented. See the PSDK for - * registering and enumerating physical stores and locations.) - * - Many flags, options and whatnot are unimplemented. - */ - -#include "precomp.h" - -WINE_DEFAULT_DEBUG_CHANNEL(crypt); - -#define WINE_CRYPTCERTSTORE_MAGIC 0x74726563 -/* The following aren't defined in wincrypt.h, as they're "reserved" */ -#define CERT_CERT_PROP_ID 32 -#define CERT_CRL_PROP_ID 33 -#define CERT_CTL_PROP_ID 34 - -/* Some typedefs that make it easier to abstract which type of context we're - * working with. - */ -typedef const void *(WINAPI *CreateContextFunc)(DWORD dwCertEncodingType, - const BYTE *pbCertEncoded, DWORD cbCertEncoded); -typedef BOOL (WINAPI *AddContextToStoreFunc)(HCERTSTORE hCertStore, - const void *context, DWORD dwAddDisposition, const void **ppStoreContext); -typedef BOOL (WINAPI *AddEncodedContextToStoreFunc)(HCERTSTORE hCertStore, - DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded, - DWORD dwAddDisposition, const void **ppContext); -typedef const void *(WINAPI *EnumContextsInStoreFunc)(HCERTSTORE hCertStore, - const void *pPrevContext); -typedef BOOL (WINAPI *GetContextPropertyFunc)(const void *context, - DWORD dwPropID, void *pvData, DWORD *pcbData); -typedef BOOL (WINAPI *SetContextPropertyFunc)(const void *context, - DWORD dwPropID, DWORD dwFlags, const void *pvData); -typedef BOOL (WINAPI *SerializeElementFunc)(const void *context, DWORD dwFlags, - BYTE *pbElement, DWORD *pcbElement); -typedef BOOL (WINAPI *FreeContextFunc)(const void *context); -typedef BOOL (WINAPI *DeleteContextFunc)(const void *context); - -/* An abstract context (certificate, CRL, or CTL) interface */ -typedef struct _WINE_CONTEXT_INTERFACE -{ - CreateContextFunc create; - AddContextToStoreFunc addContextToStore; - AddEncodedContextToStoreFunc addEncodedToStore; - EnumContextsInStoreFunc enumContextsInStore; - GetContextPropertyFunc getProp; - SetContextPropertyFunc setProp; - SerializeElementFunc serialize; - FreeContextFunc free; - DeleteContextFunc deleteFromStore; -} WINE_CONTEXT_INTERFACE, *PWINE_CONTEXT_INTERFACE; - -static const WINE_CONTEXT_INTERFACE gCertInterface = { - (CreateContextFunc)CertCreateCertificateContext, - (AddContextToStoreFunc)CertAddCertificateContextToStore, - (AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore, - (EnumContextsInStoreFunc)CertEnumCertificatesInStore, - (GetContextPropertyFunc)CertGetCertificateContextProperty, - (SetContextPropertyFunc)CertSetCertificateContextProperty, - (SerializeElementFunc)CertSerializeCertificateStoreElement, - (FreeContextFunc)CertFreeCertificateContext, - (DeleteContextFunc)CertDeleteCertificateFromStore, -}; - -static const WINE_CONTEXT_INTERFACE gCRLInterface = { - (CreateContextFunc)CertCreateCRLContext, - (AddContextToStoreFunc)CertAddCRLContextToStore, - (AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore, - (EnumContextsInStoreFunc)CertEnumCRLsInStore, - (GetContextPropertyFunc)CertGetCRLContextProperty, - (SetContextPropertyFunc)CertSetCRLContextProperty, - (SerializeElementFunc)CertSerializeCRLStoreElement, - (FreeContextFunc)CertFreeCRLContext, - (DeleteContextFunc)CertDeleteCRLFromStore, -}; - -static const WINE_CONTEXT_INTERFACE gCTLInterface = { - (CreateContextFunc)CertCreateCTLContext, - (AddContextToStoreFunc)CertAddCTLContextToStore, - (AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore, - (EnumContextsInStoreFunc)CertEnumCTLsInStore, - (GetContextPropertyFunc)CertGetCTLContextProperty, - (SetContextPropertyFunc)CertSetCTLContextProperty, - (SerializeElementFunc)CertSerializeCTLStoreElement, - (FreeContextFunc)CertFreeCTLContext, - (DeleteContextFunc)CertDeleteCTLFromStore, -}; - -struct WINE_CRYPTCERTSTORE; - -typedef struct WINE_CRYPTCERTSTORE * (*StoreOpenFunc)(HCRYPTPROV hCryptProv, - DWORD dwFlags, const void *pvPara); - -struct _WINE_CERT_CONTEXT_REF; - -/* Called to enumerate the next certificate in a store. The returned pointer - * must be newly allocated (via CryptMemAlloc): CertFreeCertificateContext - * frees it. - */ -typedef struct _WINE_CERT_CONTEXT_REF * (*EnumCertFunc) - (struct WINE_CRYPTCERTSTORE *store, struct _WINE_CERT_CONTEXT_REF *pPrev); - -struct _WINE_CERT_CONTEXT; - -/* Called to create a new reference to an existing cert context. Should call - * CRYPT_InitCertRef to make sure the reference count is properly updated. - * If the store does not provide any additional allocated data (that is, does - * not need to implement a FreeCertFunc), it may use CRYPT_CreateCertRef for - * this. - */ -typedef struct _WINE_CERT_CONTEXT_REF * (*CreateRefFunc) - (struct _WINE_CERT_CONTEXT *context, HCERTSTORE store); - -/* Optional, called when a cert context reference is being freed. Don't free - * the ref pointer itself, CertFreeCertificateContext does that. - */ -typedef void (*FreeCertFunc)(struct _WINE_CERT_CONTEXT_REF *ref); - -typedef enum _CertStoreType { - StoreTypeMem, - StoreTypeCollection, - StoreTypeReg, - StoreTypeDummy, -} CertStoreType; - -/* A cert store is polymorphic through the use of function pointers. A type - * is still needed to distinguish collection stores from other types. - * On the function pointers: - * - closeStore is called when the store's ref count becomes 0 - * - addCert is called with a PWINE_CERT_CONTEXT as the second parameter - * - control is optional, but should be implemented by any store that supports - * persistence - */ -typedef struct WINE_CRYPTCERTSTORE -{ - DWORD dwMagic; - LONG ref; - DWORD dwOpenFlags; - HCRYPTPROV cryptProv; - CertStoreType type; - PFN_CERT_STORE_PROV_CLOSE closeStore; - PFN_CERT_STORE_PROV_WRITE_CERT addCert; - CreateRefFunc createCertRef; - EnumCertFunc enumCert; - PFN_CERT_STORE_PROV_DELETE_CERT deleteCert; - FreeCertFunc freeCert; /* optional */ - PFN_CERT_STORE_PROV_CONTROL control; /* optional */ -} WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE; - -/* A certificate context has pointers to data that are owned by this module, - * so rather than duplicate the data every time a certificate context is - * copied, I keep a reference count to the data. Thus I have two data - * structures, the "true" certificate context (that has the reference count) - * and a reference certificate context, that has a pointer to the true context. - * Each one can be cast to a PCERT_CONTEXT, though you'll usually be dealing - * with the reference version. - */ -typedef struct _WINE_CERT_CONTEXT -{ - CERT_CONTEXT cert; - LONG ref; - CRITICAL_SECTION cs; - struct list extendedProperties; -} WINE_CERT_CONTEXT, *PWINE_CERT_CONTEXT; - -typedef struct _WINE_CERT_CONTEXT_REF -{ - CERT_CONTEXT cert; - WINE_CERT_CONTEXT *context; -} WINE_CERT_CONTEXT_REF, *PWINE_CERT_CONTEXT_REF; - -/* An extended certificate property in serialized form is prefixed by this - * header. - */ -typedef struct _WINE_CERT_PROP_HEADER -{ - DWORD propID; - DWORD unknown; /* always 1 */ - DWORD cb; -} WINE_CERT_PROP_HEADER, *PWINE_CERT_PROP_HEADER; - -/* Stores an extended property in a cert. */ -typedef struct _WINE_CERT_PROPERTY -{ - WINE_CERT_PROP_HEADER hdr; - LPBYTE pbData; - struct list entry; -} WINE_CERT_PROPERTY, *PWINE_CERT_PROPERTY; - -/* A mem store has a list of these. They're also returned by the mem store - * during enumeration. - */ -typedef struct _WINE_CERT_LIST_ENTRY -{ - WINE_CERT_CONTEXT_REF cert; - struct list entry; -} WINE_CERT_LIST_ENTRY, *PWINE_CERT_LIST_ENTRY; - -typedef struct _WINE_MEMSTORE -{ - WINECRYPT_CERTSTORE hdr; - CRITICAL_SECTION cs; - struct list certs; -} WINE_MEMSTORE, *PWINE_MEMSTORE; - -typedef struct _WINE_HASH_TO_DELETE -{ - BYTE hash[20]; - struct list entry; -} WINE_HASH_TO_DELETE, *PWINE_HASH_TO_DELETE; - -/* Returned by a reg store during enumeration. */ -typedef struct _WINE_REG_CERT_CONTEXT -{ - WINE_CERT_CONTEXT_REF cert; - PWINE_CERT_CONTEXT_REF childContext; -} WINE_REG_CERT_CONTEXT, *PWINE_REG_CERT_CONTEXT; - -typedef struct _WINE_REGSTORE -{ - WINECRYPT_CERTSTORE hdr; - PWINECRYPT_CERTSTORE memStore; - HKEY key; - BOOL dirty; - CRITICAL_SECTION cs; - struct list certsToDelete; -} WINE_REGSTORE, *PWINE_REGSTORE; - -typedef struct _WINE_STORE_LIST_ENTRY -{ - PWINECRYPT_CERTSTORE store; - DWORD dwUpdateFlags; - DWORD dwPriority; - struct list entry; -} WINE_STORE_LIST_ENTRY, *PWINE_STORE_LIST_ENTRY; - -/* Returned by a collection store during enumeration. - * Note: relies on the list entry being valid after use, which a number of - * conditions might make untrue (reentrancy, closing a collection store before - * continuing an enumeration on it, ...). The tests seem to indicate this - * sort of unsafety is okay, since Windows isn't well-behaved in these - * scenarios either. - */ -typedef struct _WINE_COLLECTION_CERT_CONTEXT -{ - WINE_CERT_CONTEXT_REF cert; - PWINE_STORE_LIST_ENTRY entry; - PWINE_CERT_CONTEXT_REF childContext; -} WINE_COLLECTION_CERT_CONTEXT, *PWINE_COLLECTION_CERT_CONTEXT; - -typedef struct _WINE_COLLECTIONSTORE -{ - WINECRYPT_CERTSTORE hdr; - CRITICAL_SECTION cs; - struct list stores; -} WINE_COLLECTIONSTORE, *PWINE_COLLECTIONSTORE; - -/* Like CertGetCertificateContextProperty, but operates directly on the - * WINE_CERT_CONTEXT. Doesn't support special-case properties, since they - * are handled by CertGetCertificateContextProperty, and are particular to the - * store in which the property exists (which is separate from the context.) - */ -static BOOL WINAPI CRYPT_GetCertificateContextProperty( - PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData); - -/* Like CertSetCertificateContextProperty, but operates directly on the - * WINE_CERT_CONTEXT. Doesn't handle special cases, since they're handled by - * CertSetCertificateContextProperty anyway. - */ -static BOOL WINAPI CRYPT_SetCertificateContextProperty( - PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData); - -/* Helper function for store reading functions and - * CertAddSerializedElementToStore. Returns a context of the appropriate type - * if it can, or NULL otherwise. Doesn't validate any of the properties in - * the serialized context (for example, bad hashes are retained.) - * *pdwContentType is set to the type of the returned context. - */ -static const void * WINAPI CRYPT_ReadSerializedElement(const BYTE *pbElement, - DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType); - -/* filter for page-fault exceptions */ -static WINE_EXCEPTION_FILTER(page_fault) -{ - if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) - return EXCEPTION_EXECUTE_HANDLER; - return EXCEPTION_CONTINUE_SEARCH; -} - -static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv, - DWORD dwFlags, CertStoreType type) -{ - store->ref = 1; - store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC; - store->type = type; - if (!hCryptProv) - { - hCryptProv = CRYPT_GetDefaultProvider(); - dwFlags |= CERT_STORE_NO_CRYPT_RELEASE_FLAG; - } - store->cryptProv = hCryptProv; - store->dwOpenFlags = dwFlags; -} - -/* Initializes the reference ref to point to pCertContext, which is assumed to - * be a PWINE_CERT_CONTEXT, and increments pCertContext's reference count. - * Also sets the hCertStore member of the reference to store. - */ -static void CRYPT_InitCertRef(PWINE_CERT_CONTEXT_REF ref, - PWINE_CERT_CONTEXT context, HCERTSTORE store) -{ - TRACE("(%p, %p)\n", ref, context); - memcpy(&ref->cert, context, sizeof(ref->cert)); - ref->context = context; - InterlockedIncrement(&context->ref); - ref->cert.hCertStore = store; -} - -static PWINE_CERT_CONTEXT_REF CRYPT_CreateCertRef(PWINE_CERT_CONTEXT context, - HCERTSTORE store) -{ - PWINE_CERT_CONTEXT_REF pCertRef = CryptMemAlloc( - sizeof(WINE_CERT_CONTEXT_REF)); - - if (pCertRef) - CRYPT_InitCertRef(pCertRef, context, store); - return pCertRef; -} - -static BOOL WINAPI CRYPT_MemAddCert(HCERTSTORE store, PCCERT_CONTEXT pCert, - DWORD dwAddDisposition) -{ - WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; - BOOL add = FALSE, ret; - - TRACE("(%p, %p, %ld)\n", store, pCert, dwAddDisposition); - - switch (dwAddDisposition) - { - case CERT_STORE_ADD_ALWAYS: - add = TRUE; - break; - case CERT_STORE_ADD_NEW: - { - BYTE hashToAdd[20], hash[20]; - DWORD size = sizeof(hashToAdd); - - ret = CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)pCert, - CERT_HASH_PROP_ID, hashToAdd, &size); - if (ret) - { - PWINE_CERT_LIST_ENTRY cursor; - - /* Add if no cert with the same hash is found. */ - add = TRUE; - EnterCriticalSection(&ms->cs); - LIST_FOR_EACH_ENTRY(cursor, &ms->certs, WINE_CERT_LIST_ENTRY, entry) - { - size = sizeof(hash); - ret = CertGetCertificateContextProperty(&cursor->cert.cert, - CERT_HASH_PROP_ID, hash, &size); - if (ret && !memcmp(hashToAdd, hash, size)) - { - TRACE("found matching certificate, not adding\n"); - SetLastError(CRYPT_E_EXISTS); - add = FALSE; - break; - } - } - LeaveCriticalSection(&ms->cs); - } - break; - } - case CERT_STORE_ADD_REPLACE_EXISTING: - { - BYTE hashToAdd[20], hash[20]; - DWORD size = sizeof(hashToAdd); - - add = TRUE; - ret = CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)pCert, - CERT_HASH_PROP_ID, hashToAdd, &size); - if (ret) - { - PWINE_CERT_LIST_ENTRY cursor, next; - - /* Look for existing cert to delete */ - EnterCriticalSection(&ms->cs); - LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &ms->certs, - WINE_CERT_LIST_ENTRY, entry) - { - size = sizeof(hash); - ret = CertGetCertificateContextProperty(&cursor->cert.cert, - CERT_HASH_PROP_ID, hash, &size); - if (ret && !memcmp(hashToAdd, hash, size)) - { - TRACE("found matching certificate, replacing\n"); - list_remove(&cursor->entry); - CertFreeCertificateContext((PCCERT_CONTEXT)cursor); - break; - } - } - LeaveCriticalSection(&ms->cs); - } - break; - } - default: - FIXME("Unimplemented add disposition %ld\n", dwAddDisposition); - add = FALSE; - } - if (add) - { - PWINE_CERT_LIST_ENTRY entry = CryptMemAlloc( - sizeof(WINE_CERT_LIST_ENTRY)); - - if (entry) - { - TRACE("adding %p\n", entry); - CRYPT_InitCertRef(&entry->cert, (PWINE_CERT_CONTEXT)pCert, store); - list_init(&entry->entry); - EnterCriticalSection(&ms->cs); - list_add_tail(&ms->certs, &entry->entry); - LeaveCriticalSection(&ms->cs); - ret = TRUE; - } - else - ret = FALSE; - } - else - ret = FALSE; - return ret; -} - -static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, - PWINE_CERT_CONTEXT_REF pPrev) -{ - WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; - PWINE_CERT_LIST_ENTRY prevEntry = (PWINE_CERT_LIST_ENTRY)pPrev, ret; - struct list *listNext; - - TRACE("(%p, %p)\n", store, pPrev); - EnterCriticalSection(&ms->cs); - if (prevEntry) - { - listNext = list_next(&ms->certs, &prevEntry->entry); - CertFreeCertificateContext((PCCERT_CONTEXT)pPrev); - } - else - listNext = list_next(&ms->certs, &ms->certs); - if (listNext) - { - ret = CryptMemAlloc(sizeof(WINE_CERT_LIST_ENTRY)); - memcpy(ret, LIST_ENTRY(listNext, WINE_CERT_LIST_ENTRY, entry), - sizeof(WINE_CERT_LIST_ENTRY)); - InterlockedIncrement(&ret->cert.context->ref); - } - else - { - SetLastError(CRYPT_E_NOT_FOUND); - ret = NULL; - } - LeaveCriticalSection(&ms->cs); - - TRACE("returning %p\n", ret); - return (PWINE_CERT_CONTEXT_REF)ret; -} - -static BOOL WINAPI CRYPT_MemDeleteCert(HCERTSTORE hCertStore, - PCCERT_CONTEXT pCertContext, DWORD dwFlags) -{ - WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore; - WINE_CERT_CONTEXT_REF *ref = (WINE_CERT_CONTEXT_REF *)pCertContext; - PWINE_CERT_LIST_ENTRY cert, next; - BOOL ret; - - /* Find the entry associated with the passed-in context, since the - * passed-in context may not be a list entry itself (e.g. if it came from - * CertDuplicateCertificateContext.) Pointing to the same context is - * a sufficient test of equality. - */ - EnterCriticalSection(&store->cs); - LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs, WINE_CERT_LIST_ENTRY, - entry) - { - if (cert->cert.context == ref->context) - { - TRACE("removing %p\n", cert); - /* FIXME: this isn't entirely thread-safe, the entry itself isn't - * protected. - */ - list_remove(&cert->entry); - cert->entry.prev = cert->entry.next = &store->certs; - break; - } - } - ret = TRUE; - LeaveCriticalSection(&store->cs); - return ret; -} - -static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) -{ - WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore; - PWINE_CERT_LIST_ENTRY cert, next; - - TRACE("(%p, %08lx)\n", store, dwFlags); - if (dwFlags) - FIXME("Unimplemented flags: %08lx\n", dwFlags); - - /* Note that CertFreeCertificateContext calls HeapFree on the passed-in - * pointer if its ref-count reaches zero. That's okay here because there - * aren't any allocated data outside of the WINE_CERT_CONTEXT_REF portion - * of the CertListEntry. - */ - LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs, WINE_CERT_LIST_ENTRY, - entry) - { - TRACE("removing %p\n", cert); - list_remove(&cert->entry); - CertFreeCertificateContext((PCCERT_CONTEXT)cert); - } - DeleteCriticalSection(&store->cs); - CryptMemFree(store); -} - -static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv, - DWORD dwFlags, const void *pvPara) -{ - PWINE_MEMSTORE store; - - TRACE("(%ld, %08lx, %p)\n", hCryptProv, dwFlags, pvPara); - - if (dwFlags & CERT_STORE_DELETE_FLAG) - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - store = NULL; - } - else - { - store = CryptMemAlloc(sizeof(WINE_MEMSTORE)); - if (store) - { - memset(store, 0, sizeof(WINE_MEMSTORE)); - CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags, StoreTypeMem); - store->hdr.closeStore = CRYPT_MemCloseStore; - store->hdr.addCert = CRYPT_MemAddCert; - store->hdr.createCertRef = CRYPT_CreateCertRef; - store->hdr.enumCert = CRYPT_MemEnumCert; - store->hdr.deleteCert = CRYPT_MemDeleteCert; - store->hdr.freeCert = NULL; - InitializeCriticalSection(&store->cs); - list_init(&store->certs); - } - } - return (PWINECRYPT_CERTSTORE)store; -} - -static BOOL WINAPI CRYPT_CollectionAddCert(HCERTSTORE store, - PCCERT_CONTEXT pCert, DWORD dwAddDisposition) -{ - PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; - PWINE_STORE_LIST_ENTRY entry, next; - BOOL ret; - - TRACE("(%p, %p, %ld)\n", store, pCert, dwAddDisposition); - - ret = FALSE; - EnterCriticalSection(&cs->cs); - LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY, - entry) - { - if (entry->dwUpdateFlags & CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG) - { - ret = entry->store->addCert(entry->store, pCert, dwAddDisposition); - break; - } - } - LeaveCriticalSection(&cs->cs); - SetLastError(ret ? ERROR_SUCCESS : HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)); - return ret; -} - -static PWINE_CERT_CONTEXT_REF CRYPT_CollectionCreateCertRef( - PWINE_CERT_CONTEXT context, HCERTSTORE store) -{ - PWINE_COLLECTION_CERT_CONTEXT ret = CryptMemAlloc( - sizeof(WINE_COLLECTION_CERT_CONTEXT)); - - if (ret) - { - /* Initialize to empty for now, just make sure the size is right */ - CRYPT_InitCertRef((PWINE_CERT_CONTEXT_REF)ret, context, store); - ret->entry = NULL; - ret->childContext = NULL; - } - return (PWINE_CERT_CONTEXT_REF)ret; -} - -static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD dwFlags) -{ - PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; - PWINE_STORE_LIST_ENTRY entry, next; - - TRACE("(%p, %08lx)\n", store, dwFlags); - - LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY, - entry) - { - TRACE("closing %p\n", entry); - CertCloseStore((HCERTSTORE)entry->store, dwFlags); - CryptMemFree(entry); - } - DeleteCriticalSection(&cs->cs); - CryptMemFree(cs); -} - -/* Advances a collection enumeration by one cert, if possible, where advancing - * means: - * - calling the current store's enumeration function once, and returning - * the enumerated cert if one is returned - * - moving to the next store if the current store has no more items, and - * recursively calling itself to get the next item. - * Returns NULL if the collection contains no more items or on error. - * Assumes the collection store's lock is held. - */ -static PWINE_COLLECTION_CERT_CONTEXT CRYPT_CollectionAdvanceEnum( - PWINE_COLLECTIONSTORE store, PWINE_STORE_LIST_ENTRY storeEntry, - PWINE_COLLECTION_CERT_CONTEXT pPrev) -{ - PWINE_COLLECTION_CERT_CONTEXT ret; - PWINE_CERT_CONTEXT_REF child; - - TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev); - - if (pPrev) - { - child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store, - pPrev->childContext); - if (child) - { - ret = pPrev; - memcpy(&ret->cert, child, sizeof(WINE_CERT_CONTEXT_REF)); - ret->cert.cert.hCertStore = (HCERTSTORE)store; - InterlockedIncrement(&ret->cert.context->ref); - ret->childContext = child; - } - else - { - struct list *storeNext = list_next(&store->stores, - &storeEntry->entry); - - pPrev->childContext = NULL; - CertFreeCertificateContext((PCCERT_CONTEXT)pPrev); - if (storeNext) - { - storeEntry = LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY, - entry); - ret = CRYPT_CollectionAdvanceEnum(store, storeEntry, NULL); - } - else - { - SetLastError(CRYPT_E_NOT_FOUND); - ret = NULL; - } - } - } - else - { - child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store, - NULL); - if (child) - { - ret = (PWINE_COLLECTION_CERT_CONTEXT)CRYPT_CollectionCreateCertRef( - child->context, store); - if (ret) - { - ret->entry = storeEntry; - ret->childContext = child; - } - else - CertFreeCertificateContext((PCCERT_CONTEXT)child); - } - else - { - struct list *storeNext = list_next(&store->stores, - &storeEntry->entry); - - if (storeNext) - { - storeEntry = LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY, - entry); - ret = CRYPT_CollectionAdvanceEnum(store, storeEntry, NULL); - } - else - { - SetLastError(CRYPT_E_NOT_FOUND); - ret = NULL; - } - } - } - TRACE("returning %p\n", ret); - return ret; -} - -static PWINE_CERT_CONTEXT_REF CRYPT_CollectionEnumCert( - PWINECRYPT_CERTSTORE store, PWINE_CERT_CONTEXT_REF pPrev) -{ - PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; - PWINE_COLLECTION_CERT_CONTEXT prevEntry = - (PWINE_COLLECTION_CERT_CONTEXT)pPrev, ret; - - TRACE("(%p, %p)\n", store, pPrev); - - if (prevEntry) - { - EnterCriticalSection(&cs->cs); - ret = CRYPT_CollectionAdvanceEnum(cs, prevEntry->entry, prevEntry); - LeaveCriticalSection(&cs->cs); - } - else - { - EnterCriticalSection(&cs->cs); - if (!list_empty(&cs->stores)) - { - PWINE_STORE_LIST_ENTRY storeEntry; - - storeEntry = LIST_ENTRY(cs->stores.next, WINE_STORE_LIST_ENTRY, - entry); - ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, prevEntry); - } - else - { - SetLastError(CRYPT_E_NOT_FOUND); - ret = NULL; - } - LeaveCriticalSection(&cs->cs); - } - TRACE("returning %p\n", ret); - return (PWINE_CERT_CONTEXT_REF)ret; -} - -static BOOL WINAPI CRYPT_CollectionDeleteCert(HCERTSTORE hCertStore, - PCCERT_CONTEXT pCertContext, DWORD dwFlags) -{ - PWINE_COLLECTION_CERT_CONTEXT context = - (PWINE_COLLECTION_CERT_CONTEXT)pCertContext; - BOOL ret; - - TRACE("(%p, %p, %08lx)\n", hCertStore, pCertContext, dwFlags); - - ret = CertDeleteCertificateFromStore((PCCERT_CONTEXT)context->childContext); - if (ret) - context->childContext = NULL; - return ret; -} - -static void CRYPT_CollectionFreeCert(PWINE_CERT_CONTEXT_REF ref) -{ - PWINE_COLLECTION_CERT_CONTEXT context = (PWINE_COLLECTION_CERT_CONTEXT)ref; - - TRACE("(%p)\n", ref); - - if (context->childContext) - CertFreeCertificateContext((PCCERT_CONTEXT)context->childContext); -} - -static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv, - DWORD dwFlags, const void *pvPara) -{ - PWINE_COLLECTIONSTORE store; - - if (dwFlags & CERT_STORE_DELETE_FLAG) - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - store = NULL; - } - else - { - store = CryptMemAlloc(sizeof(WINE_COLLECTIONSTORE)); - if (store) - { - memset(store, 0, sizeof(WINE_COLLECTIONSTORE)); - CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags, - StoreTypeCollection); - store->hdr.closeStore = CRYPT_CollectionCloseStore; - store->hdr.addCert = CRYPT_CollectionAddCert; - store->hdr.createCertRef = CRYPT_CollectionCreateCertRef; - store->hdr.enumCert = CRYPT_CollectionEnumCert; - store->hdr.deleteCert = CRYPT_CollectionDeleteCert; - store->hdr.freeCert = CRYPT_CollectionFreeCert; - InitializeCriticalSection(&store->cs); - list_init(&store->stores); - } - } - return (PWINECRYPT_CERTSTORE)store; -} - -static void CRYPT_HashToStr(LPBYTE hash, LPWSTR asciiHash) -{ - static const WCHAR fmt[] = { '%','0','2','X',0 }; - DWORD i; - - assert(hash); - assert(asciiHash); - - for (i = 0; i < 20; i++) - wsprintfW(asciiHash + i * 2, fmt, hash[i]); -} - -static const WCHAR CertsW[] = { 'C','e','r','t','i','f','i','c','a','t','e','s', - 0 }; -static const WCHAR CRLsW[] = { 'C','R','L','s',0 }; -static const WCHAR CTLsW[] = { 'C','T','L','s',0 }; -static const WCHAR BlobW[] = { 'B','l','o','b',0 }; - -static void CRYPT_RegReadSerializedFromReg(PWINE_REGSTORE store, HKEY key, - DWORD contextType) -{ - LONG rc; - DWORD index = 0; - WCHAR subKeyName[MAX_PATH]; - - do { - DWORD size = sizeof(subKeyName) / sizeof(WCHAR); - - rc = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL, NULL, - NULL); - if (!rc) - { - HKEY subKey; - - rc = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey); - if (!rc) - { - LPBYTE buf = NULL; - - size = 0; - rc = RegQueryValueExW(subKey, BlobW, NULL, NULL, NULL, &size); - if (!rc) - buf = CryptMemAlloc(size); - if (buf) - { - rc = RegQueryValueExW(subKey, BlobW, NULL, NULL, buf, - &size); - if (!rc) - { - const void *context; - DWORD addedType; - - TRACE("Adding cert with hash %s\n", - debugstr_w(subKeyName)); - context = CRYPT_ReadSerializedElement(buf, size, - contextType, &addedType); - if (context) - { - const WINE_CONTEXT_INTERFACE *contextInterface; - BYTE hash[20]; - - switch (addedType) - { - case CERT_STORE_CERTIFICATE_CONTEXT: - contextInterface = &gCertInterface; - break; - case CERT_STORE_CRL_CONTEXT: - contextInterface = &gCRLInterface; - break; - case CERT_STORE_CTL_CONTEXT: - contextInterface = &gCTLInterface; - break; - default: - contextInterface = NULL; - } - if (contextInterface) - { - size = sizeof(hash); - if (contextInterface->getProp(context, - CERT_HASH_PROP_ID, hash, &size)) - { - WCHAR asciiHash[20 * 2 + 1]; - - CRYPT_HashToStr(hash, asciiHash); - TRACE("comparing %s\n", - debugstr_w(asciiHash)); - TRACE("with %s\n", debugstr_w(subKeyName)); - if (!lstrcmpW(asciiHash, subKeyName)) - { - TRACE("hash matches, adding\n"); - contextInterface->addContextToStore( - store, context, - CERT_STORE_ADD_REPLACE_EXISTING, NULL); - } - else - { - TRACE("hash doesn't match, ignoring\n"); - contextInterface->free(context); - } - } - } - } - } - CryptMemFree(buf); - } - RegCloseKey(subKey); - } - /* Ignore intermediate errors, continue enumerating */ - rc = ERROR_SUCCESS; - } - } while (!rc); -} - -static void CRYPT_RegReadFromReg(PWINE_REGSTORE store) -{ - static const WCHAR *subKeys[] = { CertsW, CRLsW, CTLsW }; - static const DWORD contextFlags[] = { CERT_STORE_CERTIFICATE_CONTEXT_FLAG, - CERT_STORE_CRL_CONTEXT_FLAG, CERT_STORE_CTL_CONTEXT_FLAG }; - DWORD i; - - for (i = 0; i < sizeof(subKeys) / sizeof(subKeys[0]); i++) - { - HKEY key; - LONG rc; - - rc = RegCreateKeyExW(store->key, subKeys[i], 0, NULL, 0, KEY_READ, NULL, - &key, NULL); - if (!rc) - { - CRYPT_RegReadSerializedFromReg(store, key, contextFlags[i]); - RegCloseKey(key); - } - } -} - -/* Hash is assumed to be 20 bytes in length (a SHA-1 hash) */ -static BOOL CRYPT_WriteSerializedToReg(HKEY key, LPBYTE hash, LPBYTE buf, - DWORD len) -{ - WCHAR asciiHash[20 * 2 + 1]; - LONG rc; - HKEY subKey; - BOOL ret; - - CRYPT_HashToStr(hash, asciiHash); - rc = RegCreateKeyExW(key, asciiHash, 0, NULL, 0, KEY_ALL_ACCESS, NULL, - &subKey, NULL); - if (!rc) - { - rc = RegSetValueExW(subKey, BlobW, 0, REG_BINARY, buf, len); - RegCloseKey(subKey); - } - if (!rc) - ret = TRUE; - else - { - SetLastError(rc); - ret = FALSE; - } - return ret; -} - -static BOOL CRYPT_SerializeContextsToReg(HKEY key, - const WINE_CONTEXT_INTERFACE *contextInterface, HCERTSTORE memStore) -{ - const void *context = NULL; - BOOL ret; - - do { - context = contextInterface->enumContextsInStore(memStore, context); - if (context) - { - BYTE hash[20]; - DWORD hashSize = sizeof(hash); - - ret = contextInterface->getProp(context, CERT_HASH_PROP_ID, hash, - &hashSize); - if (ret) - { - DWORD size = 0; - LPBYTE buf = NULL; - - ret = contextInterface->serialize(context, 0, NULL, &size); - if (size) - buf = CryptMemAlloc(size); - if (buf) - { - ret = contextInterface->serialize(context, 0, buf, &size); - if (ret) - ret = CRYPT_WriteSerializedToReg(key, hash, buf, size); - } - CryptMemFree(buf); - } - } - else - ret = TRUE; - } while (ret && context != NULL); - if (context) - contextInterface->free(context); - return ret; -} - -static BOOL CRYPT_RegWriteToReg(PWINE_REGSTORE store) -{ - static const WCHAR *subKeys[] = { CertsW, CRLsW, CTLsW }; - static const WINE_CONTEXT_INTERFACE *interfaces[] = { &gCertInterface, - &gCRLInterface, &gCTLInterface }; - struct list *listToDelete[] = { &store->certsToDelete, NULL, NULL }; - BOOL ret = TRUE; - DWORD i; - - for (i = 0; ret && i < sizeof(subKeys) / sizeof(subKeys[0]); i++) - { - HKEY key; - LONG rc = RegCreateKeyExW(store->key, subKeys[i], 0, NULL, 0, - KEY_ALL_ACCESS, NULL, &key, NULL); - - if (!rc) - { - if (listToDelete[i]) - { - PWINE_HASH_TO_DELETE toDelete, next; - WCHAR asciiHash[20 * 2 + 1]; - - EnterCriticalSection(&store->cs); - LIST_FOR_EACH_ENTRY_SAFE(toDelete, next, listToDelete[i], - WINE_HASH_TO_DELETE, entry) - { - LONG rc; - - CRYPT_HashToStr(toDelete->hash, asciiHash); - TRACE("Removing %s\n", debugstr_w(asciiHash)); - rc = RegDeleteKeyW(key, asciiHash); - if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND) - { - SetLastError(rc); - ret = FALSE; - } - list_remove(&toDelete->entry); - CryptMemFree(toDelete); - } - LeaveCriticalSection(&store->cs); - } - ret = CRYPT_SerializeContextsToReg(key, interfaces[i], - store->memStore); - RegCloseKey(key); - } - else - { - SetLastError(rc); - ret = FALSE; - } - } - return ret; -} - -/* If force is true or the registry store is dirty, writes the contents of the - * store to the registry. - */ -static BOOL CRYPT_RegFlushStore(PWINE_REGSTORE store, BOOL force) -{ - BOOL ret; - - if (store->dirty || force) - ret = CRYPT_RegWriteToReg(store); - else - ret = TRUE; - return ret; -} - -static void WINAPI CRYPT_RegCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) -{ - PWINE_REGSTORE store = (PWINE_REGSTORE)hCertStore; - - TRACE("(%p, %08lx)\n", store, dwFlags); - if (dwFlags) - FIXME("Unimplemented flags: %08lx\n", dwFlags); - - CRYPT_RegFlushStore(store, FALSE); - /* certsToDelete should already be cleared by this point */ - store->memStore->closeStore(store->memStore, 0); - RegCloseKey(store->key); - DeleteCriticalSection(&store->cs); - CryptMemFree(store); -} - -static BOOL WINAPI CRYPT_RegAddCert(HCERTSTORE hCertStore, PCCERT_CONTEXT cert, - DWORD dwAddDisposition) -{ - PWINE_REGSTORE store = (PWINE_REGSTORE)hCertStore; - BOOL ret; - - TRACE("(%p, %p, %ld)\n", hCertStore, cert, dwAddDisposition); - - if (store->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG) - { - SetLastError(ERROR_ACCESS_DENIED); - ret = FALSE; - } - else - { - ret = store->memStore->addCert(store->memStore, cert, dwAddDisposition); - if (ret) - store->dirty = TRUE; - } - return ret; -} - -static PWINE_CERT_CONTEXT_REF CRYPT_RegCreateCertRef( - PWINE_CERT_CONTEXT context, HCERTSTORE store) -{ - PWINE_REG_CERT_CONTEXT ret = CryptMemAlloc( - sizeof(WINE_REG_CERT_CONTEXT)); - - if (ret) - { - CRYPT_InitCertRef((PWINE_CERT_CONTEXT_REF)ret, context, store); - ret->childContext = NULL; - } - return (PWINE_CERT_CONTEXT_REF)ret; -} - -static PWINE_CERT_CONTEXT_REF CRYPT_RegEnumCert(PWINECRYPT_CERTSTORE store, - PWINE_CERT_CONTEXT_REF pPrev) -{ - PWINE_REGSTORE rs = (PWINE_REGSTORE)store; - PWINE_CERT_CONTEXT_REF child; - PWINE_REG_CERT_CONTEXT prev = (PWINE_REG_CERT_CONTEXT)pPrev, ret = NULL; - - TRACE("(%p, %p)\n", store, pPrev); - - if (pPrev) - { - child = rs->memStore->enumCert(rs->memStore, prev->childContext); - if (child) - { - ret = (PWINE_REG_CERT_CONTEXT)pPrev; - memcpy(&ret->cert, child, sizeof(WINE_CERT_CONTEXT_REF)); - ret->cert.cert.hCertStore = (HCERTSTORE)store; - ret->childContext = child; - } - } - else - { - child = rs->memStore->enumCert(rs->memStore, NULL); - if (child) - { - ret = CryptMemAlloc(sizeof(WINE_REG_CERT_CONTEXT)); - - if (ret) - { - memcpy(&ret->cert, child, sizeof(WINE_CERT_CONTEXT_REF)); - ret->cert.cert.hCertStore = (HCERTSTORE)store; - ret->childContext = child; - } - else - CertFreeCertificateContext((PCCERT_CONTEXT)child); - } - } - return (PWINE_CERT_CONTEXT_REF)ret; -} - -static BOOL WINAPI CRYPT_RegDeleteCert(HCERTSTORE hCertStore, - PCCERT_CONTEXT pCertContext, DWORD dwFlags) -{ - PWINE_REGSTORE store = (PWINE_REGSTORE)hCertStore; - BOOL ret; - - TRACE("(%p, %p, %08lx)\n", store, pCertContext, dwFlags); - - if (store->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG) - { - SetLastError(ERROR_ACCESS_DENIED); - ret = FALSE; - } - else - { - PWINE_HASH_TO_DELETE toDelete = - CryptMemAlloc(sizeof(WINE_HASH_TO_DELETE)); - - if (toDelete) - { - DWORD size = sizeof(toDelete->hash); - - ret = CertGetCertificateContextProperty(pCertContext, - CERT_HASH_PROP_ID, toDelete->hash, &size); - if (ret) - { - list_init(&toDelete->entry); - EnterCriticalSection(&store->cs); - list_add_tail(&store->certsToDelete, &toDelete->entry); - LeaveCriticalSection(&store->cs); - ret = store->memStore->deleteCert(store->memStore, pCertContext, - dwFlags); - } - else - CryptMemFree(toDelete); - } - else - ret = FALSE; - if (ret) - store->dirty = TRUE; - } - return ret; -} - -static void CRYPT_RegFreeCert(PWINE_CERT_CONTEXT_REF ref) -{ - PWINE_REG_CERT_CONTEXT context = (PWINE_REG_CERT_CONTEXT)ref; - - TRACE("(%p)\n", ref); - - if (context->childContext) - CertFreeCertificateContext((PCCERT_CONTEXT)context->childContext); -} - -static BOOL WINAPI CRYPT_RegControl(HCERTSTORE hCertStore, DWORD dwFlags, - DWORD dwCtrlType, void const *pvCtrlPara) -{ - PWINE_REGSTORE store = (PWINE_REGSTORE)hCertStore; - BOOL ret; - - switch (dwCtrlType) - { - case CERT_STORE_CTRL_RESYNC: - CRYPT_RegFlushStore(store, FALSE); - store->memStore->closeStore(store->memStore, 0); - store->memStore = CRYPT_MemOpenStore(store->hdr.cryptProv, - store->hdr.dwOpenFlags, NULL); - if (store->memStore) - { - CRYPT_RegReadFromReg(store); - ret = TRUE; - } - else - ret = FALSE; - break; - case CERT_STORE_CTRL_COMMIT: - ret = CRYPT_RegFlushStore(store, - dwFlags & CERT_STORE_CTRL_COMMIT_FORCE_FLAG); - break; - default: - FIXME("%ld: stub\n", dwCtrlType); - ret = FALSE; - } - return ret; -} - -/* Copied from shlwapi's SHDeleteKeyW, and reformatted to match this file. */ -static DWORD CRYPT_RecurseDeleteKey(HKEY hKey, LPCWSTR lpszSubKey) -{ - DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i; - WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf; - HKEY hSubKey = 0; - - TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey)); - - dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey); - if (!dwRet) - { - /* Find how many subkeys there are */ - dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount, - &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL); - if (!dwRet) - { - dwMaxSubkeyLen++; - if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR)) - { - /* Name too big: alloc a buffer for it */ - lpszName = CryptMemAlloc(dwMaxSubkeyLen*sizeof(WCHAR)); - } - - if (!lpszName) - dwRet = ERROR_NOT_ENOUGH_MEMORY; - else - { - /* Recursively delete all the subkeys */ - for (i = 0; i < dwKeyCount && !dwRet; i++) - { - dwSize = dwMaxSubkeyLen; - dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, - NULL, NULL, NULL); - if (!dwRet) - dwRet = CRYPT_RecurseDeleteKey(hSubKey, lpszName); - } - - if (lpszName != szNameBuf) - { - /* Free buffer if allocated */ - CryptMemFree(lpszName); - } - } - } - - RegCloseKey(hSubKey); - if (!dwRet) - dwRet = RegDeleteKeyW(hKey, lpszSubKey); - } - return dwRet; -} - -static WINECRYPT_CERTSTORE *CRYPT_RegOpenStore(HCRYPTPROV hCryptProv, - DWORD dwFlags, const void *pvPara) -{ - PWINE_REGSTORE store = NULL; - - TRACE("(%ld, %08lx, %p)\n", hCryptProv, dwFlags, pvPara); - - if (dwFlags & CERT_STORE_DELETE_FLAG) - { - DWORD rc = CRYPT_RecurseDeleteKey((HKEY)pvPara, CertsW); - - if (rc == ERROR_SUCCESS || rc == ERROR_NO_MORE_ITEMS) - rc = CRYPT_RecurseDeleteKey((HKEY)pvPara, CRLsW); - if (rc == ERROR_SUCCESS || rc == ERROR_NO_MORE_ITEMS) - rc = CRYPT_RecurseDeleteKey((HKEY)pvPara, CTLsW); - if (rc == ERROR_NO_MORE_ITEMS) - rc = ERROR_SUCCESS; - SetLastError(rc); - } - else - { - HKEY key; - - if (DuplicateHandle(GetCurrentProcess(), (HANDLE)pvPara, - GetCurrentProcess(), (LPHANDLE)&key, - dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ : KEY_ALL_ACCESS, - TRUE, 0)) - { - PWINECRYPT_CERTSTORE memStore; - - memStore = CRYPT_MemOpenStore(hCryptProv, dwFlags, NULL); - if (memStore) - { - store = CryptMemAlloc(sizeof(WINE_REGSTORE)); - if (store) - { - memset(store, 0, sizeof(WINE_REGSTORE)); - CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags, - StoreTypeReg); - store->hdr.closeStore = CRYPT_RegCloseStore; - store->hdr.addCert = CRYPT_RegAddCert; - store->hdr.createCertRef = CRYPT_RegCreateCertRef; - store->hdr.enumCert = CRYPT_RegEnumCert; - store->hdr.deleteCert = CRYPT_RegDeleteCert; - store->hdr.freeCert = CRYPT_RegFreeCert; - store->hdr.control = CRYPT_RegControl; - store->memStore = memStore; - store->key = key; - InitializeCriticalSection(&store->cs); - list_init(&store->certsToDelete); - CRYPT_RegReadFromReg(store); - store->dirty = FALSE; - } - } - } - } - TRACE("returning %p\n", store); - return (WINECRYPT_CERTSTORE *)store; -} - -/* FIXME: this isn't complete for the Root store, in which the top-level - * self-signed CA certs reside. Adding a cert to the Root store should present - * the user with a dialog indicating the consequences of doing so, and asking - * the user to confirm whether the cert should be added. - */ -static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv, - DWORD dwFlags, const void *pvPara) -{ - static const WCHAR fmt[] = { '%','s','\\','%','s',0 }; - LPCWSTR storeName = (LPCWSTR)pvPara; - LPWSTR storePath; - PWINECRYPT_CERTSTORE store = NULL; - HKEY root; - LPCWSTR base; - BOOL ret; - - TRACE("(%ld, %08lx, %s)\n", hCryptProv, dwFlags, - debugstr_w((LPCWSTR)pvPara)); - - if (!pvPara) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return NULL; - } - - ret = TRUE; - switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) - { - case CERT_SYSTEM_STORE_LOCAL_MACHINE: - root = HKEY_LOCAL_MACHINE; - base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH; - break; - case CERT_SYSTEM_STORE_CURRENT_USER: - root = HKEY_CURRENT_USER; - base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH; - break; - case CERT_SYSTEM_STORE_CURRENT_SERVICE: - /* hklm\Software\Microsoft\Cryptography\Services\servicename\ - * SystemCertificates - */ - FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n", - debugstr_w(storeName)); - return NULL; - case CERT_SYSTEM_STORE_SERVICES: - /* hklm\Software\Microsoft\Cryptography\Services\servicename\ - * SystemCertificates - */ - FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n", - debugstr_w(storeName)); - return NULL; - case CERT_SYSTEM_STORE_USERS: - /* hku\user sid\Software\Microsoft\SystemCertificates */ - FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n", - debugstr_w(storeName)); - return NULL; - case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY: - root = HKEY_CURRENT_USER; - base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH; - break; - case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY: - root = HKEY_LOCAL_MACHINE; - base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH; - break; - case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE: - /* hklm\Software\Microsoft\EnterpriseCertificates */ - FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n", - debugstr_w(storeName)); - return NULL; - default: - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return NULL; - } - - storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) * - sizeof(WCHAR)); - if (storePath) - { - LONG rc; - HKEY key; - REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ : - KEY_ALL_ACCESS; - - wsprintfW(storePath, fmt, base, storeName); - if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG) - rc = RegOpenKeyExW(root, storePath, 0, sam, &key); - else - { - DWORD disp; - - rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL, - &key, &disp); - if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG && - disp == REG_OPENED_EXISTING_KEY) - { - RegCloseKey(key); - rc = ERROR_FILE_EXISTS; - } - } - if (!rc) - { - store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key); - RegCloseKey(key); - } - else - SetLastError(rc); - CryptMemFree(storePath); - } - return store; -} - -static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv, - DWORD dwFlags, const void *pvPara) -{ - int len; - PWINECRYPT_CERTSTORE ret = NULL; - - TRACE("(%ld, %08lx, %s)\n", hCryptProv, dwFlags, - debugstr_a((LPCSTR)pvPara)); - - if (!pvPara) - { - SetLastError(ERROR_FILE_NOT_FOUND); - return NULL; - } - len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0); - if (len) - { - LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR)); - - if (storeName) - { - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len); - ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName); - CryptMemFree(storeName); - } - } - return ret; -} - -static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv, - DWORD dwFlags, const void *pvPara) -{ - HCERTSTORE store = 0; - BOOL ret; - - TRACE("(%ld, %08lx, %s)\n", hCryptProv, dwFlags, - debugstr_w((LPCWSTR)pvPara)); - - if (!pvPara) - { - SetLastError(ERROR_FILE_NOT_FOUND); - return NULL; - } - /* This returns a different error than system registry stores if the - * location is invalid. - */ - switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) - { - case CERT_SYSTEM_STORE_LOCAL_MACHINE: - case CERT_SYSTEM_STORE_CURRENT_USER: - case CERT_SYSTEM_STORE_CURRENT_SERVICE: - case CERT_SYSTEM_STORE_SERVICES: - case CERT_SYSTEM_STORE_USERS: - case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY: - case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY: - case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE: - ret = TRUE; - break; - default: - SetLastError(ERROR_FILE_NOT_FOUND); - ret = FALSE; - } - if (ret) - { - HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, - 0, hCryptProv, dwFlags, pvPara); - - if (regStore) - { - store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, - CERT_STORE_CREATE_NEW_FLAG, NULL); - if (store) - { - CertAddStoreToCollection(store, regStore, - dwFlags & CERT_STORE_READONLY_FLAG ? 0 : - CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); - CertCloseStore(regStore, 0); - } - } - } - return (PWINECRYPT_CERTSTORE)store; -} - -static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv, - DWORD dwFlags, const void *pvPara) -{ - int len; - PWINECRYPT_CERTSTORE ret = NULL; - - TRACE("(%ld, %08lx, %s)\n", hCryptProv, dwFlags, - debugstr_a((LPCSTR)pvPara)); - - if (!pvPara) - { - SetLastError(ERROR_FILE_NOT_FOUND); - return NULL; - } - len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0); - if (len) - { - LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR)); - - if (storeName) - { - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len); - ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName); - CryptMemFree(storeName); - } - } - return ret; -} - -HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider, - DWORD dwMsgAndCertEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, - const void* pvPara) -{ - WINECRYPT_CERTSTORE *hcs; - StoreOpenFunc openFunc = NULL; - - TRACE("(%s, %08lx, %08lx, %08lx, %p)\n", debugstr_a(lpszStoreProvider), - dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara); - - if (!HIWORD(lpszStoreProvider)) - { - switch (LOWORD(lpszStoreProvider)) - { - case (int)CERT_STORE_PROV_MEMORY: - openFunc = CRYPT_MemOpenStore; - break; - case (int)CERT_STORE_PROV_REG: - openFunc = CRYPT_RegOpenStore; - break; - case (int)CERT_STORE_PROV_COLLECTION: - openFunc = CRYPT_CollectionOpenStore; - break; - case (int)CERT_STORE_PROV_SYSTEM_A: - openFunc = CRYPT_SysOpenStoreA; - break; - case (int)CERT_STORE_PROV_SYSTEM_W: - openFunc = CRYPT_SysOpenStoreW; - break; - case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_A: - openFunc = CRYPT_SysRegOpenStoreA; - break; - case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W: - openFunc = CRYPT_SysRegOpenStoreW; - break; - default: - if (LOWORD(lpszStoreProvider)) - FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider)); - } - } - else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY)) - openFunc = CRYPT_MemOpenStore; - else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM)) - openFunc = CRYPT_SysOpenStoreW; - else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION)) - openFunc = CRYPT_CollectionOpenStore; - else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY)) - openFunc = CRYPT_SysRegOpenStoreW; - else - { - FIXME("unimplemented type %s\n", lpszStoreProvider); - openFunc = NULL; - } - - if (!openFunc) - { - /* FIXME: need to look for an installed provider for this type */ - SetLastError(ERROR_FILE_NOT_FOUND); - hcs = NULL; - } - else - hcs = openFunc(hCryptProv, dwFlags, pvPara); - return (HCERTSTORE)hcs; -} - -HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV hProv, - LPCSTR szSubSystemProtocol) -{ - HCERTSTORE ret = 0; - - if (szSubSystemProtocol) - { - int len = MultiByteToWideChar(CP_ACP, 0, szSubSystemProtocol, -1, NULL, - 0); - LPWSTR param = CryptMemAlloc(len * sizeof(WCHAR)); - - if (param) - { - MultiByteToWideChar(CP_ACP, 0, szSubSystemProtocol, -1, param, len); - ret = CertOpenSystemStoreW(hProv, param); - CryptMemFree(param); - } - } - else - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return ret; -} - -HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV hProv, - LPCWSTR szSubSystemProtocol) -{ - HCERTSTORE ret; - - if (!szSubSystemProtocol) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return 0; - } - - /* FIXME: needs some tests. It seems to open both HKEY_LOCAL_MACHINE and - * HKEY_CURRENT_USER stores, but I'm not sure under what conditions, if any, - * it fails. - */ - ret = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, hProv, - CERT_STORE_CREATE_NEW_FLAG, NULL); - if (ret) - { - HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, - 0, hProv, CERT_SYSTEM_STORE_LOCAL_MACHINE, szSubSystemProtocol); - - if (store) - { - CertAddStoreToCollection(ret, store, - CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); - CertCloseStore(store, 0); - } - store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, - 0, hProv, CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol); - if (store) - { - CertAddStoreToCollection(ret, store, - CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); - CertCloseStore(store, 0); - } - } - return ret; -} - -BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType, - DWORD dwSaveAs, DWORD dwSaveTo, void* pvSaveToPara, DWORD dwFlags) -{ - FIXME("(%p,%ld,%ld,%ld,%p,%08lx) stub!\n", hCertStore, - dwMsgAndCertEncodingType, dwSaveAs, dwSaveTo, pvSaveToPara, dwFlags); - return TRUE; -} - -PCCRL_CONTEXT WINAPI CertCreateCRLContext( DWORD dwCertEncodingType, - const BYTE* pbCrlEncoded, DWORD cbCrlEncoded) -{ - PCRL_CONTEXT pcrl; - BYTE* data; - - TRACE("%08lx %p %08lx\n", dwCertEncodingType, pbCrlEncoded, cbCrlEncoded); - - /* FIXME: semi-stub, need to use CryptDecodeObjectEx to decode the CRL. */ - pcrl = CryptMemAlloc( sizeof (CRL_CONTEXT) ); - if( !pcrl ) - return NULL; - - data = CryptMemAlloc( cbCrlEncoded ); - if( !data ) - { - CryptMemFree( pcrl ); - return NULL; - } - - pcrl->dwCertEncodingType = dwCertEncodingType; - pcrl->pbCrlEncoded = data; - pcrl->cbCrlEncoded = cbCrlEncoded; - pcrl->pCrlInfo = NULL; - pcrl->hCertStore = 0; - - return pcrl; -} - -/* Decodes the encoded certificate and creates the certificate context for it. - * The reference count is initially zero, so you must create a reference to it - * to avoid leaking memory. - */ -static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext( - DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded) -{ - PWINE_CERT_CONTEXT cert = NULL; - BOOL ret; - PCERT_SIGNED_CONTENT_INFO signedCert = NULL; - PCERT_INFO certInfo = NULL; - DWORD size = 0; - - TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCertEncoded, - cbCertEncoded); - - /* First try to decode it as a signed cert. */ - ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT, pbCertEncoded, - cbCertEncoded, CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, - (BYTE *)&signedCert, &size); - if (ret) - { - size = 0; - ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, - signedCert->ToBeSigned.pbData, signedCert->ToBeSigned.cbData, - CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, - (BYTE *)&certInfo, &size); - LocalFree(signedCert); - } - /* Failing that, try it as an unsigned cert */ - if (!ret) - { - size = 0; - ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, - pbCertEncoded, cbCertEncoded, - CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, - (BYTE *)&certInfo, &size); - } - if (ret) - { - BYTE *data = NULL; - - cert = CryptMemAlloc(sizeof(WINE_CERT_CONTEXT)); - if (!cert) - goto end; - data = CryptMemAlloc(cbCertEncoded); - if (!data) - { - CryptMemFree(cert); - cert = NULL; - goto end; - } - memcpy(data, pbCertEncoded, cbCertEncoded); - cert->cert.dwCertEncodingType = dwCertEncodingType; - cert->cert.pbCertEncoded = data; - cert->cert.cbCertEncoded = cbCertEncoded; - cert->cert.pCertInfo = certInfo; - cert->cert.hCertStore = 0; - cert->ref = 0; - InitializeCriticalSection(&cert->cs); - list_init(&cert->extendedProperties); - } - -end: - return cert; -} - -static void CRYPT_FreeCert(PWINE_CERT_CONTEXT context) -{ - PWINE_CERT_PROPERTY prop, next; - - CryptMemFree(context->cert.pbCertEncoded); - LocalFree(context->cert.pCertInfo); - DeleteCriticalSection(&context->cs); - LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties, - WINE_CERT_PROPERTY, entry) - { - list_remove(&prop->entry); - CryptMemFree(prop->pbData); - CryptMemFree(prop); - } - CryptMemFree(context); -} - -PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType, - const BYTE *pbCertEncoded, DWORD cbCertEncoded) -{ - PWINE_CERT_CONTEXT cert; - PWINE_CERT_CONTEXT_REF ret = NULL; - - TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCertEncoded, - cbCertEncoded); - - cert = CRYPT_CreateCertificateContext(dwCertEncodingType, pbCertEncoded, - cbCertEncoded); - if (cert) - ret = CRYPT_CreateCertRef(cert, 0); - return (PCCERT_CONTEXT)ret; -} - -/* Since the properties are stored in a list, this is a tad inefficient - * (O(n^2)) since I have to find the previous position every time. - */ -DWORD WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext, - DWORD dwPropId) -{ - PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext; - DWORD ret; - - TRACE("(%p, %ld)\n", pCertContext, dwPropId); - - EnterCriticalSection(&ref->context->cs); - if (dwPropId) - { - PWINE_CERT_PROPERTY cursor = NULL; - - LIST_FOR_EACH_ENTRY(cursor, &ref->context->extendedProperties, - WINE_CERT_PROPERTY, entry) - { - if (cursor->hdr.propID == dwPropId) - break; - } - if (cursor) - { - if (cursor->entry.next != &ref->context->extendedProperties) - ret = LIST_ENTRY(cursor->entry.next, WINE_CERT_PROPERTY, - entry)->hdr.propID; - else - ret = 0; - } - else - ret = 0; - } - else if (!list_empty(&ref->context->extendedProperties)) - ret = LIST_ENTRY(ref->context->extendedProperties.next, - WINE_CERT_PROPERTY, entry)->hdr.propID; - else - ret = 0; - LeaveCriticalSection(&ref->context->cs); - return ret; -} - -static BOOL WINAPI CRYPT_GetCertificateContextProperty( - PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData) -{ - PWINE_CERT_PROPERTY prop; - BOOL ret, found; - - TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData); - - EnterCriticalSection(&context->cs); - ret = FALSE; - found = FALSE; - LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties, - WINE_CERT_PROPERTY, entry) - { - if (prop->hdr.propID == dwPropId) - { - if (!pvData) - { - *pcbData = prop->hdr.cb; - ret = TRUE; - } - else if (*pcbData < prop->hdr.cb) - { - SetLastError(ERROR_MORE_DATA); - *pcbData = prop->hdr.cb; - } - else - { - memcpy(pvData, prop->pbData, prop->hdr.cb); - *pcbData = prop->hdr.cb; - ret = TRUE; - } - found = TRUE; - } - break; - } - if (!found) - { - /* Implicit properties */ - switch (dwPropId) - { - case CERT_SHA1_HASH_PROP_ID: - ret = CryptHashCertificate(0, CALG_SHA1, 0, - context->cert.pbCertEncoded, context->cert.cbCertEncoded, pvData, - pcbData); - if (ret) - { - CRYPT_DATA_BLOB blob = { *pcbData, pvData }; - - ret = CRYPT_SetCertificateContextProperty(context, dwPropId, - 0, &blob); - } - break; - case CERT_KEY_PROV_INFO_PROP_ID: - case CERT_MD5_HASH_PROP_ID: - case CERT_SIGNATURE_HASH_PROP_ID: - case CERT_KEY_IDENTIFIER_PROP_ID: - case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID: - case CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID: - case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID: - FIXME("implicit property %ld\n", dwPropId); - break; - } - } - LeaveCriticalSection(&context->cs); - TRACE("returning %d\n", ret); - return ret; -} - -BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, - DWORD dwPropId, void *pvData, DWORD *pcbData) -{ - PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext; - BOOL ret; - - TRACE("(%p, %ld, %p, %p)\n", pCertContext, dwPropId, pvData, pcbData); - - /* Special cases for invalid/special prop IDs. - */ - switch (dwPropId) - { - case 0: - case CERT_CERT_PROP_ID: - case CERT_CRL_PROP_ID: - case CERT_CTL_PROP_ID: - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return FALSE; - case CERT_ACCESS_STATE_PROP_ID: - if (!pvData) - { - *pcbData = sizeof(DWORD); - return TRUE; - } - else if (*pcbData < sizeof(DWORD)) - { - SetLastError(ERROR_MORE_DATA); - *pcbData = sizeof(DWORD); - return FALSE; - } - else - { - DWORD state = 0; - - if (pCertContext->hCertStore) - { - PWINECRYPT_CERTSTORE store = - (PWINECRYPT_CERTSTORE)pCertContext->hCertStore; - - /* Take advantage of knowledge of the stores to answer the - * access state question - */ - if (store->type != StoreTypeReg || - !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG)) - state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG; - } - *(DWORD *)pvData = state; - return TRUE; - } - } - - ret = CRYPT_GetCertificateContextProperty(ref->context, dwPropId, - pvData, pcbData); - TRACE("returning %d\n", ret); - return ret; -} - -/* Copies cbData bytes from pbData to the context's property with ID - * dwPropId. - */ -static BOOL CRYPT_SaveCertificateContextProperty(PWINE_CERT_CONTEXT context, - DWORD dwPropId, const BYTE *pbData, size_t cbData) -{ - BOOL ret = FALSE; - LPBYTE data; - - if (cbData) - { - data = CryptMemAlloc(cbData); - if (data) - memcpy(data, pbData, cbData); - } - else - data = NULL; - if (!cbData || data) - { - PWINE_CERT_PROPERTY prop; - - EnterCriticalSection(&context->cs); - LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties, - WINE_CERT_PROPERTY, entry) - { - if (prop->hdr.propID == dwPropId) - break; - } - if (prop && prop->entry.next != &context->extendedProperties) - { - CryptMemFree(prop->pbData); - prop->hdr.cb = cbData; - prop->pbData = cbData ? data : NULL; - ret = TRUE; - } - else - { - prop = CryptMemAlloc(sizeof(WINE_CERT_PROPERTY)); - if (prop) - { - prop->hdr.propID = dwPropId; - prop->hdr.unknown = 1; - prop->hdr.cb = cbData; - list_init(&prop->entry); - prop->pbData = cbData ? data : NULL; - list_add_tail(&context->extendedProperties, &prop->entry); - ret = TRUE; - } - else - CryptMemFree(data); - } - LeaveCriticalSection(&context->cs); - } - return ret; -} - -static BOOL WINAPI CRYPT_SetCertificateContextProperty( - PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData) -{ - BOOL ret = FALSE; - - TRACE("(%p, %ld, %08lx, %p)\n", context, dwPropId, dwFlags, pvData); - - if (!pvData) - { - PWINE_CERT_PROPERTY prop, next; - - EnterCriticalSection(&context->cs); - LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties, - WINE_CERT_PROPERTY, entry) - { - if (prop->hdr.propID == dwPropId) - { - list_remove(&prop->entry); - CryptMemFree(prop->pbData); - CryptMemFree(prop); - } - } - LeaveCriticalSection(&context->cs); - ret = TRUE; - } - else - { - switch (dwPropId) - { - case CERT_AUTO_ENROLL_PROP_ID: - case CERT_CTL_USAGE_PROP_ID: - case CERT_DESCRIPTION_PROP_ID: - case CERT_FRIENDLY_NAME_PROP_ID: - case CERT_HASH_PROP_ID: - case CERT_KEY_IDENTIFIER_PROP_ID: - case CERT_MD5_HASH_PROP_ID: - case CERT_NEXT_UPDATE_LOCATION_PROP_ID: - case CERT_PUBKEY_ALG_PARA_PROP_ID: - case CERT_PVK_FILE_PROP_ID: - case CERT_SIGNATURE_HASH_PROP_ID: - case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID: - case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID: - case CERT_ENROLLMENT_PROP_ID: - case CERT_CROSS_CERT_DIST_POINTS_PROP_ID: - case CERT_RENEWAL_PROP_ID: - { - PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData; - - ret = CRYPT_SaveCertificateContextProperty(context, dwPropId, - blob->pbData, blob->cbData); - break; - } - case CERT_DATE_STAMP_PROP_ID: - ret = CRYPT_SaveCertificateContextProperty(context, dwPropId, - pvData, sizeof(FILETIME)); - break; - default: - FIXME("%ld: stub\n", dwPropId); - } - } - TRACE("returning %d\n", ret); - return ret; -} - -BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext, - DWORD dwPropId, DWORD dwFlags, const void *pvData) -{ - PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext; - BOOL ret; - - TRACE("(%p, %ld, %08lx, %p)\n", pCertContext, dwPropId, dwFlags, pvData); - - /* Handle special cases for "read-only"/invalid prop IDs. Windows just - * crashes on most of these, I'll be safer. - */ - switch (dwPropId) - { - case 0: - case CERT_ACCESS_STATE_PROP_ID: - case CERT_CERT_PROP_ID: - case CERT_CRL_PROP_ID: - case CERT_CTL_PROP_ID: - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return FALSE; - } - ret = CRYPT_SetCertificateContextProperty(ref->context, dwPropId, - dwFlags, pvData); - TRACE("returning %d\n", ret); - return ret; -} - -/* Only the reference portion of the context is duplicated. The returned - * context has the cert store set to 0, to prevent the store's certificate free - * function from getting called on partial data. - * FIXME: is this okay? Needs a test. - */ -PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext( - PCCERT_CONTEXT pCertContext) -{ - PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext, ret; - - TRACE("(%p)\n", pCertContext); - if (ref) - { - ret = CryptMemAlloc(sizeof(WINE_CERT_CONTEXT_REF)); - if (ret) - { - memcpy(ret, ref, sizeof(*ret)); - ret->cert.hCertStore = 0; - InterlockedIncrement(&ret->context->ref); - } - } - else - ret = NULL; - return (PCCERT_CONTEXT)ret; -} - -BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore, - PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition, - PCCERT_CONTEXT *ppStoreContext) -{ - PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore; - PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext; - PWINE_CERT_CONTEXT cert; - BOOL ret; - - TRACE("(%p, %p, %08lx, %p)\n", hCertStore, pCertContext, - dwAddDisposition, ppStoreContext); - - /* FIXME: some tests needed to verify return codes */ - if (!store) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if (store->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - cert = CRYPT_CreateCertificateContext(ref->context->cert.dwCertEncodingType, - ref->context->cert.pbCertEncoded, ref->context->cert.cbCertEncoded); - if (cert) - { - PWINE_CERT_PROPERTY prop; - - ret = TRUE; - EnterCriticalSection(&ref->context->cs); - LIST_FOR_EACH_ENTRY(prop, &ref->context->extendedProperties, - WINE_CERT_PROPERTY, entry) - { - ret = CRYPT_SaveCertificateContextProperty(cert, prop->hdr.propID, - prop->pbData, prop->hdr.cb); - if (!ret) - break; - } - LeaveCriticalSection(&ref->context->cs); - if (ret) - { - ret = store->addCert(store, (PCCERT_CONTEXT)cert, dwAddDisposition); - if (ret && ppStoreContext) - *ppStoreContext = (PCCERT_CONTEXT)store->createCertRef(cert, - hCertStore); - } - if (!ret) - CRYPT_FreeCert(cert); - } - else - ret = FALSE; - return ret; -} - -BOOL WINAPI CertAddEncodedCertificateToStore(HCERTSTORE hCertStore, - DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded, - DWORD dwAddDisposition, PCCERT_CONTEXT *ppCertContext) -{ - WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore; - BOOL ret; - - TRACE("(%p, %08lx, %p, %ld, %08lx, %p)\n", hCertStore, dwCertEncodingType, - pbCertEncoded, cbCertEncoded, dwAddDisposition, ppCertContext); - - if (!hcs) - ret = FALSE; - else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - ret = FALSE; - else - { - PWINE_CERT_CONTEXT cert = CRYPT_CreateCertificateContext( - dwCertEncodingType, pbCertEncoded, cbCertEncoded); - - if (cert) - { - ret = hcs->addCert(hcs, (PCCERT_CONTEXT)cert, dwAddDisposition); - if (ret && ppCertContext) - *ppCertContext = (PCCERT_CONTEXT)hcs->createCertRef(cert, - hCertStore); - if (!ret) - CRYPT_FreeCert(cert); - } - else - ret = FALSE; - } - return ret; -} - -PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, - PCCERT_CONTEXT pPrev) -{ - WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore; - PWINE_CERT_CONTEXT_REF prev = (PWINE_CERT_CONTEXT_REF)pPrev; - PCCERT_CONTEXT ret; - - TRACE("(%p, %p)\n", hCertStore, pPrev); - if (!hCertStore) - ret = NULL; - else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - ret = NULL; - else - ret = (PCCERT_CONTEXT)hcs->enumCert(hcs, prev); - return ret; -} - -BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext) -{ - BOOL ret; - - TRACE("(%p)\n", pCertContext); - - if (!pCertContext) - ret = TRUE; - else if (!pCertContext->hCertStore) - { - ret = TRUE; - CertFreeCertificateContext(pCertContext); - } - else - { - PWINECRYPT_CERTSTORE hcs = - (PWINECRYPT_CERTSTORE)pCertContext->hCertStore; - - if (!hcs) - ret = TRUE; - else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - ret = FALSE; - else - { - ret = hcs->deleteCert(hcs, pCertContext, 0); - CertFreeCertificateContext(pCertContext); - } - } - return ret; -} - -BOOL WINAPI CertAddEncodedCRLToStore(HCERTSTORE hCertStore, - DWORD dwCertEncodingType, const BYTE *pbCrlEncoded, DWORD cbCrlEncoded, - DWORD dwAddDisposition, PCCRL_CONTEXT *ppCrlContext) -{ - FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore, - dwCertEncodingType, pbCrlEncoded, cbCrlEncoded, dwAddDisposition, - ppCrlContext); - return FALSE; -} - -BOOL WINAPI CertAddCRLContextToStore( HCERTSTORE hCertStore, - PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition, - PCCRL_CONTEXT* ppStoreContext ) -{ - FIXME("%p %p %08lx %p\n", hCertStore, pCrlContext, - dwAddDisposition, ppStoreContext); - return TRUE; -} - -BOOL WINAPI CertFreeCRLContext( PCCRL_CONTEXT pCrlContext) -{ - FIXME("%p\n", pCrlContext ); - - return TRUE; -} - -BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext) -{ - FIXME("(%p): stub\n", pCrlContext); - return TRUE; -} - -PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore, - PCCRL_CONTEXT pPrev) -{ - FIXME("(%p, %p): stub\n", hCertStore, pPrev); - return NULL; -} - -PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwCertEncodingType, - const BYTE* pbCtlEncoded, DWORD cbCtlEncoded) -{ - FIXME("(%08lx, %p, %08lx): stub\n", dwCertEncodingType, pbCtlEncoded, - cbCtlEncoded); - return NULL; -} - -BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore, - DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded, - DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext) -{ - FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore, - dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition, - ppCtlContext); - return FALSE; -} - -BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore, - PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition, - PCCTL_CONTEXT* ppStoreContext) -{ - FIXME("(%p, %p, %08lx, %p): stub\n", hCertStore, pCtlContext, - dwAddDisposition, ppStoreContext); - return TRUE; -} - -BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCtlContext) -{ - FIXME("(%p): stub\n", pCtlContext ); - return TRUE; -} - -BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext) -{ - FIXME("(%p): stub\n", pCtlContext); - return TRUE; -} - -PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore, - PCCTL_CONTEXT pPrev) -{ - FIXME("(%p, %p): stub\n", hCertStore, pPrev); - return NULL; -} - - -BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) -{ - WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *) hCertStore; - - TRACE("(%p, %08lx)\n", hCertStore, dwFlags); - - if( ! hCertStore ) - return TRUE; - - if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC ) - return FALSE; - - if (InterlockedDecrement(&hcs->ref) == 0) - { - TRACE("%p's ref count is 0, freeing\n", hcs); - hcs->dwMagic = 0; - if (!(hcs->dwOpenFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) - CryptReleaseContext(hcs->cryptProv, 0); - hcs->closeStore(hcs, dwFlags); - } - else - TRACE("%p's ref count is %ld\n", hcs, hcs->ref); - return TRUE; -} - -BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags, - DWORD dwCtrlType, void const *pvCtrlPara) -{ - WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore; - BOOL ret; - - TRACE("(%p, %08lx, %ld, %p)\n", hCertStore, dwFlags, dwCtrlType, - pvCtrlPara); - - if (!hcs) - ret = FALSE; - else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - ret = FALSE; - else - { - if (hcs->control) - ret = hcs->control(hCertStore, dwFlags, dwCtrlType, pvCtrlPara); - else - ret = TRUE; - } - return ret; -} - -BOOL WINAPI CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext, - DWORD dwPropId, void *pvData, DWORD *pcbData) -{ - FIXME("(%p, %ld, %p, %p): stub\n", pCRLContext, dwPropId, pvData, pcbData); - return FALSE; -} - -BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext, - DWORD dwPropId, DWORD dwFlags, const void *pvData) -{ - FIXME("(%p, %ld, %08lx, %p): stub\n", pCRLContext, dwPropId, dwFlags, - pvData); - return FALSE; -} - -BOOL WINAPI CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext, - DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement) -{ - FIXME("(%p, %08lx, %p, %p): stub\n", pCrlContext, dwFlags, pbElement, - pcbElement); - return FALSE; -} - -BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext, - DWORD dwPropId, void *pvData, DWORD *pcbData) -{ - FIXME("(%p, %ld, %p, %p): stub\n", pCTLContext, dwPropId, pvData, pcbData); - return FALSE; -} - -BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext, - DWORD dwPropId, DWORD dwFlags, const void *pvData) -{ - FIXME("(%p, %ld, %08lx, %p): stub\n", pCTLContext, dwPropId, dwFlags, - pvData); - return FALSE; -} - -BOOL WINAPI CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext, - DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement) -{ - FIXME("(%p, %08lx, %p, %p): stub\n", pCtlContext, dwFlags, pbElement, - pcbElement); - return FALSE; -} - -BOOL WINAPI CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext, - DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement) -{ - BOOL ret; - - TRACE("(%p, %08lx, %p, %p)\n", pCertContext, dwFlags, pbElement, - pcbElement); - - if (pCertContext) - { - PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext; - DWORD bytesNeeded = sizeof(WINE_CERT_PROP_HEADER) + - pCertContext->cbCertEncoded; - PWINE_CERT_PROPERTY prop; - - EnterCriticalSection(&ref->context->cs); - LIST_FOR_EACH_ENTRY(prop, &ref->context->extendedProperties, - WINE_CERT_PROPERTY, entry) - bytesNeeded += sizeof(WINE_CERT_PROP_HEADER) + prop->hdr.cb; - if (!pbElement) - { - *pcbElement = bytesNeeded; - ret = TRUE; - } - else if (*pcbElement < bytesNeeded) - { - *pcbElement = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - PWINE_CERT_PROP_HEADER hdr; - - LIST_FOR_EACH_ENTRY(prop, &ref->context->extendedProperties, - WINE_CERT_PROPERTY, entry) - { - memcpy(pbElement, &prop->hdr, sizeof(WINE_CERT_PROP_HEADER)); - pbElement += sizeof(WINE_CERT_PROP_HEADER); - if (prop->hdr.cb) - { - memcpy(pbElement, prop->pbData, prop->hdr.cb); - pbElement += prop->hdr.cb; - } - } - hdr = (PWINE_CERT_PROP_HEADER)pbElement; - hdr->propID = CERT_CERT_PROP_ID; - hdr->unknown = 1; - hdr->cb = pCertContext->cbCertEncoded; - memcpy(pbElement + sizeof(WINE_CERT_PROP_HEADER), - pCertContext->pbCertEncoded, pCertContext->cbCertEncoded); - ret = TRUE; - } - LeaveCriticalSection(&ref->context->cs); - } - else - ret = FALSE; - return ret; -} - -/* Looks for the property with ID propID in the buffer buf. Returns a pointer - * to its header if a valid header is found, NULL if not. Valid means the - * length of thte property won't overrun buf, and the unknown field is 1. - */ -static const WINE_CERT_PROP_HEADER *CRYPT_findPropID(const BYTE *buf, - DWORD size, DWORD propID) -{ - const WINE_CERT_PROP_HEADER *ret = NULL; - BOOL done = FALSE; - - while (size && !ret && !done) - { - if (size < sizeof(WINE_CERT_PROP_HEADER)) - { - SetLastError(CRYPT_E_FILE_ERROR); - done = TRUE; - } - else - { - const WINE_CERT_PROP_HEADER *hdr = - (const WINE_CERT_PROP_HEADER *)buf; - - size -= sizeof(WINE_CERT_PROP_HEADER); - buf += sizeof(WINE_CERT_PROP_HEADER); - if (size < hdr->cb) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - done = TRUE; - } - else if (!hdr->propID) - { - /* assume a zero prop ID means the data are uninitialized, so - * stop looking. - */ - done = TRUE; - } - else if (hdr->unknown != 1) - { - SetLastError(ERROR_FILE_NOT_FOUND); - done = TRUE; - } - else if (hdr->propID == propID) - ret = hdr; - else - { - buf += hdr->cb; - size -= hdr->cb; - } - } - } - return ret; -} - -static const void * WINAPI CRYPT_ReadSerializedElement(const BYTE *pbElement, - DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType) -{ - const void *context; - - TRACE("(%p, %ld, %08lx, %p)\n", pbElement, cbElement, dwContextTypeFlags, - pdwContentType); - - if (!cbElement) - { - SetLastError(ERROR_END_OF_MEDIA); - return NULL; - } - - __TRY - { - const WINE_CONTEXT_INTERFACE *contextInterface = NULL; - const WINE_CERT_PROP_HEADER *hdr = NULL; - DWORD type = 0; - BOOL ret; - - ret = TRUE; - context = NULL; - if (dwContextTypeFlags == CERT_STORE_ALL_CONTEXT_FLAG) - { - hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID); - if (hdr) - type = CERT_STORE_CERTIFICATE_CONTEXT; - else - { - hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID); - if (hdr) - type = CERT_STORE_CRL_CONTEXT; - else - { - hdr = CRYPT_findPropID(pbElement, cbElement, - CERT_CTL_PROP_ID); - if (hdr) - type = CERT_STORE_CTL_CONTEXT; - } - } - } - else if (dwContextTypeFlags & CERT_STORE_CERTIFICATE_CONTEXT_FLAG) - { - hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID); - type = CERT_STORE_CERTIFICATE_CONTEXT; - } - else if (dwContextTypeFlags & CERT_STORE_CRL_CONTEXT_FLAG) - { - hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID); - type = CERT_STORE_CRL_CONTEXT; - } - else if (dwContextTypeFlags & CERT_STORE_CTL_CONTEXT_FLAG) - { - hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CTL_PROP_ID); - type = CERT_STORE_CTL_CONTEXT; - } - - switch (type) - { - case CERT_STORE_CERTIFICATE_CONTEXT: - contextInterface = &gCertInterface; - break; - case CERT_STORE_CRL_CONTEXT: - contextInterface = &gCRLInterface; - break; - case CERT_STORE_CTL_CONTEXT: - contextInterface = &gCTLInterface; - break; - default: - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - ret = FALSE; - } - if (!hdr) - ret = FALSE; - - if (ret) - context = contextInterface->create(X509_ASN_ENCODING, - (BYTE *)hdr + sizeof(WINE_CERT_PROP_HEADER), hdr->cb); - if (ret && context) - { - BOOL noMoreProps = FALSE; - - while (!noMoreProps && ret) - { - if (cbElement < sizeof(WINE_CERT_PROP_HEADER)) - ret = FALSE; - else - { - const WINE_CERT_PROP_HEADER *hdr = - (const WINE_CERT_PROP_HEADER *)pbElement; - - TRACE("prop is %ld\n", hdr->propID); - cbElement -= sizeof(WINE_CERT_PROP_HEADER); - pbElement += sizeof(WINE_CERT_PROP_HEADER); - if (cbElement < hdr->cb) - { - SetLastError(HRESULT_FROM_WIN32( - ERROR_INVALID_PARAMETER)); - ret = FALSE; - } - else if (!hdr->propID) - { - /* Like in CRYPT_findPropID, stop if the propID is zero - */ - noMoreProps = TRUE; - } - else if (hdr->unknown != 1) - { - SetLastError(ERROR_FILE_NOT_FOUND); - ret = FALSE; - } - else if (hdr->propID != CERT_CERT_PROP_ID && - hdr->propID != CERT_CRL_PROP_ID && hdr->propID != - CERT_CTL_PROP_ID) - { - /* Have to create a blob for most types, but not - * for all.. arghh. - */ - switch (hdr->propID) - { - case CERT_AUTO_ENROLL_PROP_ID: - case CERT_CTL_USAGE_PROP_ID: - case CERT_DESCRIPTION_PROP_ID: - case CERT_FRIENDLY_NAME_PROP_ID: - case CERT_HASH_PROP_ID: - case CERT_KEY_IDENTIFIER_PROP_ID: - case CERT_MD5_HASH_PROP_ID: - case CERT_NEXT_UPDATE_LOCATION_PROP_ID: - case CERT_PUBKEY_ALG_PARA_PROP_ID: - case CERT_PVK_FILE_PROP_ID: - case CERT_SIGNATURE_HASH_PROP_ID: - case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID: - case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID: - case CERT_ENROLLMENT_PROP_ID: - case CERT_CROSS_CERT_DIST_POINTS_PROP_ID: - case CERT_RENEWAL_PROP_ID: - { - CRYPT_DATA_BLOB blob = { hdr->cb, - (LPBYTE)pbElement }; - - ret = contextInterface->setProp(context, - hdr->propID, 0, &blob); - break; - } - case CERT_DATE_STAMP_PROP_ID: - ret = contextInterface->setProp(context, - hdr->propID, 0, pbElement); - break; - default: - FIXME("prop ID %ld: stub\n", hdr->propID); - } - } - pbElement += hdr->cb; - cbElement -= hdr->cb; - if (!cbElement) - noMoreProps = TRUE; - } - } - if (ret) - { - if (pdwContentType) - *pdwContentType = type; - } - else - { - contextInterface->free(context); - context = NULL; - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - context = NULL; - } - __ENDTRY - return context; -} - -BOOL WINAPI CertAddSerializedElementToStore(HCERTSTORE hCertStore, - const BYTE *pbElement, DWORD cbElement, DWORD dwAddDisposition, DWORD dwFlags, - DWORD dwContextTypeFlags, DWORD *pdwContentType, const void **ppvContext) -{ - const void *context; - DWORD type; - BOOL ret; - - TRACE("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p)\n", hCertStore, - pbElement, cbElement, dwAddDisposition, dwFlags, dwContextTypeFlags, - pdwContentType, ppvContext); - - /* Call the internal function, then delete the hashes. Tests show this - * function uses real hash values, not whatever's stored in the hash - * property. - */ - context = CRYPT_ReadSerializedElement(pbElement, cbElement, - dwContextTypeFlags, &type); - if (context) - { - const WINE_CONTEXT_INTERFACE *contextInterface = NULL; - - switch (type) - { - case CERT_STORE_CERTIFICATE_CONTEXT: - contextInterface = &gCertInterface; - break; - case CERT_STORE_CRL_CONTEXT: - contextInterface = &gCRLInterface; - break; - case CERT_STORE_CTL_CONTEXT: - contextInterface = &gCTLInterface; - break; - default: - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - } - if (contextInterface) - { - contextInterface->setProp(context, CERT_HASH_PROP_ID, 0, NULL); - contextInterface->setProp(context, CERT_MD5_HASH_PROP_ID, 0, NULL); - contextInterface->setProp(context, CERT_SIGNATURE_HASH_PROP_ID, 0, - NULL); - if (pdwContentType) - *pdwContentType = type; - ret = contextInterface->addContextToStore(hCertStore, context, - dwAddDisposition, ppvContext); - contextInterface->free(context); - } - else - ret = FALSE; - } - else - ret = FALSE; - return ret; -} - -BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext) -{ - TRACE("(%p)\n", pCertContext); - - if (pCertContext) - { - PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext; - PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)ref->cert.hCertStore; - - if (InterlockedDecrement(&ref->context->ref) == 0) - { - TRACE("%p's ref count is 0, freeing\n", ref->context); - CRYPT_FreeCert(ref->context); - } - else - TRACE("%p's ref count is %ld\n", ref->context, ref->context->ref); - if (store && store->dwMagic == WINE_CRYPTCERTSTORE_MAGIC && - store->freeCert) - store->freeCert(ref); - CryptMemFree(ref); - } - return TRUE; -} - -PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore, - DWORD dwCertEncodingType, DWORD dwFlags, DWORD dwType, - const void *pvPara, PCCERT_CONTEXT pPrevCertContext) -{ - FIXME("stub: %p %ld %ld %ld %p %p\n", hCertStore, dwCertEncodingType, - dwFlags, dwType, pvPara, pPrevCertContext); - SetLastError(CRYPT_E_NOT_FOUND); - return NULL; -} - -BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore, - HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority) -{ - PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore; - WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore; - PWINE_STORE_LIST_ENTRY entry; - BOOL ret; - - TRACE("(%p, %p, %08lx, %ld)\n", hCollectionStore, hSiblingStore, - dwUpdateFlags, dwPriority); - - if (!collection || !sibling) - return TRUE; - if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return FALSE; - } - if (collection->hdr.type != StoreTypeCollection) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return FALSE; - } - if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return FALSE; - } - - entry = CryptMemAlloc(sizeof(WINE_STORE_LIST_ENTRY)); - if (entry) - { - InterlockedIncrement(&sibling->ref); - TRACE("sibling %p's ref count is %ld\n", sibling, sibling->ref); - entry->store = sibling; - entry->dwUpdateFlags = dwUpdateFlags; - entry->dwPriority = dwPriority; - list_init(&entry->entry); - TRACE("%p: adding %p, priority %ld\n", collection, entry, dwPriority); - EnterCriticalSection(&collection->cs); - if (dwPriority) - { - PWINE_STORE_LIST_ENTRY cursor; - BOOL added = FALSE; - - LIST_FOR_EACH_ENTRY(cursor, &collection->stores, - WINE_STORE_LIST_ENTRY, entry) - { - if (cursor->dwPriority < dwPriority) - { - list_add_before(&cursor->entry, &entry->entry); - added = TRUE; - break; - } - } - if (!added) - list_add_tail(&collection->stores, &entry->entry); - } - else - list_add_tail(&collection->stores, &entry->entry); - LeaveCriticalSection(&collection->cs); - ret = TRUE; - } - else - ret = FALSE; - return ret; -} - -void WINAPI CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore, - HCERTSTORE hSiblingStore) -{ - PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore; - WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore; - PWINE_STORE_LIST_ENTRY store, next; - - TRACE("(%p, %p)\n", hCollectionStore, hSiblingStore); - - if (!collection || !sibling) - return; - if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return; - } - if (collection->hdr.type != StoreTypeCollection) - return; - if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return; - } - EnterCriticalSection(&collection->cs); - LIST_FOR_EACH_ENTRY_SAFE(store, next, &collection->stores, - WINE_STORE_LIST_ENTRY, entry) - { - if (store->store == sibling) - { - list_remove(&store->entry); - CertCloseStore(store->store, 0); - CryptMemFree(store); - break; - } - } - LeaveCriticalSection(&collection->cs); -} - -PCRYPT_ATTRIBUTE WINAPI CertFindAttribute(LPCSTR pszObjId, DWORD cAttr, - CRYPT_ATTRIBUTE rgAttr[]) -{ - PCRYPT_ATTRIBUTE ret = NULL; - DWORD i; - - TRACE("%s %ld %p\n", debugstr_a(pszObjId), cAttr, rgAttr); - - if (!cAttr) - return NULL; - if (!pszObjId) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - for (i = 0; !ret && i < cAttr; i++) - if (rgAttr[i].pszObjId && !strcmp(pszObjId, rgAttr[i].pszObjId)) - ret = &rgAttr[i]; - return ret; -} - -PCERT_EXTENSION WINAPI CertFindExtension(LPCSTR pszObjId, DWORD cExtensions, - CERT_EXTENSION rgExtensions[]) -{ - PCERT_EXTENSION ret = NULL; - DWORD i; - - TRACE("%s %ld %p\n", debugstr_a(pszObjId), cExtensions, rgExtensions); - - if (!cExtensions) - return NULL; - if (!pszObjId) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - for (i = 0; !ret && i < cExtensions; i++) - if (rgExtensions[i].pszObjId && !strcmp(pszObjId, - rgExtensions[i].pszObjId)) - ret = &rgExtensions[i]; - return ret; -} - -PCERT_RDN_ATTR WINAPI CertFindRDNAttr(LPCSTR pszObjId, PCERT_NAME_INFO pName) -{ - PCERT_RDN_ATTR ret = NULL; - DWORD i, j; - - TRACE("%s %p\n", debugstr_a(pszObjId), pName); - - if (!pszObjId) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - for (i = 0; !ret && i < pName->cRDN; i++) - for (j = 0; !ret && j < pName->rgRDN[i].cRDNAttr; j++) - if (pName->rgRDN[i].rgRDNAttr[j].pszObjId && !strcmp(pszObjId, - pName->rgRDN[i].rgRDNAttr[j].pszObjId)) - ret = &pName->rgRDN[i].rgRDNAttr[j]; - return ret; -} - -LONG WINAPI CertVerifyTimeValidity(LPFILETIME pTimeToVerify, - PCERT_INFO pCertInfo) -{ - FILETIME fileTime; - LONG ret; - - if (!pTimeToVerify) - { - SYSTEMTIME sysTime; - - GetSystemTime(&sysTime); - SystemTimeToFileTime(&sysTime, &fileTime); - pTimeToVerify = &fileTime; - } - if ((ret = CompareFileTime(pTimeToVerify, &pCertInfo->NotBefore)) >= 0) - { - ret = CompareFileTime(pTimeToVerify, &pCertInfo->NotAfter); - if (ret < 0) - ret = 0; - } - return ret; -} - -BOOL WINAPI CryptHashCertificate(HCRYPTPROV hCryptProv, ALG_ID Algid, - DWORD dwFlags, const BYTE *pbEncoded, DWORD cbEncoded, BYTE *pbComputedHash, - DWORD *pcbComputedHash) -{ - BOOL ret = TRUE; - HCRYPTHASH hHash = 0; - - TRACE("(%ld, %d, %08lx, %p, %ld, %p, %p)\n", hCryptProv, Algid, dwFlags, - pbEncoded, cbEncoded, pbComputedHash, pcbComputedHash); - - if (!hCryptProv) - hCryptProv = CRYPT_GetDefaultProvider(); - if (!Algid) - Algid = CALG_SHA1; - if (ret) - { - ret = CryptCreateHash(hCryptProv, Algid, 0, 0, &hHash); - if (ret) - { - ret = CryptHashData(hHash, pbEncoded, cbEncoded, 0); - if (ret) - ret = CryptGetHashParam(hHash, HP_HASHVAL, pbComputedHash, - pcbComputedHash, 0); - CryptDestroyHash(hHash); - } - } - return ret; -} - -BOOL WINAPI CryptSignCertificate(HCRYPTPROV hCryptProv, DWORD dwKeySpec, - DWORD dwCertEncodingType, const BYTE *pbEncodedToBeSigned, - DWORD cbEncodedToBeSigned, PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, - const void *pvHashAuxInfo, BYTE *pbSignature, DWORD *pcbSignature) -{ - BOOL ret; - ALG_ID algID; - HCRYPTHASH hHash; - - TRACE("(%08lx, %ld, %ld, %p, %ld, %p, %p, %p, %p)\n", hCryptProv, - dwKeySpec, dwCertEncodingType, pbEncodedToBeSigned, cbEncodedToBeSigned, - pSignatureAlgorithm, pvHashAuxInfo, pbSignature, pcbSignature); - - algID = CertOIDToAlgId(pSignatureAlgorithm->pszObjId); - if (!algID) - { - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - if (!hCryptProv) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - ret = CryptCreateHash(hCryptProv, algID, 0, 0, &hHash); - if (ret) - { - ret = CryptHashData(hHash, pbEncodedToBeSigned, cbEncodedToBeSigned, 0); - if (ret) - ret = CryptSignHashW(hHash, dwKeySpec, NULL, 0, pbSignature, - pcbSignature); - CryptDestroyHash(hHash); - } - return ret; -} - -BOOL WINAPI CryptVerifyCertificateSignature(HCRYPTPROV hCryptProv, - DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded, - PCERT_PUBLIC_KEY_INFO pPublicKey) -{ - return CryptVerifyCertificateSignatureEx(hCryptProv, dwCertEncodingType, - CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, (void *)pbEncoded, - CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pPublicKey, 0, NULL); -} - -BOOL WINAPI CryptVerifyCertificateSignatureEx(HCRYPTPROV hCryptProv, - DWORD dwCertEncodingType, DWORD dwSubjectType, void *pvSubject, - DWORD dwIssuerType, void *pvIssuer, DWORD dwFlags, void *pvReserved) -{ - BOOL ret = TRUE; - CRYPT_DATA_BLOB subjectBlob; - - TRACE("(%08lx, %ld, %ld, %p, %ld, %p, %08lx, %p)\n", hCryptProv, - dwCertEncodingType, dwSubjectType, pvSubject, dwIssuerType, pvIssuer, - dwFlags, pvReserved); - - switch (dwSubjectType) - { - case CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB: - { - PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvSubject; - - subjectBlob.pbData = blob->pbData; - subjectBlob.cbData = blob->cbData; - break; - } - case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT: - { - PCERT_CONTEXT context = (PCERT_CONTEXT)pvSubject; - - subjectBlob.pbData = context->pbCertEncoded; - subjectBlob.cbData = context->cbCertEncoded; - break; - } - case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL: - { - PCRL_CONTEXT context = (PCRL_CONTEXT)pvSubject; - - subjectBlob.pbData = context->pbCrlEncoded; - subjectBlob.cbData = context->cbCrlEncoded; - break; - } - default: - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - ret = FALSE; - } - - if (ret) - { - PCERT_SIGNED_CONTENT_INFO signedCert = NULL; - DWORD size = 0; - - ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT, - subjectBlob.pbData, subjectBlob.cbData, - CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, - (BYTE *)&signedCert, &size); - if (ret) - { - switch (dwIssuerType) - { - case CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY: - { - PCERT_PUBLIC_KEY_INFO pubKeyInfo = - (PCERT_PUBLIC_KEY_INFO)pvIssuer; - ALG_ID algID = CertOIDToAlgId(pubKeyInfo->Algorithm.pszObjId); - - if (algID) - { - HCRYPTKEY key; - - ret = CryptImportPublicKeyInfoEx(hCryptProv, - dwCertEncodingType, pubKeyInfo, algID, 0, NULL, &key); - if (ret) - { - HCRYPTHASH hash; - - ret = CryptCreateHash(hCryptProv, algID, 0, 0, &hash); - if (ret) - { - ret = CryptHashData(hash, - signedCert->ToBeSigned.pbData, - signedCert->ToBeSigned.cbData, 0); - if (ret) - { - ret = CryptVerifySignatureW(hash, - signedCert->Signature.pbData, - signedCert->Signature.cbData, key, NULL, 0); - } - CryptDestroyHash(hash); - } - CryptDestroyKey(key); - } - } - else - { - SetLastError(NTE_BAD_ALGID); - ret = FALSE; - } - break; - } - case CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT: - case CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN: - FIXME("issuer type %ld: stub\n", dwIssuerType); - ret = FALSE; - break; - case CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL: - if (pvIssuer) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - ret = FALSE; - } - else - { - FIXME("unimplemented for NULL signer\n"); - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - ret = FALSE; - } - break; - default: - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - ret = FALSE; - } - LocalFree(signedCert); - } - } - return ret; -} - -HCRYPTOIDFUNCSET WINAPI CryptInitOIDFunctionSet(LPCSTR pszFuncName, DWORD dwFlags) -{ - FIXME("stub: %s %lx\n", debugstr_a(pszFuncName), dwFlags); - return NULL; -} - -BOOL WINAPI CryptUnregisterDefaultOIDFunction(DWORD dwEncodingType, - LPCSTR pszFuncName, LPCWSTR pwszDll) -{ - FIXME("stub: %lx %s %s\n", dwEncodingType, debugstr_a(pszFuncName), debugstr_w(pwszDll)); - return FALSE; -} diff --git a/reactos/lib/crypt32/crypt32.def b/reactos/lib/crypt32/crypt32.def deleted file mode 100644 index 079203b0f74..00000000000 --- a/reactos/lib/crypt32/crypt32.def +++ /dev/null @@ -1,36 +0,0 @@ -LIBRARY CRYPT32.DLL -EXPORTS - -CertAlgIdToOID@4 @1030 - -CertOIDToAlgId@4 @1095 - -CryptMemAlloc@4 @1175 -CryptMemFree@4 @1176 -CryptMemRealloc@8 @1177 - -CryptProtectData@28 @1193 - -CryptRegisterDefaultOIDFunction@16 @1195 -CryptSIPAddProvider@4 @1198 - -CryptSIPLoad@12 @1201 -CryptSIPRemoveProvider@4 @1203 - -CryptSIPRetrieveSubjectGuid@12 @1205 - -CryptUnprotectData@28 @1221 - -I_CryptCreateLruCache@8 @1240 - -I_CryptDetachTls@4 @1242 - -I_CryptFindLruEntryData@4 @1247 - -I_CryptFlushLruCache@4 @1249 -I_CryptFreeLruCache@4 @1250 -I_CryptFreeTls@8 @1251 - -I_CryptGetTls@4 @1260 - -I_CryptSetTls@8 @1268 \ No newline at end of file diff --git a/reactos/lib/crypt32/crypt32.rc b/reactos/lib/crypt32/crypt32.rc deleted file mode 100644 index 4db5b6262d2..00000000000 --- a/reactos/lib/crypt32/crypt32.rc +++ /dev/null @@ -1,7 +0,0 @@ -/* $Id: crypt32.rc $ */ - -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "Crypt\0" -#define REACTOS_STR_INTERNAL_NAME "crypt32\0" -#define REACTOS_STR_ORIGINAL_FILENAME "crypt32.dll\0" -#include diff --git a/reactos/lib/crypt32/crypt32.xml b/reactos/lib/crypt32/crypt32.xml deleted file mode 100644 index 50a99d80908..00000000000 --- a/reactos/lib/crypt32/crypt32.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - . - - 0x501 - ntdll - kernel32 - wine - advapi32 - main.c - protectdata.c - crypt32.rc - precomp.h - diff --git a/reactos/lib/crypt32/crypt32_private.h b/reactos/lib/crypt32/crypt32_private.h deleted file mode 100644 index 9b593533723..00000000000 --- a/reactos/lib/crypt32/crypt32_private.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __CRYPT32_PRIVATE_H__ -#define __CRYPT32_PRIVATE_H__ - -/* Returns a handle to the default crypto provider; loads it if necessary. - * Returns NULL on failure. - */ -HCRYPTPROV CRYPT_GetDefaultProvider(void); - -#endif diff --git a/reactos/lib/crypt32/encode.c b/reactos/lib/crypt32/encode.c deleted file mode 100644 index cd9eaddd807..00000000000 --- a/reactos/lib/crypt32/encode.c +++ /dev/null @@ -1,5688 +0,0 @@ -/* - * Copyright 2002 Mike McCormack for CodeWeavers - * Copyright 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This file implements ASN.1 DER encoding and decoding of a limited set of - * types. It isn't a full ASN.1 implementation. Microsoft implements BER - * encoding of many of the basic types in msasn1.dll, but that interface is - * undocumented, so I implement them here. - * - * References: - * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski - * (available online, look for a PDF copy as the HTML versions tend to have - * translation errors.) - * - * RFC3280, http://www.faqs.org/rfcs/rfc3280.html - * - * MSDN, especially: - * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp - */ - -#include "precomp.h" - -/* This is a bit arbitrary, but to set some limit: */ -#define MAX_ENCODED_LEN 0x02000000 - -/* a few asn.1 tags we need */ -#define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01) -#define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03) -#define ASN_OCTETSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x04) -#define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a) -#define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11) -#define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12) -#define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13) -#define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16) -#define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17) -#define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18) - -#define ASN_FLAGS_MASK 0xf0 -#define ASN_TYPE_MASK 0x0f - -WINE_DEFAULT_DEBUG_CHANNEL(crypt); - -static const WCHAR szDllName[] = { 'D','l','l',0 }; - -typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *, - BYTE *, DWORD *); -typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *, - DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *); -typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *, - DWORD, DWORD, void *, DWORD *); -typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *, - DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *); - -/* Prototypes for built-in encoders/decoders. They follow the Ex style - * prototypes. The dwCertEncodingType and lpszStructType are ignored by the - * built-in functions, but the parameters are retained to simplify - * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in - * external DLLs that follow these signatures. - * FIXME: some built-in functions are suitable to be called directly by - * CryptEncodeObjectEx/CryptDecodeObjectEx (they implement exception handling - * and memory allocation if requested), others are only suitable to be called - * internally. Comment which are which. - */ -static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); -static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); - -static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -/* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of - * time, doesn't do memory allocation, and doesn't do exception handling. - * (This isn't intended to be the externally-called one.) - */ -static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded, - DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId); -/* Assumes algo->Parameters.pbData is set ahead of time */ -static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -/* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */ -static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -/* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData - * member has been initialized, doesn't do exception handling, and doesn't do - * memory allocation. - */ -static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -/* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData - * member has been initialized, doesn't do exception handling, and doesn't do - * memory allocation. - */ -static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); -/* Like CRYPT_AsnDecodeInteger, but unsigned. */ -static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal( - DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, - DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, - void *pvStructInfo, DWORD *pcbStructInfo); - -/* filter for page-fault exceptions */ -static WINE_EXCEPTION_FILTER(page_fault) -{ - if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) - return EXCEPTION_EXECUTE_HANDLER; - return EXCEPTION_CONTINUE_SEARCH; -} - -static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName, - LPCSTR pszOID) -{ - static const char szEncodingTypeFmt[] = - "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s"; - UINT len; - char numericOID[7]; /* enough for "#65535" */ - const char *oid; - LPSTR szKey; - - /* MSDN says the encoding type is a mask, but it isn't treated that way. - * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and - * "EncodingType 2" would be expected if it were a mask. Instead native - * stores values in "EncodingType 3". - */ - if (!HIWORD(pszOID)) - { - snprintf(numericOID, sizeof(numericOID), "#%d", LOWORD(pszOID)); - oid = numericOID; - } - else - oid = pszOID; - - /* This is enough: the lengths of the two string parameters are explicitly - * counted, and we need up to five additional characters for the encoding - * type. These are covered by the "%d", "%s", and "%s" characters in the - * format specifier that are removed by sprintf. - */ - len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid); - szKey = CryptMemAlloc(len); - if (szKey) - sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid); - return szKey; -} - -BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName, - LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName) -{ - LONG r; - HKEY hKey; - LPSTR szKey; - - TRACE("%lx %s %s %s %s\n", dwEncodingType, pszFuncName, pszOID, - debugstr_w(pwszDll), pszOverrideFuncName); - - /* This only registers functions for encoding certs, not messages */ - if (!GET_CERT_ENCODING_TYPE(dwEncodingType)) - return TRUE; - - /* Native does nothing pwszDll is NULL */ - if (!pwszDll) - return TRUE; - - /* I'm not matching MS bug for bug here, because I doubt any app depends on - * it: - * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry - * it creates would never be used - * - native returns an HRESULT rather than a Win32 error if pszOID is NULL. - * Instead I disallow both of these with ERROR_INVALID_PARAMETER. - */ - if (!pszFuncName || !pszOID) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID); - TRACE("Key name is %s\n", debugstr_a(szKey)); - - if (!szKey) - return FALSE; - - r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey); - CryptMemFree(szKey); - if(r != ERROR_SUCCESS) - return FALSE; - - /* write the values */ - if (pszOverrideFuncName) - RegSetValueExA(hKey, "FuncName", 0, REG_SZ, (const BYTE*)pszOverrideFuncName, - lstrlenA(pszOverrideFuncName) + 1); - RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*) pwszDll, - (lstrlenW(pwszDll) + 1) * sizeof (WCHAR)); - - RegCloseKey(hKey); - return TRUE; -} - -BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName, - LPCSTR pszOID) -{ - LPSTR szKey; - LONG rc; - - TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID); - - if (!GET_CERT_ENCODING_TYPE(dwEncodingType)) - return TRUE; - - if (!pszFuncName || !pszOID) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID); - rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey); - CryptMemFree(szKey); - if (rc) - SetLastError(rc); - return rc ? FALSE : TRUE; -} - -BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName, - LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData, - DWORD *pcbValueData) -{ - LPSTR szKey; - LONG rc; - HKEY hKey; - - TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName), - debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData, - pcbValueData); - - if (!GET_CERT_ENCODING_TYPE(dwEncodingType)) - return TRUE; - - if (!pszFuncName || !pszOID || !pwszValueName) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID); - rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey); - CryptMemFree(szKey); - if (rc) - SetLastError(rc); - else - { - rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType, - pbValueData, pcbValueData); - if (rc) - SetLastError(rc); - RegCloseKey(hKey); - } - return rc ? FALSE : TRUE; -} - -BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName, - LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType, - const BYTE *pbValueData, DWORD cbValueData) -{ - LPSTR szKey; - LONG rc; - HKEY hKey; - - TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType, debugstr_a(pszFuncName), - debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData, - cbValueData); - - if (!GET_CERT_ENCODING_TYPE(dwEncodingType)) - return TRUE; - - if (!pszFuncName || !pszOID || !pwszValueName) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID); - rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey); - CryptMemFree(szKey); - if (rc) - SetLastError(rc); - else - { - rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData, - cbValueData); - if (rc) - SetLastError(rc); - RegCloseKey(hKey); - } - return rc ? FALSE : TRUE; -} - -/* Gets the registered function named szFuncName for dwCertEncodingType and - * lpszStructType, or NULL if one could not be found. *lib will be set to the - * handle of the module it's in, or NULL if no module was loaded. If the - * return value is NULL, *lib will also be NULL, to simplify error handling. - */ -static void *CRYPT_GetFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType, - LPCSTR szFuncName, HMODULE *lib) -{ - void *ret = NULL; - char *szKey = CRYPT_GetKeyName(dwCertEncodingType, szFuncName, - lpszStructType); - const char *funcName; - long r; - HKEY hKey; - DWORD type, size = 0; - - TRACE("(%08lx %s %s %p)\n", dwCertEncodingType, debugstr_a(lpszStructType), - debugstr_a(szFuncName), lib); - - *lib = NULL; - r = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey); - CryptMemFree(szKey); - if(r != ERROR_SUCCESS) - return NULL; - - RegQueryValueExA(hKey, "FuncName", NULL, &type, NULL, &size); - if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ) - { - funcName = CryptMemAlloc(size); - RegQueryValueExA(hKey, "FuncName", NULL, &type, (LPBYTE)funcName, - &size); - } - else - funcName = szFuncName; - RegQueryValueExW(hKey, szDllName, NULL, &type, NULL, &size); - if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ) - { - LPWSTR dllName = CryptMemAlloc(size); - - RegQueryValueExW(hKey, szDllName, NULL, &type, (LPBYTE)dllName, - &size); - *lib = LoadLibraryW(dllName); - if (*lib) - { - ret = GetProcAddress(*lib, funcName); - if (!ret) - { - /* Unload the library, the caller doesn't want to unload it - * when the return value is NULL. - */ - FreeLibrary(*lib); - *lib = NULL; - } - } - CryptMemFree(dllName); - } - if (funcName != szFuncName) - CryptMemFree((char *)funcName); - TRACE("returning %p\n", ret); - return ret; -} - -BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType, - const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret = FALSE; - HMODULE lib; - CryptEncodeObjectFunc pCryptEncodeObject; - - TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType, - debugstr_a(lpszStructType), pvStructInfo, pbEncoded, - pcbEncoded); - - if (!pbEncoded && !pcbEncoded) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* Try registered DLL first.. */ - pCryptEncodeObject = - (CryptEncodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType, - lpszStructType, CRYPT_OID_ENCODE_OBJECT_FUNC, &lib); - if (pCryptEncodeObject) - { - ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType, - pvStructInfo, pbEncoded, pcbEncoded); - FreeLibrary(lib); - } - else - { - /* If not, use CryptEncodeObjectEx */ - ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType, - pvStructInfo, 0, NULL, pbEncoded, pcbEncoded); - } - return ret; -} - -/* Helper function to check *pcbEncoded, set it to the required size, and - * optionally to allocate memory. Assumes pbEncoded is not NULL. - * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a - * pointer to the newly allocated memory. - */ -static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded, - DWORD bytesNeeded) -{ - BOOL ret = TRUE; - - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - { - if (pEncodePara && pEncodePara->pfnAlloc) - *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded); - else - *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded); - if (!*(BYTE **)pbEncoded) - ret = FALSE; - else - *pcbEncoded = bytesNeeded; - } - else if (bytesNeeded > *pcbEncoded) - { - *pcbEncoded = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - return ret; -} - -static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - DWORD bytesNeeded, significantBytes = 0; - - if (len <= 0x7f) - bytesNeeded = 1; - else - { - DWORD temp; - - for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000); - temp <<= 8, significantBytes--) - ; - bytesNeeded = significantBytes + 1; - } - if (!pbEncoded) - { - *pcbEncoded = bytesNeeded; - return TRUE; - } - if (*pcbEncoded < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - return FALSE; - } - if (len <= 0x7f) - *pbEncoded = (BYTE)len; - else - { - DWORD i; - - *pbEncoded++ = significantBytes | 0x80; - for (i = 0; i < significantBytes; i++) - { - *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff); - len >>= 8; - } - } - *pcbEncoded = bytesNeeded; - return TRUE; -} - -struct AsnEncodeSequenceItem -{ - const void *pvStructInfo; - CryptEncodeObjectExFunc encodeFunc; - DWORD size; /* used during encoding, not for your use */ -}; - -static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType, - struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - DWORD i, dataLen = 0; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items, cItem, dwFlags, pEncodePara, - pbEncoded, *pcbEncoded); - for (i = 0, ret = TRUE; ret && i < cItem; i++) - { - ret = items[i].encodeFunc(dwCertEncodingType, NULL, - items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, - NULL, &items[i].size); - dataLen += items[i].size; - } - if (ret) - { - DWORD lenBytes, bytesNeeded; - - CRYPT_EncodeLen(dataLen, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + dataLen; - if (!pbEncoded) - *pcbEncoded = bytesNeeded; - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, - pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_SEQUENCE; - CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - for (i = 0; ret && i < cItem; i++) - { - ret = items[i].encodeFunc(dwCertEncodingType, NULL, - items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, - NULL, pbEncoded, &items[i].size); - pbEncoded += items[i].size; - } - } - } - } - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -struct AsnConstructedItem -{ - BYTE tag; - const void *pvStructInfo; - CryptEncodeObjectExFunc encodeFunc; -}; - -static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - const struct AsnConstructedItem *item = - (const struct AsnConstructedItem *)pvStructInfo; - DWORD len; - - if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType, - item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len))) - { - DWORD dataLen, bytesNeeded; - - CRYPT_EncodeLen(len, NULL, &dataLen); - bytesNeeded = 1 + dataLen + len; - if (!pbEncoded) - *pcbEncoded = bytesNeeded; - else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, - pbEncoded, pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag; - CRYPT_EncodeLen(len, pbEncoded, &dataLen); - pbEncoded += dataLen; - ret = item->encodeFunc(dwCertEncodingType, lpszStructType, - item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, - pbEncoded, &len); - } - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - const DWORD *ver = (const DWORD *)pvStructInfo; - BOOL ret; - - /* CERT_V1 is not encoded */ - if (*ver == CERT_V1) - { - *pcbEncoded = 0; - ret = TRUE; - } - else - { - struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt }; - - ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER, - &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded); - } - return ret; -} - -static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo; - BOOL ret; - - if (!pbEncoded) - { - *pcbEncoded = blob->cbData; - ret = TRUE; - } - else if (*pcbEncoded < blob->cbData) - { - *pcbEncoded = blob->cbData; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - if (blob->cbData) - memcpy(pbEncoded, blob->pbData, blob->cbData); - *pcbEncoded = blob->cbData; - ret = TRUE; - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - /* This has two filetimes in a row, a NotBefore and a NotAfter */ - const FILETIME *timePtr = (const FILETIME *)pvStructInfo; - struct AsnEncodeSequenceItem items[] = { - { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 }, - { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 }, - }; - - ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, - pcbEncoded); - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId( - DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, - DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, - DWORD *pcbEncoded) -{ - const CRYPT_ALGORITHM_IDENTIFIER *algo = - (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo; - BOOL ret; - struct AsnEncodeSequenceItem items[] = { - { algo->pszObjId, CRYPT_AsnEncodeOid, 0 }, - { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 }, - }; - - ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, - pcbEncoded); - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CERT_PUBLIC_KEY_INFO *info = - (const CERT_PUBLIC_KEY_INFO *)pvStructInfo; - struct AsnEncodeSequenceItem items[] = { - { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, - { &info->PublicKey, CRYPT_AsnEncodeBits, 0 }, - }; - - TRACE("Encoding public key with OID %s\n", - debugstr_a(info->Algorithm.pszObjId)); - ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, - pcbEncoded); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CERT_SIGNED_CONTENT_INFO *info = - (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo; - struct AsnEncodeSequenceItem items[] = { - { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 }, - { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, - { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 }, - }; - - if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG) - items[2].encodeFunc = CRYPT_AsnEncodeBits; - ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, - pcbEncoded); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -/* Like in Windows, this blithely ignores the validity of the passed-in - * CERT_INFO, and just encodes it as-is. The resulting encoded data may not - * decode properly, see CRYPT_AsnDecodeCertInfo. - */ -static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CERT_INFO *info = (const CERT_INFO *)pvStructInfo; - struct AsnEncodeSequenceItem items[10] = { - { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 }, - { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, - { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, - { &info->Issuer, CRYPT_CopyEncodedBlob, 0 }, - { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 }, - { &info->Subject, CRYPT_CopyEncodedBlob, 0 }, - { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 }, - { 0 } - }; - struct AsnConstructedItem constructed[3] = { { 0 } }; - DWORD cItem = 7, cConstructed = 0; - - if (info->IssuerUniqueId.cbData) - { - constructed[cConstructed].tag = 1; - constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId; - constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits; - items[cItem].pvStructInfo = &constructed[cConstructed]; - items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; - cConstructed++; - cItem++; - } - if (info->SubjectUniqueId.cbData) - { - constructed[cConstructed].tag = 2; - constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId; - constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits; - items[cItem].pvStructInfo = &constructed[cConstructed]; - items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; - cConstructed++; - cItem++; - } - if (info->cExtension) - { - constructed[cConstructed].tag = 3; - constructed[cConstructed].pvStructInfo = &info->cExtension; - constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions; - items[cItem].pvStructInfo = &constructed[cConstructed]; - items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed; - cConstructed++; - cItem++; - } - - ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, - dwFlags, pEncodePara, pbEncoded, pcbEncoded); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry, - BYTE *pbEncoded, DWORD *pcbEncoded) -{ - struct AsnEncodeSequenceItem items[3] = { - { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, - { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 }, - { 0 } - }; - DWORD cItem = 2; - BOOL ret; - - TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded); - - if (entry->cExtension) - { - items[cItem].pvStructInfo = &entry->cExtension; - items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions; - cItem++; - } - - ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL, - pbEncoded, pcbEncoded); - - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - DWORD cCRLEntry = *(const DWORD *)pvStructInfo; - DWORD bytesNeeded, dataLen, lenBytes, i; - const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY **) - ((const BYTE *)pvStructInfo + sizeof(DWORD)); - BOOL ret = TRUE; - - for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++) - { - DWORD size; - - ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size); - if (ret) - dataLen += size; - } - CRYPT_EncodeLen(dataLen, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + dataLen; - if (!pbEncoded) - *pcbEncoded = bytesNeeded; - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, - pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_SEQUENCEOF; - CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - for (i = 0; i < cCRLEntry; i++) - { - DWORD size = dataLen; - - ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size); - pbEncoded += size; - dataLen -= size; - } - } - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - const DWORD *ver = (const DWORD *)pvStructInfo; - BOOL ret; - - /* CRL_V1 is not encoded */ - if (*ver == CRL_V1) - { - *pcbEncoded = 0; - ret = TRUE; - } - else - ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver, - dwFlags, pEncodePara, pbEncoded, pcbEncoded); - return ret; -} - -/* Like in Windows, this blithely ignores the validity of the passed-in - * CRL_INFO, and just encodes it as-is. The resulting encoded data may not - * decode properly, see CRYPT_AsnDecodeCRLInfo. - */ -static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CRL_INFO *info = (const CRL_INFO *)pvStructInfo; - struct AsnEncodeSequenceItem items[7] = { - { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 }, - { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, - { &info->Issuer, CRYPT_CopyEncodedBlob, 0 }, - { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 }, - { 0 } - }; - DWORD cItem = 4; - - if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime) - { - items[cItem].pvStructInfo = &info->NextUpdate; - items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime; - cItem++; - } - if (info->cCRLEntry) - { - items[cItem].pvStructInfo = &info->cCRLEntry; - items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries; - cItem++; - } - if (info->cExtension) - { - items[cItem].pvStructInfo = &info->cExtension; - items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions; - cItem++; - } - - ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, - dwFlags, pEncodePara, pbEncoded, pcbEncoded); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded, - DWORD *pcbEncoded) -{ - BOOL ret; - struct AsnEncodeSequenceItem items[3] = { - { ext->pszObjId, CRYPT_AsnEncodeOid, 0 }, - { NULL, NULL, 0 }, - { NULL, NULL, 0 }, - }; - DWORD cItem = 1; - - TRACE("%p, %p, %ld\n", ext, pbEncoded, *pcbEncoded); - - if (ext->fCritical) - { - items[cItem].pvStructInfo = &ext->fCritical; - items[cItem].encodeFunc = CRYPT_AsnEncodeBool; - cItem++; - } - items[cItem].pvStructInfo = &ext->Value; - items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; - cItem++; - - ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL, - pbEncoded, pcbEncoded); - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - DWORD bytesNeeded, dataLen, lenBytes, i; - const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo; - - ret = TRUE; - for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++) - { - DWORD size; - - ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size); - if (ret) - dataLen += size; - } - CRYPT_EncodeLen(dataLen, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + dataLen; - if (!pbEncoded) - *pcbEncoded = bytesNeeded; - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, - pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_SEQUENCEOF; - CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - for (i = 0; i < exts->cExtension; i++) - { - DWORD size = dataLen; - - ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], - pbEncoded, &size); - pbEncoded += size; - dataLen -= size; - } - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - LPCSTR pszObjId = (LPCSTR)pvStructInfo; - DWORD bytesNeeded = 0, lenBytes; - BOOL ret = TRUE; - int firstPos = 0; - BYTE firstByte = 0; - - TRACE("%s\n", debugstr_a(pszObjId)); - - if (pszObjId) - { - const char *ptr; - int val1, val2; - - if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2) - { - SetLastError(CRYPT_E_ASN1_ERROR); - return FALSE; - } - bytesNeeded++; - firstByte = val1 * 40 + val2; - ptr = pszObjId + firstPos; - while (ret && *ptr) - { - int pos; - - /* note I assume each component is at most 32-bits long in base 2 */ - if (sscanf(ptr, "%d%n", &val1, &pos) == 1) - { - if (val1 >= 0x10000000) - bytesNeeded += 5; - else if (val1 >= 0x200000) - bytesNeeded += 4; - else if (val1 >= 0x4000) - bytesNeeded += 3; - else if (val1 >= 0x80) - bytesNeeded += 2; - else - bytesNeeded += 1; - ptr += pos; - if (*ptr == '.') - ptr++; - } - else - { - SetLastError(CRYPT_E_ASN1_ERROR); - return FALSE; - } - } - CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); - } - else - lenBytes = 1; - bytesNeeded += 1 + lenBytes; - if (pbEncoded) - { - if (*pcbEncoded < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - *pbEncoded++ = ASN_OBJECTIDENTIFIER; - CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - if (pszObjId) - { - const char *ptr; - int val, pos; - - *pbEncoded++ = firstByte; - ptr = pszObjId + firstPos; - while (ret && *ptr) - { - sscanf(ptr, "%d%n", &val, &pos); - { - unsigned char outBytes[5]; - int numBytes, i; - - if (val >= 0x10000000) - numBytes = 5; - else if (val >= 0x200000) - numBytes = 4; - else if (val >= 0x4000) - numBytes = 3; - else if (val >= 0x80) - numBytes = 2; - else - numBytes = 1; - for (i = numBytes; i > 0; i--) - { - outBytes[i - 1] = val & 0x7f; - val >>= 7; - } - for (i = 0; i < numBytes - 1; i++) - *pbEncoded++ = outBytes[i] | 0x80; - *pbEncoded++ = outBytes[i]; - ptr += pos; - if (*ptr == '.') - ptr++; - } - } - } - } - } - *pcbEncoded = bytesNeeded; - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType, - CERT_NAME_VALUE *value, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BYTE tag; - DWORD bytesNeeded, lenBytes, encodedLen; - BOOL ret = TRUE; - - switch (value->dwValueType) - { - case CERT_RDN_NUMERIC_STRING: - tag = ASN_NUMERICSTRING; - encodedLen = value->Value.cbData; - break; - case CERT_RDN_PRINTABLE_STRING: - tag = ASN_PRINTABLESTRING; - encodedLen = value->Value.cbData; - break; - case CERT_RDN_IA5_STRING: - tag = ASN_IA5STRING; - encodedLen = value->Value.cbData; - break; - case CERT_RDN_ANY_TYPE: - /* explicitly disallowed */ - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return FALSE; - default: - FIXME("String type %ld unimplemented\n", value->dwValueType); - return FALSE; - } - CRYPT_EncodeLen(encodedLen, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + encodedLen; - if (pbEncoded) - { - if (*pcbEncoded < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - *pbEncoded++ = tag; - CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - switch (value->dwValueType) - { - case CERT_RDN_NUMERIC_STRING: - case CERT_RDN_PRINTABLE_STRING: - case CERT_RDN_IA5_STRING: - memcpy(pbEncoded, value->Value.pbData, value->Value.cbData); - } - } - } - *pcbEncoded = bytesNeeded; - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType, - CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - DWORD bytesNeeded = 0, lenBytes, size; - BOOL ret; - - ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId, - 0, NULL, NULL, &size); - if (ret) - { - bytesNeeded += size; - /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning - * with dwValueType, so "cast" it to get its encoded size - */ - ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType, - (CERT_NAME_VALUE *)&attr->dwValueType, NULL, &size); - if (ret) - { - bytesNeeded += size; - CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); - bytesNeeded += 1 + lenBytes; - if (pbEncoded) - { - if (*pcbEncoded < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SEQUENCE; - CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, - &lenBytes); - pbEncoded += lenBytes; - size = bytesNeeded - 1 - lenBytes; - ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, - attr->pszObjId, 0, NULL, pbEncoded, &size); - if (ret) - { - pbEncoded += size; - size = bytesNeeded - 1 - lenBytes - size; - ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType, - (CERT_NAME_VALUE *)&attr->dwValueType, pbEncoded, - &size); - } - } - } - *pcbEncoded = bytesNeeded; - } - } - return ret; -} - -static int BLOBComp(const void *l, const void *r) -{ - CRYPT_DER_BLOB *a = (CRYPT_DER_BLOB *)l, *b = (CRYPT_DER_BLOB *)r; - int ret; - - if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData)))) - ret = a->cbData - b->cbData; - return ret; -} - -/* This encodes as a SET OF, which in DER must be lexicographically sorted. - */ -static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn, - BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - CRYPT_DER_BLOB *blobs = NULL; - - _SEH_TRY - { - DWORD bytesNeeded = 0, lenBytes, i; - - blobs = NULL; - ret = TRUE; - if (rdn->cRDNAttr) - { - blobs = CryptMemAlloc(rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB)); - if (!blobs) - ret = FALSE; - else - memset(blobs, 0, rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB)); - } - for (i = 0; ret && i < rdn->cRDNAttr; i++) - { - ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i], - NULL, &blobs[i].cbData); - if (ret) - bytesNeeded += blobs[i].cbData; - } - if (ret) - { - CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); - bytesNeeded += 1 + lenBytes; - if (pbEncoded) - { - if (*pcbEncoded < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - for (i = 0; ret && i < rdn->cRDNAttr; i++) - { - blobs[i].pbData = CryptMemAlloc(blobs[i].cbData); - if (!blobs[i].pbData) - ret = FALSE; - else - ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, - &rdn->rgRDNAttr[i], blobs[i].pbData, - &blobs[i].cbData); - } - if (ret) - { - qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB), - BLOBComp); - *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF; - CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, - &lenBytes); - pbEncoded += lenBytes; - for (i = 0; ret && i < rdn->cRDNAttr; i++) - { - memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData); - pbEncoded += blobs[i].cbData; - } - } - } - } - *pcbEncoded = bytesNeeded; - } - if (blobs) - { - for (i = 0; i < rdn->cRDNAttr; i++) - CryptMemFree(blobs[i].pbData); - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - return FALSE; - } - _SEH_END - CryptMemFree(blobs); - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo; - DWORD bytesNeeded = 0, lenBytes, size, i; - - TRACE("encoding name with %ld RDNs\n", info->cRDN); - ret = TRUE; - for (i = 0; ret && i < info->cRDN; i++) - { - ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], NULL, - &size); - if (ret) - bytesNeeded += size; - } - CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes); - bytesNeeded += 1 + lenBytes; - if (ret) - { - if (!pbEncoded) - *pcbEncoded = bytesNeeded; - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, - pbEncoded, pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_SEQUENCEOF; - CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, - &lenBytes); - pbEncoded += lenBytes; - for (i = 0; ret && i < info->cRDN; i++) - { - size = bytesNeeded; - ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, - &info->rgRDN[i], pbEncoded, &size); - if (ret) - { - pbEncoded += size; - bytesNeeded -= size; - } - } - } - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL val = *(const BOOL *)pvStructInfo, ret; - - TRACE("%d\n", val); - - if (!pbEncoded) - { - *pcbEncoded = 3; - ret = TRUE; - } - else if (*pcbEncoded < 3) - { - *pcbEncoded = 3; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - *pcbEncoded = 3; - *pbEncoded++ = ASN_BOOL; - *pbEncoded++ = 1; - *pbEncoded++ = val ? 0xff : 0; - ret = TRUE; - } - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry, - BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - DWORD dataLen; - - ret = TRUE; - switch (entry->dwAltNameChoice) - { - case CERT_ALT_NAME_RFC822_NAME: - case CERT_ALT_NAME_DNS_NAME: - case CERT_ALT_NAME_URL: - if (entry->u.pwszURL) - { - DWORD i; - - /* Not + 1: don't encode the NULL-terminator */ - dataLen = lstrlenW(entry->u.pwszURL); - for (i = 0; ret && i < dataLen; i++) - { - if (entry->u.pwszURL[i] > 0x7f) - { - SetLastError(CRYPT_E_INVALID_IA5_STRING); - ret = FALSE; - *pcbEncoded = i; - } - } - } - else - dataLen = 0; - break; - case CERT_ALT_NAME_IP_ADDRESS: - dataLen = entry->u.IPAddress.cbData; - break; - case CERT_ALT_NAME_REGISTERED_ID: - /* FIXME: encode OID */ - case CERT_ALT_NAME_OTHER_NAME: - case CERT_ALT_NAME_DIRECTORY_NAME: - FIXME("name type %ld unimplemented\n", entry->dwAltNameChoice); - return FALSE; - default: - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - return FALSE; - } - if (ret) - { - DWORD bytesNeeded, lenBytes; - - CRYPT_EncodeLen(dataLen, NULL, &lenBytes); - bytesNeeded = 1 + dataLen + lenBytes; - if (!pbEncoded) - *pcbEncoded = bytesNeeded; - else if (*pcbEncoded < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - *pcbEncoded = bytesNeeded; - ret = FALSE; - } - else - { - *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1); - CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - switch (entry->dwAltNameChoice) - { - case CERT_ALT_NAME_RFC822_NAME: - case CERT_ALT_NAME_DNS_NAME: - case CERT_ALT_NAME_URL: - { - DWORD i; - - for (i = 0; i < dataLen; i++) - *pbEncoded++ = (BYTE)entry->u.pwszURL[i]; - break; - } - case CERT_ALT_NAME_IP_ADDRESS: - memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen); - break; - } - if (ret) - *pcbEncoded = bytesNeeded; - } - } - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CERT_ALT_NAME_INFO *info = - (const CERT_ALT_NAME_INFO *)pvStructInfo; - - DWORD bytesNeeded, dataLen, lenBytes, i; - - ret = TRUE; - /* FIXME: should check that cAltEntry is not bigger than 0xff, since we - * can't encode an erroneous entry index if it's bigger than this. - */ - for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++) - { - DWORD len; - - ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL, - &len); - if (ret) - dataLen += len; - else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING) - { - /* CRYPT_AsnEncodeAltNameEntry encoded the index of - * the bad character, now set the index of the bad - * entry - */ - *pcbEncoded = (BYTE)i << - CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len; - } - } - if (ret) - { - CRYPT_EncodeLen(dataLen, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + dataLen; - if (!pbEncoded) - { - *pcbEncoded = bytesNeeded; - ret = TRUE; - } - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, - pbEncoded, pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_SEQUENCEOF; - CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - for (i = 0; ret && i < info->cAltEntry; i++) - { - DWORD len = dataLen; - - ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], - pbEncoded, &len); - if (ret) - { - pbEncoded += len; - dataLen -= len; - } - } - } - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CERT_BASIC_CONSTRAINTS2_INFO *info = - (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo; - struct AsnEncodeSequenceItem items[2] = { { 0 } }; - DWORD cItem = 0; - - if (info->fCA) - { - items[cItem].pvStructInfo = &info->fCA; - items[cItem].encodeFunc = CRYPT_AsnEncodeBool; - cItem++; - } - if (info->fPathLenConstraint) - { - items[cItem].pvStructInfo = &info->dwPathLenConstraint; - items[cItem].encodeFunc = CRYPT_AsnEncodeInt; - cItem++; - } - ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, - dwFlags, pEncodePara, pbEncoded, pcbEncoded); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const BLOBHEADER *hdr = - (const BLOBHEADER *)pvStructInfo; - - if (hdr->bType != PUBLICKEYBLOB) - { - SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); - ret = FALSE; - } - else - { - const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *) - ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER)); - CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8, - (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) }; - struct AsnEncodeSequenceItem items[] = { - { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 }, - { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 }, - }; - - ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, - pcbEncoded); - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo; - DWORD bytesNeeded, lenBytes; - - TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob->cbData, blob->pbData, - dwFlags, pEncodePara, pbEncoded, *pcbEncoded); - - CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + blob->cbData; - if (!pbEncoded) - { - *pcbEncoded = bytesNeeded; - ret = TRUE; - } - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, - pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_OCTETSTRING; - CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - if (blob->cbData) - memcpy(pbEncoded, blob->pbData, blob->cbData); - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo; - DWORD bytesNeeded, lenBytes, dataBytes; - BYTE unusedBits; - - /* yep, MS allows cUnusedBits to be >= 8 */ - if (!blob->cUnusedBits) - { - dataBytes = blob->cbData; - unusedBits = 0; - } - else if (blob->cbData * 8 > blob->cUnusedBits) - { - dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1; - unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 : - blob->cUnusedBits; - } - else - { - dataBytes = 0; - unusedBits = 0; - } - CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + dataBytes + 1; - if (!pbEncoded) - { - *pcbEncoded = bytesNeeded; - ret = TRUE; - } - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, - pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_BITSTRING; - CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - *pbEncoded++ = unusedBits; - if (dataBytes) - { - BYTE mask = 0xff << unusedBits; - - if (dataBytes > 1) - { - memcpy(pbEncoded, blob->pbData, dataBytes - 1); - pbEncoded += dataBytes - 1; - } - *pbEncoded = *(blob->pbData + dataBytes - 1) & mask; - } - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo; - CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits }; - - ret = TRUE; - if (newBlob.cbData) - { - newBlob.pbData = CryptMemAlloc(newBlob.cbData); - if (newBlob.pbData) - { - DWORD i; - - for (i = 0; i < newBlob.cbData; i++) - newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i]; - } - else - ret = FALSE; - } - if (ret) - ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType, - &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); - CryptMemFree(newBlob.pbData); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo }; - - return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER, - &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); -} - -static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - DWORD significantBytes, lenBytes; - BYTE padByte = 0, bytesNeeded; - BOOL pad = FALSE; - const CRYPT_INTEGER_BLOB *blob = - (const CRYPT_INTEGER_BLOB *)pvStructInfo; - - significantBytes = blob->cbData; - if (significantBytes) - { - if (blob->pbData[significantBytes - 1] & 0x80) - { - /* negative, lop off leading (little-endian) 0xffs */ - for (; significantBytes > 0 && - blob->pbData[significantBytes - 1] == 0xff; significantBytes--) - ; - if (blob->pbData[significantBytes - 1] < 0x80) - { - padByte = 0xff; - pad = TRUE; - } - } - else - { - /* positive, lop off leading (little-endian) zeroes */ - for (; significantBytes > 0 && - !blob->pbData[significantBytes - 1]; significantBytes--) - ; - if (significantBytes == 0) - significantBytes = 1; - if (blob->pbData[significantBytes - 1] > 0x7f) - { - padByte = 0; - pad = TRUE; - } - } - } - if (pad) - CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); - else - CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + significantBytes; - if (pad) - bytesNeeded++; - if (!pbEncoded) - { - *pcbEncoded = bytesNeeded; - ret = TRUE; - } - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, - pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_INTEGER; - if (pad) - { - CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - *pbEncoded++ = padByte; - } - else - { - CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - } - for (; significantBytes > 0; significantBytes--) - *(pbEncoded++) = blob->pbData[significantBytes - 1]; - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - DWORD significantBytes, lenBytes; - BYTE bytesNeeded; - BOOL pad = FALSE; - const CRYPT_INTEGER_BLOB *blob = - (const CRYPT_INTEGER_BLOB *)pvStructInfo; - - significantBytes = blob->cbData; - if (significantBytes) - { - /* positive, lop off leading (little-endian) zeroes */ - for (; significantBytes > 0 && !blob->pbData[significantBytes - 1]; - significantBytes--) - ; - if (significantBytes == 0) - significantBytes = 1; - if (blob->pbData[significantBytes - 1] > 0x7f) - pad = TRUE; - } - if (pad) - CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); - else - CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + significantBytes; - if (pad) - bytesNeeded++; - if (!pbEncoded) - { - *pcbEncoded = bytesNeeded; - ret = TRUE; - } - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, - pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_INTEGER; - if (pad) - { - CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - *pbEncoded++ = 0; - } - else - { - CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - } - for (; significantBytes > 0; significantBytes--) - *(pbEncoded++) = blob->pbData[significantBytes - 1]; - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - CRYPT_INTEGER_BLOB blob; - BOOL ret; - - /* Encode as an unsigned integer, then change the tag to enumerated */ - blob.cbData = sizeof(DWORD); - blob.pbData = (BYTE *)pvStructInfo; - ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType, - X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded); - if (ret && pbEncoded) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - pbEncoded[0] = ASN_ENUMERATED; - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - SYSTEMTIME sysTime; - /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a - * temporary buffer because the output buffer is not NULL-terminated. - */ - char buf[16]; - static const DWORD bytesNeeded = sizeof(buf) - 1; - - if (!pbEncoded) - { - *pcbEncoded = bytesNeeded; - ret = TRUE; - } - else - { - /* Sanity check the year, this is a two-digit year format */ - ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo, - &sysTime); - if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050)) - { - SetLastError(CRYPT_E_BAD_ENCODE); - ret = FALSE; - } - if (ret) - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, - pbEncoded, pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - buf[0] = ASN_UTCTIME; - buf[1] = bytesNeeded - 2; - snprintf(buf + 2, sizeof(buf) - 2, - "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ? - sysTime.wYear - 2000 : sysTime.wYear - 1900, - sysTime.wDay, sysTime.wMonth, sysTime.wHour, - sysTime.wMinute, sysTime.wSecond); - memcpy(pbEncoded, buf, bytesNeeded); - } - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - SYSTEMTIME sysTime; - /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a - * temporary buffer because the output buffer is not NULL-terminated. - */ - char buf[18]; - static const DWORD bytesNeeded = sizeof(buf) - 1; - - if (!pbEncoded) - { - *pcbEncoded = bytesNeeded; - ret = TRUE; - } - else - { - ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo, - &sysTime); - if (ret) - ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, - pcbEncoded, bytesNeeded); - if (ret) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - buf[0] = ASN_GENERALTIME; - buf[1] = bytesNeeded - 2; - snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ", - sysTime.wYear, sysTime.wDay, sysTime.wMonth, sysTime.wHour, - sysTime.wMinute, sysTime.wSecond); - memcpy(pbEncoded, buf, bytesNeeded); - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - SYSTEMTIME sysTime; - - /* Check the year, if it's in the UTCTime range call that encode func */ - if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime)) - return FALSE; - if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050) - ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType, - pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded); - else - ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType, - lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded, - pcbEncoded); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, - PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) -{ - BOOL ret; - - _SEH_TRY - { - DWORD bytesNeeded, dataLen, lenBytes, i; - const CRYPT_SEQUENCE_OF_ANY *seq = - (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo; - - for (i = 0, dataLen = 0; i < seq->cValue; i++) - dataLen += seq->rgValue[i].cbData; - CRYPT_EncodeLen(dataLen, NULL, &lenBytes); - bytesNeeded = 1 + lenBytes + dataLen; - if (!pbEncoded) - { - *pcbEncoded = bytesNeeded; - ret = TRUE; - } - else - { - if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, - pcbEncoded, bytesNeeded))) - { - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) - pbEncoded = *(BYTE **)pbEncoded; - *pbEncoded++ = ASN_SEQUENCEOF; - CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes); - pbEncoded += lenBytes; - for (i = 0; i < seq->cValue; i++) - { - memcpy(pbEncoded, seq->rgValue[i].pbData, - seq->rgValue[i].cbData); - pbEncoded += seq->rgValue[i].cbData; - } - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, - const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, - void *pvEncoded, DWORD *pcbEncoded) -{ - BOOL ret = FALSE; - HMODULE lib = NULL; - CryptEncodeObjectExFunc encodeFunc = NULL; - - TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType, - debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara, - pvEncoded, pcbEncoded); - - if (!pvEncoded && !pcbEncoded) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING - && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING) - { - SetLastError(ERROR_FILE_NOT_FOUND); - return FALSE; - } - - SetLastError(NOERROR); - if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded) - *(BYTE **)pvEncoded = NULL; - if (!HIWORD(lpszStructType)) - { - switch (LOWORD(lpszStructType)) - { - case (WORD)X509_CERT: - encodeFunc = CRYPT_AsnEncodeCert; - break; - case (WORD)X509_CERT_TO_BE_SIGNED: - encodeFunc = CRYPT_AsnEncodeCertInfo; - break; - case (WORD)X509_CERT_CRL_TO_BE_SIGNED: - encodeFunc = CRYPT_AsnEncodeCRLInfo; - break; - case (WORD)X509_EXTENSIONS: - encodeFunc = CRYPT_AsnEncodeExtensions; - break; - case (WORD)X509_NAME: - encodeFunc = CRYPT_AsnEncodeName; - break; - case (WORD)X509_PUBLIC_KEY_INFO: - encodeFunc = CRYPT_AsnEncodePubKeyInfo; - break; - case (WORD)X509_ALTERNATE_NAME: - encodeFunc = CRYPT_AsnEncodeAltName; - break; - case (WORD)X509_BASIC_CONSTRAINTS2: - encodeFunc = CRYPT_AsnEncodeBasicConstraints2; - break; - case (WORD)RSA_CSP_PUBLICKEYBLOB: - encodeFunc = CRYPT_AsnEncodeRsaPubKey; - break; - case (WORD)X509_OCTET_STRING: - encodeFunc = CRYPT_AsnEncodeOctets; - break; - case (WORD)X509_BITS: - case (WORD)X509_KEY_USAGE: - encodeFunc = CRYPT_AsnEncodeBits; - break; - case (WORD)X509_INTEGER: - encodeFunc = CRYPT_AsnEncodeInt; - break; - case (WORD)X509_MULTI_BYTE_INTEGER: - encodeFunc = CRYPT_AsnEncodeInteger; - break; - case (WORD)X509_MULTI_BYTE_UINT: - encodeFunc = CRYPT_AsnEncodeUnsignedInteger; - break; - case (WORD)X509_ENUMERATED: - encodeFunc = CRYPT_AsnEncodeEnumerated; - break; - case (WORD)X509_CHOICE_OF_TIME: - encodeFunc = CRYPT_AsnEncodeChoiceOfTime; - break; - case (WORD)X509_SEQUENCE_OF_ANY: - encodeFunc = CRYPT_AsnEncodeSequenceOfAny; - break; - case (WORD)PKCS_UTC_TIME: - encodeFunc = CRYPT_AsnEncodeUtcTime; - break; - default: - FIXME("%d: unimplemented\n", LOWORD(lpszStructType)); - } - } - else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS)) - encodeFunc = CRYPT_AsnEncodeExtensions; - else if (!strcmp(lpszStructType, szOID_RSA_signingTime)) - encodeFunc = CRYPT_AsnEncodeUtcTime; - else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE)) - encodeFunc = CRYPT_AsnEncodeEnumerated; - else if (!strcmp(lpszStructType, szOID_KEY_USAGE)) - encodeFunc = CRYPT_AsnEncodeBits; - else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER)) - encodeFunc = CRYPT_AsnEncodeOctets; - else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2)) - encodeFunc = CRYPT_AsnEncodeBasicConstraints2; - else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME)) - encodeFunc = CRYPT_AsnEncodeAltName; - else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2)) - encodeFunc = CRYPT_AsnEncodeAltName; - else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION)) - encodeFunc = CRYPT_AsnEncodeAltName; - else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME)) - encodeFunc = CRYPT_AsnEncodeAltName; - else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2)) - encodeFunc = CRYPT_AsnEncodeAltName; - else - TRACE("OID %s not found or unimplemented, looking for DLL\n", - debugstr_a(lpszStructType)); - if (!encodeFunc) - encodeFunc = (CryptEncodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType, - lpszStructType, CRYPT_OID_ENCODE_OBJECT_EX_FUNC, &lib); - if (encodeFunc) - ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo, - dwFlags, pEncodePara, pvEncoded, pcbEncoded); - else - SetLastError(ERROR_FILE_NOT_FOUND); - if (lib) - FreeLibrary(lib); - return ret; -} - -BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType, - const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, - DWORD *pcbStructInfo) -{ - BOOL ret = FALSE; - HMODULE lib; - CryptDecodeObjectFunc pCryptDecodeObject; - - TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType, - debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags, - pvStructInfo, pcbStructInfo); - - if (!pvStructInfo && !pcbStructInfo) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* Try registered DLL first.. */ - pCryptDecodeObject = - (CryptDecodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType, - lpszStructType, CRYPT_OID_DECODE_OBJECT_FUNC, &lib); - if (pCryptDecodeObject) - { - ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType, - pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo); - FreeLibrary(lib); - } - else - { - /* If not, use CryptDecodeObjectEx */ - ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded, - cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo); - } - return ret; -} - -/* Gets the number of length bytes from the given (leading) length byte */ -#define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f)) - -/* Helper function to get the encoded length of the data starting at pbEncoded, - * where pbEncoded[0] is the tag. If the data are too short to contain a - * length or if the length is too large for cbEncoded, sets an appropriate - * error code and returns FALSE. - */ -static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, - DWORD *len) -{ - BOOL ret; - - if (cbEncoded <= 1) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - else if (pbEncoded[1] <= 0x7f) - { - if (pbEncoded[1] + 1 > cbEncoded) - { - SetLastError(CRYPT_E_ASN1_EOD); - ret = FALSE; - } - else - { - *len = pbEncoded[1]; - ret = TRUE; - } - } - else - { - BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]); - - if (lenLen > sizeof(DWORD) + 1) - { - SetLastError(CRYPT_E_ASN1_LARGE); - ret = FALSE; - } - else if (lenLen + 2 > cbEncoded) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - else - { - DWORD out = 0; - - pbEncoded += 2; - while (--lenLen) - { - out <<= 8; - out |= *pbEncoded++; - } - if (out + lenLen + 1 > cbEncoded) - { - SetLastError(CRYPT_E_ASN1_EOD); - ret = FALSE; - } - else - { - *len = out; - ret = TRUE; - } - } - } - return ret; -} - -/* Helper function to check *pcbStructInfo, set it to the required size, and - * optionally to allocate memory. Assumes pvStructInfo is not NULL. - * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a - * pointer to the newly allocated memory. - */ -static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo, - DWORD bytesNeeded) -{ - BOOL ret = TRUE; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - { - if (pDecodePara && pDecodePara->pfnAlloc) - *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded); - else - *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded); - if (!*(BYTE **)pvStructInfo) - ret = FALSE; - else - *pcbStructInfo = bytesNeeded; - } - else if (*pcbStructInfo < bytesNeeded) - { - *pcbStructInfo = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - return ret; -} - -/* A few of the members need explanation: - * offset: - * A sequence is decoded into a struct. The offset member is the - * offset of this item within that struct. - * decodeFunc: - * The decoder function to use. If this is NULL, then the member isn't - * decoded, but minSize space is reserved for it. - * minSize: - * The minimum amount of space occupied after decoding. You must set this. - * optional: - * If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then - * minSize space is filled with 0 for this member. (Any other failure - * results in CRYPT_AsnDecodeSequence failing.) - * hasPointer, pointerOffset, minSize: - * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to - * the offset within the (outer) struct of the data pointer (or to the - * first data pointer, if more than one exist). - * size: - * Used by CRYPT_AsnDecodeSequence, not for your use. - */ -struct AsnDecodeSequenceItem -{ - DWORD offset; - CryptDecodeObjectExFunc decodeFunc; - DWORD minSize; - BOOL optional; - BOOL hasPointer; - DWORD pointerOffset; - DWORD size; -}; - -/* This decodes an arbitrary sequence into a contiguous block of memory - * (basically, a struct.) Each element being decoded is described by a struct - * AsnDecodeSequenceItem, see above. - * startingPointer is an optional pointer to the first place where dynamic - * data will be stored. If you know the starting offset, you may pass it - * here. Otherwise, pass NULL, and one will be inferred from the items. - * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set. - * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT. - */ -static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType, - struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded, - DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, - void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer) -{ - BOOL ret; - - TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded, - cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo, - startingPointer); - - if (pbEncoded[0] == ASN_SEQUENCE) - { - DWORD dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - DWORD i, bytesNeeded = 0, minSize = 0; - const BYTE *ptr; - - ptr = pbEncoded + 1 + lenBytes; - for (i = 0; ret && i < cItem; i++) - { - DWORD nextItemLen; - - minSize += items[i].minSize; - if (cbEncoded - (ptr - pbEncoded) != 0) - { - if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded), - &nextItemLen))) - { - BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]); - - if (items[i].decodeFunc) - { - TRACE("sizing item %ld\n", i); - ret = items[i].decodeFunc(dwCertEncodingType, NULL, - ptr, 1 + nextItemLenBytes + nextItemLen, - dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, - &items[i].size); - if (ret) - { - /* Account for alignment padding */ - bytesNeeded += items[i].size; - if (items[i].size % sizeof(DWORD)) - bytesNeeded += sizeof(DWORD) - - items[i].size % sizeof(DWORD); - ptr += 1 + nextItemLenBytes + nextItemLen; - } - else if (items[i].optional && - GetLastError() == CRYPT_E_ASN1_BADTAG) - { - TRACE("skipping optional item %ld\n", i); - bytesNeeded += items[i].minSize; - SetLastError(NOERROR); - ret = TRUE; - } - else - TRACE("item %ld failed: %08lx\n", i, - GetLastError()); - } - else - bytesNeeded += items[i].minSize; - } - } - else if (items[i].optional) - bytesNeeded += items[i].minSize; - else - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - } - if (cbEncoded - (ptr - pbEncoded) != 0) - { - TRACE("%ld remaining bytes, failing\n", cbEncoded - - (ptr - pbEncoded)); - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - if (ret) - { - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) - { - BYTE *nextData; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - if (startingPointer) - nextData = (BYTE *)startingPointer; - else - nextData = (BYTE *)pvStructInfo + minSize; - memset(pvStructInfo, 0, minSize); - ptr = pbEncoded + 1 + lenBytes; - for (i = 0; ret && i < cItem; i++) - { - if (cbEncoded - (ptr - pbEncoded) != 0) - { - DWORD nextItemLen; - BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]); - - CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded), - &nextItemLen); - if (items[i].hasPointer) - { - *(BYTE **)((BYTE *)pvStructInfo + - items[i].pointerOffset) = nextData; - } - if (items[i].decodeFunc) - { - TRACE("decoding item %ld\n", i); - ret = items[i].decodeFunc(dwCertEncodingType, - NULL, ptr, 1 + nextItemLenBytes + nextItemLen, - dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, - (BYTE *)pvStructInfo + items[i].offset, - &items[i].size); - if (!ret) - TRACE("item %ld failed: %08lx\n", i, - GetLastError()); - } - else - items[i].size = items[i].minSize; - if (ret) - { - if (items[i].hasPointer && - items[i].size > items[i].minSize) - { - nextData += items[i].size - - items[i].minSize; - /* align nextData to DWORD boundaries */ - if (items[i].size % sizeof(DWORD)) - { - nextData += sizeof(DWORD) - - items[i].size % sizeof(DWORD); - } - } - ptr += 1 + nextItemLenBytes + nextItemLen; - } - else if (items[i].optional && - GetLastError() == CRYPT_E_ASN1_BADTAG) - { - SetLastError(NOERROR); - ret = TRUE; - } - } - else if (!items[i].optional) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -/* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by - * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set - * to CRYPT_E_ASN1_CORRUPT. - * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData - * set! - */ -static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - DWORD dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB); - - if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) - bytesNeeded += 1 + lenBytes + dataLen; - - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo, bytesNeeded))) - { - CRYPT_DER_BLOB *blob = (CRYPT_DER_BLOB *)pvStructInfo; - - blob->cbData = 1 + lenBytes + dataLen; - if (blob->cbData) - { - if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) - blob->pbData = (BYTE *)pbEncoded; - else - { - assert(blob->pbData); - memcpy(blob->pbData, pbEncoded, blob->cbData); - } - } - else - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - } - } - return ret; -} - -/* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */ -static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in- - * place. - */ - ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType, - pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara, - pvStructInfo, pcbStructInfo); - if (ret && pvStructInfo) - { - CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo; - - if (blob->cbData) - { - DWORD i; - BYTE temp; - - for (i = 0; i < blob->cbData / 2; i++) - { - temp = blob->pbData[i]; - blob->pbData[i] = blob->pbData[blob->cbData - i - 1]; - blob->pbData[blob->cbData - i - 1] = temp; - } - } - } - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - _SEH_TRY - { - struct AsnDecodeSequenceItem items[] = { - { offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned), - CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, - offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 }, - { offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm), - CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), - FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO, - SignatureAlgorithm.pszObjId), 0 }, - { offsetof(CERT_SIGNED_CONTENT_INFO, Signature), - CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, - offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 }, - }; - - if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG) - items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal; - ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, NULL); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR)) - { - DWORD dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER, - pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo); - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - struct AsnDecodeSequenceItem items[] = { - { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore), - CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 }, - { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter), - CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 }, - }; - - ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, NULL); - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 3)) - { - DWORD dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType, - X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo); - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - _SEH_TRY - { - struct AsnDecodeSequenceItem items[] = { - { offsetof(CERT_INFO, dwVersion), CRYPT_AsnDecodeCertVersion, - sizeof(DWORD), TRUE, FALSE, 0, 0 }, - { offsetof(CERT_INFO, SerialNumber), CRYPT_AsnDecodeIntegerInternal, - sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, - SerialNumber.pbData), 0 }, - { offsetof(CERT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId, - sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_INFO, - SignatureAlgorithm.pszObjId), 0 }, - { offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob, - sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, - Issuer.pbData) }, - { offsetof(CERT_INFO, NotBefore), CRYPT_AsnDecodeValidity, - sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE, FALSE, 0 }, - { offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob, - sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, - Subject.pbData) }, - { offsetof(CERT_INFO, SubjectPublicKeyInfo), CRYPT_AsnDecodePubKeyInfo, - sizeof(CERT_PUBLIC_KEY_INFO), FALSE, TRUE, offsetof(CERT_INFO, - SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 }, - { offsetof(CERT_INFO, IssuerUniqueId), CRYPT_AsnDecodeBitsInternal, - sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO, - IssuerUniqueId.pbData), 0 }, - { offsetof(CERT_INFO, SubjectUniqueId), CRYPT_AsnDecodeBitsInternal, - sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO, - SubjectUniqueId.pbData), 0 }, - { offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeCertExtensions, - sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CERT_INFO, - rgExtension), 0 }, - }; - - ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, NULL); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded, - DWORD dwFlags, PCRL_ENTRY entry, DWORD *pcbEntry) -{ - BOOL ret; - struct AsnDecodeSequenceItem items[] = { - { offsetof(CRL_ENTRY, SerialNumber), CRYPT_AsnDecodeIntegerInternal, - sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CRL_ENTRY, - SerialNumber.pbData), 0 }, - { offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime, - sizeof(FILETIME), FALSE, FALSE, 0 }, - { offsetof(CRL_ENTRY, cExtension), CRYPT_AsnDecodeExtensionsInternal, - sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CRL_ENTRY, - rgExtension), 0 }, - }; - - TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry, - *pcbEntry); - - ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, - NULL, entry, pcbEntry, entry ? entry->SerialNumber.pbData : NULL); - TRACE("Returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -typedef struct _WINE_CRL_ENTRIES { - DWORD cCRLEntry; - PCRL_ENTRY rgCRLEntry; -} WINE_CRL_ENTRIES, *PWINE_CRL_ENTRIES; - -/* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has - * been set prior to calling. - */ -static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - if (pbEncoded[0] == ASN_SEQUENCEOF) - { - DWORD dataLen, bytesNeeded; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - DWORD cCRLEntry = 0; - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - bytesNeeded = sizeof(WINE_CRL_ENTRIES); - if (dataLen) - { - const BYTE *ptr; - DWORD size; - - for (ptr = pbEncoded + 1 + lenBytes; ret && - ptr - pbEncoded - 1 - lenBytes < dataLen; ) - { - size = 0; - ret = CRYPT_AsnDecodeCRLEntry(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size); - if (ret) - { - DWORD nextLen; - - cCRLEntry++; - bytesNeeded += size; - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); - } - } - } - if (ret) - { - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) - { - DWORD size, i; - BYTE *nextData; - const BYTE *ptr; - PWINE_CRL_ENTRIES entries; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - *pcbStructInfo = bytesNeeded; - entries = (PWINE_CRL_ENTRIES)pvStructInfo; - entries->cCRLEntry = cCRLEntry; - assert(entries->rgCRLEntry); - nextData = (BYTE *)entries->rgCRLEntry + - entries->cCRLEntry * sizeof(CRL_ENTRY); - for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret && - i < cCRLEntry && ptr - pbEncoded - 1 - lenBytes < - dataLen; i++) - { - entries->rgCRLEntry[i].SerialNumber.pbData = nextData; - size = bytesNeeded; - ret = CRYPT_AsnDecodeCRLEntry(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, - &entries->rgCRLEntry[i], &size); - if (ret) - { - DWORD nextLen; - - bytesNeeded -= size; - /* Increment nextData by the difference of the - * minimum size and the actual size. - */ - if (size > sizeof(CRL_ENTRY)) - nextData += size - sizeof(CRL_ENTRY); - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); - } - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - TRACE("Returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - _SEH_TRY - { - struct AsnDecodeSequenceItem items[] = { - { offsetof(CRL_INFO, dwVersion), CRYPT_AsnDecodeCertVersion, - sizeof(DWORD), TRUE, FALSE, 0, 0 }, - { offsetof(CRL_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId, - sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRL_INFO, - SignatureAlgorithm.pszObjId), 0 }, - { offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob, - sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO, - Issuer.pbData) }, - { offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime, - sizeof(FILETIME), FALSE, FALSE, 0 }, - { offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime, - sizeof(FILETIME), TRUE, FALSE, 0 }, - { offsetof(CRL_INFO, cCRLEntry), CRYPT_AsnDecodeCRLEntries, - sizeof(WINE_CRL_ENTRIES), TRUE, TRUE, offsetof(CRL_INFO, - rgCRLEntry), 0 }, - /* Note that the extensions are ignored by MS, so I'll ignore them too - */ - { offsetof(CRL_INFO, cExtension), NULL, - sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 }, - }; - - ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, NULL); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - - TRACE("Returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -/* Differences between this and CRYPT_AsnDecodeOid: - * - pvStructInfo is a LPSTR *, not an LPSTR - * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte - * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this - * to - */ -static BOOL WINAPI CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - ret = CRYPT_AsnDecodeOid(pbEncoded, cbEncoded, dwFlags, - pvStructInfo ? *(LPSTR *)pvStructInfo : NULL, pcbStructInfo); - if (ret || GetLastError() == ERROR_MORE_DATA) - *pcbStructInfo += sizeof(LPSTR); - if (ret && pvStructInfo) - TRACE("returning %s\n", debugstr_a(*(LPSTR *)pvStructInfo)); - return ret; -} - -/* Warning: assumes ext->pszObjId is set ahead of time! */ -static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded, - DWORD dwFlags, CERT_EXTENSION *ext, DWORD *pcbExt) -{ - struct AsnDecodeSequenceItem items[] = { - { offsetof(CERT_EXTENSION, pszObjId), CRYPT_AsnDecodeOidWrapper, - sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_EXTENSION, pszObjId), 0 }, - { offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool, - sizeof(BOOL), TRUE, FALSE, 0, 0 }, - { offsetof(CERT_EXTENSION, Value), CRYPT_AsnDecodeOctetsInternal, - sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, offsetof(CERT_EXTENSION, - Value.pbData) }, - }; - BOOL ret = TRUE; - - TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext, - *pcbExt); - - if (ext) - TRACE("ext->pszObjId is %p\n", ext->pszObjId); - ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL, - ext, pcbExt, ext ? ext->pszObjId : NULL); - if (ext) - TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId, - debugstr_a(ext->pszObjId)); - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - if (pbEncoded[0] == ASN_SEQUENCEOF) - { - DWORD dataLen, bytesNeeded; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - DWORD cExtension = 0; - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - bytesNeeded = sizeof(CERT_EXTENSIONS); - if (dataLen) - { - const BYTE *ptr; - DWORD size; - - for (ptr = pbEncoded + 1 + lenBytes; ret && - ptr - pbEncoded - 1 - lenBytes < dataLen; ) - { - size = 0; - ret = CRYPT_AsnDecodeExtension(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size); - if (ret) - { - DWORD nextLen; - - cExtension++; - bytesNeeded += size; - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); - } - } - } - if (ret) - { - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if (*pcbStructInfo < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - *pcbStructInfo = bytesNeeded; - ret = FALSE; - } - else - { - DWORD size, i; - BYTE *nextData; - const BYTE *ptr; - CERT_EXTENSIONS *exts; - - *pcbStructInfo = bytesNeeded; - exts = (CERT_EXTENSIONS *)pvStructInfo; - exts->cExtension = cExtension; - assert(exts->rgExtension); - nextData = (BYTE *)exts->rgExtension + - exts->cExtension * sizeof(CERT_EXTENSION); - for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret && - i < cExtension && ptr - pbEncoded - 1 - lenBytes < - dataLen; i++) - { - exts->rgExtension[i].pszObjId = (LPSTR)nextData; - size = bytesNeeded; - ret = CRYPT_AsnDecodeExtension(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, - &exts->rgExtension[i], &size); - if (ret) - { - DWORD nextLen; - - bytesNeeded -= size; - if (size > sizeof(CERT_EXTENSION)) - nextData += size - sizeof(CERT_EXTENSION); - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); - } - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - _SEH_TRY - { - ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo); - if (ret && pvStructInfo) - { - ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, - pcbStructInfo, *pcbStructInfo); - if (ret) - { - CERT_EXTENSIONS *exts; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - exts = (CERT_EXTENSIONS *)pvStructInfo; - exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts + - sizeof(CERT_EXTENSIONS)); - ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo, - pcbStructInfo); - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -/* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */ -static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded, - DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId) -{ - BOOL ret = TRUE; - - TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, pszObjId, - *pcbObjId); - - _SEH_TRY - { - if (pbEncoded[0] == ASN_OBJECTIDENTIFIER) - { - DWORD dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - DWORD bytesNeeded; - - if (dataLen) - { - /* The largest possible string for the first two components - * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough. - */ - char firstTwo[6]; - const BYTE *ptr; - - snprintf(firstTwo, sizeof(firstTwo), "%d.%d", - pbEncoded[1 + lenBytes] / 40, - pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40) - * 40); - bytesNeeded = strlen(firstTwo) + 1; - for (ptr = pbEncoded + 2 + lenBytes; ret && - ptr - pbEncoded - 1 - lenBytes < dataLen; ) - { - /* large enough for ".4000000" */ - char str[9]; - int val = 0; - - while (ptr - pbEncoded - 1 - lenBytes < dataLen && - (*ptr & 0x80)) - { - val <<= 7; - val |= *ptr & 0x7f; - ptr++; - } - if (ptr - pbEncoded - 1 - lenBytes >= dataLen || - (*ptr & 0x80)) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - else - { - val <<= 7; - val |= *ptr++; - snprintf(str, sizeof(str), ".%d", val); - bytesNeeded += strlen(str); - } - } - if (!pszObjId) - *pcbObjId = bytesNeeded; - else if (*pcbObjId < bytesNeeded) - { - *pcbObjId = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - *pszObjId = 0; - sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40, - pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / - 40) * 40); - pszObjId += strlen(pszObjId); - for (ptr = pbEncoded + 2 + lenBytes; ret && - ptr - pbEncoded - 1 - lenBytes < dataLen; ) - { - int val = 0; - - while (ptr - pbEncoded - 1 - lenBytes < dataLen && - (*ptr & 0x80)) - { - val <<= 7; - val |= *ptr & 0x7f; - ptr++; - } - val <<= 7; - val |= *ptr++; - sprintf(pszObjId, ".%d", val); - pszObjId += strlen(pszObjId); - } - } - } - else - bytesNeeded = 0; - *pcbObjId = bytesNeeded; - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -/* Warning: this assumes the address of value->Value.pbData is already set, in - * order to avoid overwriting memory. (In some cases, it may change it, if it - * doesn't copy anything to memory.) Be sure to set it correctly! - */ -static BOOL WINAPI CRYPT_AsnDecodeNameValue(const BYTE *pbEncoded, - DWORD cbEncoded, DWORD dwFlags, CERT_NAME_VALUE *value, DWORD *pcbValue) -{ - BOOL ret = TRUE; - - _SEH_TRY - { - DWORD dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - switch (pbEncoded[0]) - { - case ASN_NUMERICSTRING: - case ASN_PRINTABLESTRING: - case ASN_IA5STRING: - break; - default: - FIXME("Unimplemented string type %02x\n", pbEncoded[0]); - SetLastError(OSS_UNIMPLEMENTED); - ret = FALSE; - } - if (ret) - { - DWORD bytesNeeded = sizeof(CERT_NAME_VALUE); - - switch (pbEncoded[0]) - { - case ASN_NUMERICSTRING: - case ASN_PRINTABLESTRING: - case ASN_IA5STRING: - if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) - bytesNeeded += dataLen; - break; - } - if (!value) - *pcbValue = bytesNeeded; - else if (*pcbValue < bytesNeeded) - { - *pcbValue = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - *pcbValue = bytesNeeded; - switch (pbEncoded[0]) - { - case ASN_NUMERICSTRING: - value->dwValueType = CERT_RDN_NUMERIC_STRING; - break; - case ASN_PRINTABLESTRING: - value->dwValueType = CERT_RDN_PRINTABLE_STRING; - break; - case ASN_IA5STRING: - value->dwValueType = CERT_RDN_IA5_STRING; - break; - } - if (dataLen) - { - switch (pbEncoded[0]) - { - case ASN_NUMERICSTRING: - case ASN_PRINTABLESTRING: - case ASN_IA5STRING: - value->Value.cbData = dataLen; - if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) - value->Value.pbData = (BYTE *)pbEncoded + 1 + - lenBytes; - else - { - assert(value->Value.pbData); - memcpy(value->Value.pbData, - pbEncoded + 1 + lenBytes, dataLen); - } - break; - } - } - else - { - value->Value.cbData = 0; - value->Value.pbData = NULL; - } - } - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -/* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it - * at the moment because of the ASN_CONSTRUCTOR tag.) - */ -static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, - DWORD cbEncoded, DWORD dwFlags, CERT_RDN_ATTR *attr, DWORD *pcbAttr) -{ - BOOL ret; - - _SEH_TRY - { - if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCE)) - { - DWORD bytesNeeded, dataLen, size; - BYTE lenBytes; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - /* The data length must be at least 4, two for the tag and - * length for the OID, and two for the string (assuming both - * have short-form lengths.) - */ - if (dataLen < 4) - { - SetLastError(CRYPT_E_ASN1_EOD); - ret = FALSE; - } - else - { - bytesNeeded = sizeof(CERT_RDN_ATTR); - lenBytes = GET_LEN_BYTES(pbEncoded[1]); - ret = CRYPT_AsnDecodeOid(pbEncoded + 1 + lenBytes, - cbEncoded - 1 - lenBytes, dwFlags, NULL, &size); - if (ret) - { - /* ugly: need to know the size of the next element of - * the sequence, so get it directly - */ - DWORD objIdOfset = 1 + lenBytes, objIdLen, - nameValueOffset = 0; - - ret = CRYPT_GetLen(pbEncoded + objIdOfset, - cbEncoded - objIdOfset, &objIdLen); - bytesNeeded += size; - /* hack: like encoding, this takes advantage of the - * fact that the rest of the structure is identical to - * a CERT_NAME_VALUE. - */ - if (ret) - { - nameValueOffset = objIdOfset + objIdLen + 1 + - GET_LEN_BYTES(pbEncoded[objIdOfset]); - ret = CRYPT_AsnDecodeNameValue( - pbEncoded + nameValueOffset, - cbEncoded - nameValueOffset, dwFlags, NULL, &size); - } - if (ret) - { - bytesNeeded += size; - if (!attr) - *pcbAttr = bytesNeeded; - else if (*pcbAttr < bytesNeeded) - { - *pcbAttr = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - BYTE *originalData = attr->Value.pbData; - - *pcbAttr = bytesNeeded; - /* strange: decode the value first, because it - * has a counted size, and we can store the OID - * after it. Keep track of the original data - * pointer, we'll need to know whether it was - * changed. - */ - size = bytesNeeded; - ret = CRYPT_AsnDecodeNameValue( - pbEncoded + nameValueOffset, - cbEncoded - nameValueOffset, dwFlags, - (CERT_NAME_VALUE *)&attr->dwValueType, &size); - if (ret) - { - if (objIdLen) - { - /* if the data were copied to the - * original location, the OID goes - * after. Otherwise it goes in the - * spot originally reserved for the - * data. - */ - if (attr->Value.pbData == originalData) - attr->pszObjId = - (LPSTR)(attr->Value.pbData + - attr->Value.cbData); - else - attr->pszObjId = - (LPSTR)originalData; - size = bytesNeeded - size; - ret = CRYPT_AsnDecodeOid( - pbEncoded + objIdOfset, - cbEncoded - objIdOfset, - dwFlags, attr->pszObjId, &size); - } - else - attr->pszObjId = NULL; - } - } - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded, - DWORD dwFlags, CERT_RDN *rdn, DWORD *pcbRdn) -{ - BOOL ret = TRUE; - - _SEH_TRY - { - if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SETOF)) - { - DWORD dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - DWORD bytesNeeded, cRDNAttr = 0; - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - bytesNeeded = sizeof(CERT_RDN); - if (dataLen) - { - const BYTE *ptr; - DWORD size; - - for (ptr = pbEncoded + 1 + lenBytes; ret && - ptr - pbEncoded - 1 - lenBytes < dataLen; ) - { - ret = CRYPT_AsnDecodeRdnAttr(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size); - if (ret) - { - DWORD nextLen; - - cRDNAttr++; - bytesNeeded += size; - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); - } - } - } - if (ret) - { - if (!rdn) - *pcbRdn = bytesNeeded; - else if (*pcbRdn < bytesNeeded) - { - *pcbRdn = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - DWORD size, i; - BYTE *nextData; - const BYTE *ptr; - - *pcbRdn = bytesNeeded; - rdn->cRDNAttr = cRDNAttr; - rdn->rgRDNAttr = (CERT_RDN_ATTR *)((BYTE *)rdn + - sizeof(CERT_RDN)); - nextData = (BYTE *)rdn->rgRDNAttr + - rdn->cRDNAttr * sizeof(CERT_RDN_ATTR); - for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret && - i < cRDNAttr && ptr - pbEncoded - 1 - lenBytes < - dataLen; i++) - { - rdn->rgRDNAttr[i].Value.pbData = nextData; - size = bytesNeeded; - ret = CRYPT_AsnDecodeRdnAttr(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, - &rdn->rgRDNAttr[i], &size); - if (ret) - { - DWORD nextLen; - - bytesNeeded -= size; - /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the - * data may not have been copied. - */ - if (rdn->rgRDNAttr[i].Value.pbData == nextData) - nextData += - rdn->rgRDNAttr[i].Value.cbData; - /* Ugly: the OID, if copied, is stored in - * memory after the value, so increment by its - * string length if it's set and points here. - */ - if ((const BYTE *)rdn->rgRDNAttr[i].pszObjId - == nextData) - nextData += strlen( - rdn->rgRDNAttr[i].pszObjId) + 1; - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); - } - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - _SEH_TRY - { - if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCEOF)) - { - DWORD dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - DWORD bytesNeeded, cRDN = 0; - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - bytesNeeded = sizeof(CERT_NAME_INFO); - if (dataLen) - { - const BYTE *ptr; - - for (ptr = pbEncoded + 1 + lenBytes; ret && - ptr - pbEncoded - 1 - lenBytes < dataLen; ) - { - DWORD size; - - ret = CRYPT_AsnDecodeRdn(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size); - if (ret) - { - DWORD nextLen; - - cRDN++; - bytesNeeded += size; - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); - } - } - } - if (ret) - { - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) - { - CERT_NAME_INFO *info; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - info = (CERT_NAME_INFO *)pvStructInfo; - info->cRDN = cRDN; - if (info->cRDN == 0) - info->rgRDN = NULL; - else - { - DWORD size, i; - BYTE *nextData; - const BYTE *ptr; - - info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo + - sizeof(CERT_NAME_INFO)); - nextData = (BYTE *)info->rgRDN + - info->cRDN * sizeof(CERT_RDN); - for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret && - i < cRDN && ptr - pbEncoded - 1 - lenBytes < - dataLen; i++) - { - info->rgRDN[i].rgRDNAttr = - (CERT_RDN_ATTR *)nextData; - size = bytesNeeded; - ret = CRYPT_AsnDecodeRdn(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, - &info->rgRDN[i], &size); - if (ret) - { - DWORD nextLen; - - nextData += size; - bytesNeeded -= size; - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + - GET_LEN_BYTES(ptr[1]); - } - } - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB); - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) - bytesNeeded += cbEncoded; - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if (*pcbStructInfo < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - *pcbStructInfo = bytesNeeded; - ret = FALSE; - } - else - { - PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo; - - *pcbStructInfo = bytesNeeded; - blob->cbData = cbEncoded; - if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) - blob->pbData = (LPBYTE)pbEncoded; - else - { - assert(blob->pbData); - memcpy(blob->pbData, pbEncoded, blob->cbData); - } - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - CRYPT_ALGORITHM_IDENTIFIER *algo = - (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo; - BOOL ret = TRUE; - struct AsnDecodeSequenceItem items[] = { - { offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), - CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE, - offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 }, - { offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters), - CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, - offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 }, - }; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL); - if (ret && pvStructInfo) - { - TRACE("pszObjId is %p (%s)\n", algo->pszObjId, - debugstr_a(algo->pszObjId)); - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - _SEH_TRY - { - struct AsnDecodeSequenceItem items[] = { - { offsetof(CERT_PUBLIC_KEY_INFO, Algorithm), - CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), - FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO, - Algorithm.pszObjId) }, - { offsetof(CERT_PUBLIC_KEY_INFO, PublicKey), - CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, - offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) }, - }; - - ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, NULL); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - if (cbEncoded < 3) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - return FALSE; - } - if (pbEncoded[0] != ASN_BOOL) - { - SetLastError(CRYPT_E_ASN1_BADTAG); - return FALSE; - } - if (GET_LEN_BYTES(pbEncoded[1]) > 1) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - return FALSE; - } - if (pbEncoded[1] > 1) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - return FALSE; - } - if (!pvStructInfo) - { - *pcbStructInfo = sizeof(BOOL); - ret = TRUE; - } - else if (*pcbStructInfo < sizeof(BOOL)) - { - *pcbStructInfo = sizeof(BOOL); - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE; - ret = TRUE; - } - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded, - DWORD dwFlags, CERT_ALT_NAME_ENTRY *entry, DWORD *pcbEntry) -{ - DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY); - BOOL ret; - - if (cbEncoded < 2) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - return FALSE; - } - if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT) - { - SetLastError(CRYPT_E_ASN1_BADTAG); - return FALSE; - } - lenBytes = GET_LEN_BYTES(pbEncoded[1]); - if (1 + lenBytes > cbEncoded) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - return FALSE; - } - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - switch (pbEncoded[0] & ASN_TYPE_MASK) - { - case 1: /* rfc822Name */ - case 2: /* dNSName */ - case 6: /* uniformResourceIdentifier */ - bytesNeeded += (dataLen + 1) * sizeof(WCHAR); - break; - case 7: /* iPAddress */ - bytesNeeded += dataLen; - break; - case 8: /* registeredID */ - /* FIXME: decode as OID */ - case 0: /* otherName */ - case 4: /* directoryName */ - FIXME("stub\n"); - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - break; - case 3: /* x400Address, unimplemented */ - case 5: /* ediPartyName, unimplemented */ - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - break; - default: - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - if (ret) - { - if (!entry) - *pcbEntry = bytesNeeded; - else if (*pcbEntry < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - /* MS used values one greater than the asn1 ones.. sigh */ - entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1; - switch (pbEncoded[0] & ASN_TYPE_MASK) - { - case 1: /* rfc822Name */ - case 2: /* dNSName */ - case 6: /* uniformResourceIdentifier */ - { - DWORD i; - - for (i = 0; i < dataLen; i++) - entry->u.pwszURL[i] = - (WCHAR)pbEncoded[1 + lenBytes + i]; - entry->u.pwszURL[i] = 0; - break; - } - case 7: /* iPAddress */ - /* The next data pointer is in the pwszURL spot, that is, - * the first 4 bytes. Need to move it to the next spot. - */ - entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL; - entry->u.IPAddress.cbData = dataLen; - memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes, - dataLen); - break; - } - } - } - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - _SEH_TRY - { - if (pbEncoded[0] == ASN_SEQUENCEOF) - { - DWORD dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - DWORD bytesNeeded, cEntry = 0; - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - bytesNeeded = sizeof(CERT_ALT_NAME_INFO); - if (dataLen) - { - const BYTE *ptr; - - for (ptr = pbEncoded + 1 + lenBytes; ret && - ptr - pbEncoded - 1 - lenBytes < dataLen; ) - { - DWORD size; - - ret = CRYPT_AsnDecodeAltNameEntry(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size); - if (ret) - { - DWORD nextLen; - - cEntry++; - bytesNeeded += size; - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); - } - } - } - if (ret) - { - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) - { - CERT_ALT_NAME_INFO *info; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - info = (CERT_ALT_NAME_INFO *)pvStructInfo; - info->cAltEntry = 0; - if (cEntry == 0) - info->rgAltEntry = NULL; - else - { - DWORD size, i; - BYTE *nextData; - const BYTE *ptr; - - info->rgAltEntry = - (CERT_ALT_NAME_ENTRY *)((BYTE *)pvStructInfo + - sizeof(CERT_ALT_NAME_INFO)); - nextData = (BYTE *)info->rgAltEntry + - cEntry * sizeof(CERT_ALT_NAME_ENTRY); - for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret && - i < cEntry && ptr - pbEncoded - 1 - lenBytes < - dataLen; i++) - { - info->rgAltEntry[i].u.pwszURL = - (LPWSTR)nextData; - size = bytesNeeded; - ret = CRYPT_AsnDecodeAltNameEntry(ptr, - cbEncoded - (ptr - pbEncoded), dwFlags, - &info->rgAltEntry[i], &size); - if (ret) - { - DWORD nextLen; - - info->cAltEntry++; - nextData += size - - sizeof(CERT_ALT_NAME_ENTRY); - bytesNeeded -= size; - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + - GET_LEN_BYTES(ptr[1]); - } - } - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -struct PATH_LEN_CONSTRAINT -{ - BOOL fPathLenConstraint; - DWORD dwPathLenConstraint; -}; - -static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - if (cbEncoded) - { - if (pbEncoded[0] == ASN_INTEGER) - { - DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT); - - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if (*pcbStructInfo < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - *pcbStructInfo = bytesNeeded; - ret = FALSE; - } - else - { - struct PATH_LEN_CONSTRAINT *constraint = - (struct PATH_LEN_CONSTRAINT *)pvStructInfo; - DWORD size = sizeof(constraint->dwPathLenConstraint); - - ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER, - pbEncoded, cbEncoded, 0, NULL, - &constraint->dwPathLenConstraint, &size); - if (ret) - constraint->fPathLenConstraint = TRUE; - TRACE("got an int, dwPathLenConstraint is %ld\n", - constraint->dwPathLenConstraint); - } - } - else - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - } - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - _SEH_TRY - { - struct AsnDecodeSequenceItem items[] = { - { offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA), CRYPT_AsnDecodeBool, - sizeof(BOOL), TRUE, FALSE, 0, 0 }, - { offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fPathLenConstraint), - CRYPT_AsnDecodePathLenConstraint, sizeof(struct PATH_LEN_CONSTRAINT), - TRUE, FALSE, 0, 0 }, - }; - - ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, NULL); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -#define RSA1_MAGIC 0x31415352 - -struct DECODED_RSA_PUB_KEY -{ - DWORD pubexp; - CRYPT_INTEGER_BLOB modulus; -}; - -static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - _SEH_TRY - { - struct AsnDecodeSequenceItem items[] = { - { offsetof(struct DECODED_RSA_PUB_KEY, modulus), - CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), - FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData), - 0 }, - { offsetof(struct DECODED_RSA_PUB_KEY, pubexp), - CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 }, - }; - struct DECODED_RSA_PUB_KEY *decodedKey = NULL; - DWORD size = 0; - - ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, - sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, - CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL); - if (ret) - { - DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + - decodedKey->modulus.cbData; - - if (!pvStructInfo) - { - *pcbStructInfo = bytesNeeded; - ret = TRUE; - } - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo, bytesNeeded))) - { - BLOBHEADER *hdr; - RSAPUBKEY *rsaPubKey; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - hdr = (BLOBHEADER *)pvStructInfo; - hdr->bType = PUBLICKEYBLOB; - hdr->bVersion = CUR_BLOB_VERSION; - hdr->reserved = 0; - hdr->aiKeyAlg = CALG_RSA_KEYX; - rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo + - sizeof(BLOBHEADER)); - rsaPubKey->magic = RSA1_MAGIC; - rsaPubKey->pubexp = decodedKey->pubexp; - rsaPubKey->bitlen = decodedKey->modulus.cbData * 8; - memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) + - sizeof(RSAPUBKEY), decodedKey->modulus.pbData, - decodedKey->modulus.cbData); - } - LocalFree(decodedKey); - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - if (pbEncoded[0] == ASN_OCTETSTRING) - { - DWORD bytesNeeded, dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) - bytesNeeded = sizeof(CRYPT_DATA_BLOB); - else - bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB); - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if (*pcbStructInfo < bytesNeeded) - { - SetLastError(ERROR_MORE_DATA); - *pcbStructInfo = bytesNeeded; - ret = FALSE; - } - else - { - CRYPT_DATA_BLOB *blob; - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - blob = (CRYPT_DATA_BLOB *)pvStructInfo; - blob->cbData = dataLen; - if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) - blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes; - else - { - assert(blob->pbData); - if (blob->cbData) - memcpy(blob->pbData, pbEncoded + 1 + lenBytes, - blob->cbData); - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - _SEH_TRY - { - DWORD bytesNeeded; - - if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded))) - { - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo, bytesNeeded))) - { - CRYPT_DATA_BLOB *blob; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - blob = (CRYPT_DATA_BLOB *)pvStructInfo; - blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB); - ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo, - &bytesNeeded); - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, *pcbStructInfo); - - if (pbEncoded[0] == ASN_BITSTRING) - { - DWORD bytesNeeded, dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) - bytesNeeded = sizeof(CRYPT_BIT_BLOB); - else - bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB); - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if (*pcbStructInfo < bytesNeeded) - { - *pcbStructInfo = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - CRYPT_BIT_BLOB *blob; - - blob = (CRYPT_BIT_BLOB *)pvStructInfo; - blob->cbData = dataLen - 1; - blob->cUnusedBits = *(pbEncoded + 1 + - GET_LEN_BYTES(pbEncoded[1])); - if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) - { - blob->pbData = (BYTE *)pbEncoded + 2 + - GET_LEN_BYTES(pbEncoded[1]); - } - else - { - assert(blob->pbData); - if (blob->cbData) - { - BYTE mask = 0xff << blob->cUnusedBits; - - memcpy(blob->pbData, pbEncoded + 2 + - GET_LEN_BYTES(pbEncoded[1]), blob->cbData); - blob->pbData[blob->cbData - 1] &= mask; - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo); - - _SEH_TRY - { - DWORD bytesNeeded; - - if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded))) - { - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo, bytesNeeded))) - { - CRYPT_BIT_BLOB *blob; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - blob = (CRYPT_BIT_BLOB *)pvStructInfo; - blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB); - ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo, - &bytesNeeded); - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - TRACE("returning %d (%08lx)\n", ret, GetLastError()); - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - if (!pvStructInfo) - { - *pcbStructInfo = sizeof(int); - return TRUE; - } - _SEH_TRY - { - BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)]; - CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf; - DWORD size = sizeof(buf); - - blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB); - ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType, - X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size); - if (ret) - { - if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo, sizeof(int)))) - { - int val, i; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - if (blob->pbData[blob->cbData - 1] & 0x80) - { - /* initialize to a negative value to sign-extend */ - val = -1; - } - else - val = 0; - for (i = 0; i < blob->cbData; i++) - { - val <<= 8; - val |= blob->pbData[blob->cbData - i - 1]; - } - memcpy(pvStructInfo, &val, sizeof(int)); - } - } - else if (GetLastError() == ERROR_MORE_DATA) - SetLastError(CRYPT_E_ASN1_LARGE); - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - if (pbEncoded[0] == ASN_INTEGER) - { - DWORD bytesNeeded, dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB); - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if (*pcbStructInfo < bytesNeeded) - { - *pcbStructInfo = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo; - - blob->cbData = dataLen; - assert(blob->pbData); - if (blob->cbData) - { - DWORD i; - - for (i = 0; i < blob->cbData; i++) - { - blob->pbData[i] = *(pbEncoded + 1 + lenBytes + - dataLen - i - 1); - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - _SEH_TRY - { - DWORD bytesNeeded; - - if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded))) - { - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo, bytesNeeded))) - { - CRYPT_INTEGER_BLOB *blob; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - blob = (CRYPT_INTEGER_BLOB *)pvStructInfo; - blob->pbData = (BYTE *)pvStructInfo + - sizeof(CRYPT_INTEGER_BLOB); - ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo, - &bytesNeeded); - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal( - DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, - DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, - void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - if (pbEncoded[0] == ASN_INTEGER) - { - DWORD bytesNeeded, dataLen; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); - - bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB); - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if (*pcbStructInfo < bytesNeeded) - { - *pcbStructInfo = bytesNeeded; - SetLastError(ERROR_MORE_DATA); - ret = FALSE; - } - else - { - CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo; - - blob->cbData = dataLen; - assert(blob->pbData); - /* remove leading zero byte if it exists */ - if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0) - { - blob->cbData--; - blob->pbData++; - } - if (blob->cbData) - { - DWORD i; - - for (i = 0; i < blob->cbData; i++) - { - blob->pbData[i] = *(pbEncoded + 1 + lenBytes + - dataLen - i - 1); - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - _SEH_TRY - { - DWORD bytesNeeded; - - if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded))) - { - if (!pvStructInfo) - *pcbStructInfo = bytesNeeded; - else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo, bytesNeeded))) - { - CRYPT_INTEGER_BLOB *blob; - - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - blob = (CRYPT_INTEGER_BLOB *)pvStructInfo; - blob->pbData = (BYTE *)pvStructInfo + - sizeof(CRYPT_INTEGER_BLOB); - ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, - dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo, - &bytesNeeded); - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - if (!pvStructInfo) - { - *pcbStructInfo = sizeof(int); - return TRUE; - } - _SEH_TRY - { - if (pbEncoded[0] == ASN_ENUMERATED) - { - unsigned int val = 0, i; - - if (cbEncoded <= 1) - { - SetLastError(CRYPT_E_ASN1_EOD); - ret = FALSE; - } - else if (pbEncoded[1] == 0) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - else - { - /* A little strange looking, but we have to accept a sign byte: - * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also, - * assuming a small length is okay here, it has to be in short - * form. - */ - if (pbEncoded[1] > sizeof(unsigned int) + 1) - { - SetLastError(CRYPT_E_ASN1_LARGE); - return FALSE; - } - for (i = 0; i < pbEncoded[1]; i++) - { - val <<= 8; - val |= pbEncoded[2 + i]; - } - if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo, sizeof(unsigned int)))) - { - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - memcpy(pvStructInfo, &val, sizeof(unsigned int)); - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -/* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE - * if it fails. - */ -#define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \ - do { \ - BYTE i; \ - \ - (word) = 0; \ - for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \ - { \ - if (!isdigit(*(pbEncoded))) \ - { \ - SetLastError(CRYPT_E_ASN1_CORRUPT); \ - ret = FALSE; \ - } \ - else \ - { \ - (word) *= 10; \ - (word) += *(pbEncoded)++ - '0'; \ - } \ - } \ - } while (0) - -static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len, - SYSTEMTIME *sysTime) -{ - BOOL ret; - - _SEH_TRY - { - ret = TRUE; - if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-')) - { - WORD hours, minutes = 0; - BYTE sign = *pbEncoded++; - - len--; - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours); - if (ret && hours >= 24) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - else if (len >= 2) - { - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes); - if (ret && minutes >= 60) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - } - if (ret) - { - if (sign == '+') - { - sysTime->wHour += hours; - sysTime->wMinute += minutes; - } - else - { - if (hours > sysTime->wHour) - { - sysTime->wDay--; - sysTime->wHour = 24 - (hours - sysTime->wHour); - } - else - sysTime->wHour -= hours; - if (minutes > sysTime->wMinute) - { - sysTime->wHour--; - sysTime->wMinute = 60 - (minutes - sysTime->wMinute); - } - else - sysTime->wMinute -= minutes; - } - } - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -#define MIN_ENCODED_TIME_LENGTH 10 - -static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - if (!pvStructInfo) - { - *pcbStructInfo = sizeof(FILETIME); - return TRUE; - } - _SEH_TRY - { - ret = TRUE; - if (pbEncoded[0] == ASN_UTCTIME) - { - if (cbEncoded <= 1) - { - SetLastError(CRYPT_E_ASN1_EOD); - ret = FALSE; - } - else if (pbEncoded[1] > 0x7f) - { - /* long-form date strings really can't be valid */ - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - else - { - SYSTEMTIME sysTime = { 0 }; - BYTE len = pbEncoded[1]; - - if (len < MIN_ENCODED_TIME_LENGTH) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - else - { - pbEncoded += 2; - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear); - if (sysTime.wYear >= 50) - sysTime.wYear += 1900; - else - sysTime.wYear += 2000; - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth); - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay); - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour); - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute); - if (ret && len > 0) - { - if (len >= 2 && isdigit(*pbEncoded) && - isdigit(*(pbEncoded + 1))) - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, - sysTime.wSecond); - else if (isdigit(*pbEncoded)) - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1, - sysTime.wSecond); - if (ret) - ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len, - &sysTime); - } - if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, - sizeof(FILETIME)))) - { - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - ret = SystemTimeToFileTime(&sysTime, - (FILETIME *)pvStructInfo); - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - if (!pvStructInfo) - { - *pcbStructInfo = sizeof(FILETIME); - return TRUE; - } - _SEH_TRY - { - ret = TRUE; - if (pbEncoded[0] == ASN_GENERALTIME) - { - if (cbEncoded <= 1) - { - SetLastError(CRYPT_E_ASN1_EOD); - ret = FALSE; - } - else if (pbEncoded[1] > 0x7f) - { - /* long-form date strings really can't be valid */ - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - else - { - BYTE len = pbEncoded[1]; - - if (len < MIN_ENCODED_TIME_LENGTH) - { - SetLastError(CRYPT_E_ASN1_CORRUPT); - ret = FALSE; - } - else - { - SYSTEMTIME sysTime = { 0 }; - - pbEncoded += 2; - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear); - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth); - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay); - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour); - if (ret && len > 0) - { - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, - sysTime.wMinute); - if (ret && len > 0) - CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, - sysTime.wSecond); - if (ret && len > 0 && (*pbEncoded == '.' || - *pbEncoded == ',')) - { - BYTE digits; - - pbEncoded++; - len--; - /* workaround macro weirdness */ - digits = min(len, 3); - CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits, - sysTime.wMilliseconds); - } - if (ret) - ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len, - &sysTime); - } - if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, - pDecodePara, pvStructInfo, pcbStructInfo, - sizeof(FILETIME)))) - { - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - ret = SystemTimeToFileTime(&sysTime, - (FILETIME *)pvStructInfo); - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret; - - _SEH_TRY - { - if (pbEncoded[0] == ASN_UTCTIME) - ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType, - pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, - pcbStructInfo); - else if (pbEncoded[0] == ASN_GENERALTIME) - ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo); - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - ret = FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType, - LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = TRUE; - - _SEH_TRY - { - if (pbEncoded[0] == ASN_SEQUENCEOF) - { - DWORD bytesNeeded, dataLen, remainingLen, cValue; - - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) - { - BYTE lenBytes; - const BYTE *ptr; - - lenBytes = GET_LEN_BYTES(pbEncoded[1]); - bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY); - cValue = 0; - ptr = pbEncoded + 1 + lenBytes; - remainingLen = dataLen; - while (ret && remainingLen) - { - DWORD nextLen; - - ret = CRYPT_GetLen(ptr, remainingLen, &nextLen); - if (ret) - { - DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]); - - remainingLen -= 1 + nextLenBytes + nextLen; - ptr += 1 + nextLenBytes + nextLen; - bytesNeeded += sizeof(CRYPT_DER_BLOB); - if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) - bytesNeeded += 1 + nextLenBytes + nextLen; - cValue++; - } - } - if (ret) - { - CRYPT_SEQUENCE_OF_ANY *seq; - BYTE *nextPtr; - DWORD i; - - if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, - pvStructInfo, pcbStructInfo, bytesNeeded))) - { - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) - pvStructInfo = *(BYTE **)pvStructInfo; - seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo; - seq->cValue = cValue; - seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq + - sizeof(*seq)); - nextPtr = (BYTE *)seq->rgValue + - cValue * sizeof(CRYPT_DER_BLOB); - ptr = pbEncoded + 1 + lenBytes; - remainingLen = dataLen; - i = 0; - while (ret && remainingLen) - { - DWORD nextLen; - - ret = CRYPT_GetLen(ptr, remainingLen, &nextLen); - if (ret) - { - DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]); - - seq->rgValue[i].cbData = 1 + nextLenBytes + - nextLen; - if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) - seq->rgValue[i].pbData = (BYTE *)ptr; - else - { - seq->rgValue[i].pbData = nextPtr; - memcpy(nextPtr, ptr, 1 + nextLenBytes + - nextLen); - nextPtr += 1 + nextLenBytes + nextLen; - } - remainingLen -= 1 + nextLenBytes + nextLen; - ptr += 1 + nextLenBytes + nextLen; - i++; - } - } - } - } - } - } - else - { - SetLastError(CRYPT_E_ASN1_BADTAG); - return FALSE; - } - } - _SEH_EXCEPT(page_fault) - { - SetLastError(STATUS_ACCESS_VIOLATION); - ret = FALSE; - } - _SEH_END - return ret; -} - -BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, - const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, - PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) -{ - BOOL ret = FALSE; - HMODULE lib = NULL; - CryptDecodeObjectExFunc decodeFunc = NULL; - - TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n", - dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded, - cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); - - if (!pvStructInfo && !pcbStructInfo) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING - && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING) - { - SetLastError(ERROR_FILE_NOT_FOUND); - return FALSE; - } - if (!cbEncoded) - { - SetLastError(CRYPT_E_ASN1_EOD); - return FALSE; - } - if (cbEncoded > MAX_ENCODED_LEN) - { - SetLastError(CRYPT_E_ASN1_LARGE); - return FALSE; - } - - SetLastError(NOERROR); - if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo) - *(BYTE **)pvStructInfo = NULL; - if (!HIWORD(lpszStructType)) - { - switch (LOWORD(lpszStructType)) - { - case (WORD)X509_CERT: - decodeFunc = CRYPT_AsnDecodeCert; - break; - case (WORD)X509_CERT_TO_BE_SIGNED: - decodeFunc = CRYPT_AsnDecodeCertInfo; - break; - case (WORD)X509_CERT_CRL_TO_BE_SIGNED: - decodeFunc = CRYPT_AsnDecodeCRLInfo; - break; - case (WORD)X509_EXTENSIONS: - decodeFunc = CRYPT_AsnDecodeExtensions; - break; - case (WORD)X509_NAME: - decodeFunc = CRYPT_AsnDecodeName; - break; - case (WORD)X509_PUBLIC_KEY_INFO: - decodeFunc = CRYPT_AsnDecodePubKeyInfo; - break; - case (WORD)X509_ALTERNATE_NAME: - decodeFunc = CRYPT_AsnDecodeAltName; - break; - case (WORD)X509_BASIC_CONSTRAINTS2: - decodeFunc = CRYPT_AsnDecodeBasicConstraints2; - break; - case (WORD)RSA_CSP_PUBLICKEYBLOB: - decodeFunc = CRYPT_AsnDecodeRsaPubKey; - break; - case (WORD)X509_OCTET_STRING: - decodeFunc = CRYPT_AsnDecodeOctets; - break; - case (WORD)X509_BITS: - case (WORD)X509_KEY_USAGE: - decodeFunc = CRYPT_AsnDecodeBits; - break; - case (WORD)X509_INTEGER: - decodeFunc = CRYPT_AsnDecodeInt; - break; - case (WORD)X509_MULTI_BYTE_INTEGER: - decodeFunc = CRYPT_AsnDecodeInteger; - break; - case (WORD)X509_MULTI_BYTE_UINT: - decodeFunc = CRYPT_AsnDecodeUnsignedInteger; - break; - case (WORD)X509_ENUMERATED: - decodeFunc = CRYPT_AsnDecodeEnumerated; - break; - case (WORD)X509_CHOICE_OF_TIME: - decodeFunc = CRYPT_AsnDecodeChoiceOfTime; - break; - case (WORD)X509_SEQUENCE_OF_ANY: - decodeFunc = CRYPT_AsnDecodeSequenceOfAny; - break; - case (WORD)PKCS_UTC_TIME: - decodeFunc = CRYPT_AsnDecodeUtcTime; - break; - default: - FIXME("%d: unimplemented\n", LOWORD(lpszStructType)); - } - } - else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS)) - decodeFunc = CRYPT_AsnDecodeExtensions; - else if (!strcmp(lpszStructType, szOID_RSA_signingTime)) - decodeFunc = CRYPT_AsnDecodeUtcTime; - else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE)) - decodeFunc = CRYPT_AsnDecodeEnumerated; - else if (!strcmp(lpszStructType, szOID_KEY_USAGE)) - decodeFunc = CRYPT_AsnDecodeBits; - else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER)) - decodeFunc = CRYPT_AsnDecodeOctets; - else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2)) - decodeFunc = CRYPT_AsnDecodeBasicConstraints2; - else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME)) - decodeFunc = CRYPT_AsnDecodeAltName; - else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2)) - decodeFunc = CRYPT_AsnDecodeAltName; - else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION)) - decodeFunc = CRYPT_AsnDecodeAltName; - else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME)) - decodeFunc = CRYPT_AsnDecodeAltName; - else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2)) - decodeFunc = CRYPT_AsnDecodeAltName; - else - TRACE("OID %s not found or unimplemented, looking for DLL\n", - debugstr_a(lpszStructType)); - if (!decodeFunc) - decodeFunc = (CryptDecodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType, - lpszStructType, CRYPT_OID_DECODE_OBJECT_EX_FUNC, &lib); - if (decodeFunc) - ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded, - cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); - else - SetLastError(ERROR_FILE_NOT_FOUND); - if (lib) - FreeLibrary(lib); - return ret; -} - -BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec, - DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) -{ - return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType, - NULL, 0, NULL, pInfo, pcbInfo); -} - -static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv, - DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, - DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) -{ - BOOL ret; - HCRYPTKEY key; - - TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec, - dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo, - pInfo, pcbInfo); - - if (!pszPublicKeyObjId) - pszPublicKeyObjId = szOID_RSA_RSA; - if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key))) - { - DWORD keySize = 0; - - ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize); - if (ret) - { - LPBYTE pubKey = CryptMemAlloc(keySize); - - if (pubKey) - { - ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey, - &keySize); - if (ret) - { - DWORD encodedLen = 0; - - ret = CryptEncodeObject(dwCertEncodingType, - RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen); - if (ret) - { - DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) + - strlen(pszPublicKeyObjId) + 1 + encodedLen; - - if (!pInfo) - *pcbInfo = sizeNeeded; - else if (*pcbInfo < sizeNeeded) - { - SetLastError(ERROR_MORE_DATA); - *pcbInfo = sizeNeeded; - ret = FALSE; - } - else - { - pInfo->Algorithm.pszObjId = (char *)pInfo + - sizeof(CERT_PUBLIC_KEY_INFO); - lstrcpyA(pInfo->Algorithm.pszObjId, - pszPublicKeyObjId); - pInfo->Algorithm.Parameters.cbData = 0; - pInfo->Algorithm.Parameters.pbData = NULL; - pInfo->PublicKey.pbData = - (BYTE *)pInfo->Algorithm.pszObjId - + lstrlenA(pInfo->Algorithm.pszObjId) + 1; - pInfo->PublicKey.cbData = encodedLen; - pInfo->PublicKey.cUnusedBits = 0; - ret = CryptEncodeObject(dwCertEncodingType, - RSA_CSP_PUBLICKEYBLOB, pubKey, - pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData); - } - } - } - CryptMemFree(pubKey); - } - else - ret = FALSE; - } - CryptDestroyKey(key); - } - return ret; -} - -typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv, - DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, - DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo); - -BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec, - DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags, - void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo) -{ - BOOL ret; - ExportPublicKeyInfoExFunc exportFunc = NULL; - HMODULE lib = NULL; - - TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec, - dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo, - pInfo, pcbInfo); - - if (!hCryptProv) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (pszPublicKeyObjId) - exportFunc = CRYPT_GetFunc(dwCertEncodingType, pszPublicKeyObjId, - CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC, &lib); - if (!exportFunc) - exportFunc = CRYPT_ExportRsaPublicKeyInfoEx; - ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType, - pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo); - if (lib) - FreeLibrary(lib); - return ret; -} - -BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv, - DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) -{ - return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo, - 0, 0, NULL, phKey); -} - -static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv, - DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, - DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey) -{ - BOOL ret; - DWORD pubKeySize = 0; - - TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv, - dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey); - - ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, - pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize); - if (ret) - { - LPBYTE pubKey = CryptMemAlloc(pubKeySize); - - if (pubKey) - { - ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB, - pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey, - &pubKeySize); - if (ret) - ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0, - phKey); - CryptMemFree(pubKey); - } - else - ret = FALSE; - } - return ret; -} - -typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv, - DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, - DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey); - -BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv, - DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, - DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey) -{ - BOOL ret; - ImportPublicKeyInfoExFunc importFunc = NULL; - HMODULE lib = NULL; - - TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv, - dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey); - - importFunc = CRYPT_GetFunc(dwCertEncodingType, pInfo->Algorithm.pszObjId, - CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, &lib); - if (!importFunc) - importFunc = CRYPT_ImportRsaPublicKeyInfoEx; - ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, - pvAuxInfo, phKey); - if (lib) - FreeLibrary(lib); - return ret; -} diff --git a/reactos/lib/crypt32/main.c b/reactos/lib/crypt32/main.c deleted file mode 100644 index 0dda361f9aa..00000000000 --- a/reactos/lib/crypt32/main.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright 2002 Mike McCormack for CodeWeavers - * Copyright 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "precomp.h" - -WINE_DEFAULT_DEBUG_CHANNEL(crypt); - -static HCRYPTPROV hDefProv; - -struct OIDToAlgID -{ - LPCSTR oid; - DWORD algID; -}; - -static const struct OIDToAlgID oidToAlgID[] = { - { szOID_RSA_RSA, CALG_RSA_KEYX }, - { szOID_RSA_MD2RSA, CALG_MD2 }, - { szOID_RSA_MD4RSA, CALG_MD4 }, - { szOID_RSA_MD5RSA, CALG_MD5 }, - { szOID_RSA_SHA1RSA, CALG_SHA }, - { szOID_RSA_DH, CALG_DH_SF }, - { szOID_RSA_SMIMEalgESDH, CALG_DH_EPHEM }, - { szOID_RSA_SMIMEalgCMS3DESwrap, CALG_3DES }, - { szOID_RSA_SMIMEalgCMSRC2wrap, CALG_RC2 }, - { szOID_RSA_MD2, CALG_MD2 }, - { szOID_RSA_MD4, CALG_MD4 }, - { szOID_RSA_MD5, CALG_MD5 }, - { szOID_RSA_RC2CBC, CALG_RC2 }, - { szOID_RSA_RC4, CALG_RC4 }, - { szOID_RSA_DES_EDE3_CBC, CALG_3DES }, - { szOID_ANSI_X942_DH, CALG_DH_SF }, - { szOID_X957_DSA, CALG_DSS_SIGN }, - { szOID_X957_SHA1DSA, CALG_SHA }, - { szOID_OIWSEC_md4RSA, CALG_MD4 }, - { szOID_OIWSEC_md5RSA, CALG_MD5 }, - { szOID_OIWSEC_md4RSA2, CALG_MD4 }, - { szOID_OIWSEC_desCBC, CALG_DES }, - { szOID_OIWSEC_dsa, CALG_DSS_SIGN }, - { szOID_OIWSEC_shaDSA, CALG_SHA }, - { szOID_OIWSEC_shaRSA, CALG_SHA }, - { szOID_OIWSEC_sha, CALG_SHA }, - { szOID_OIWSEC_rsaXchg, CALG_RSA_KEYX }, - { szOID_OIWSEC_sha1, CALG_SHA }, - { szOID_OIWSEC_dsaSHA1, CALG_SHA }, - { szOID_OIWSEC_sha1RSASign, CALG_SHA }, - { szOID_OIWDIR_md2RSA, CALG_MD2 }, - { szOID_INFOSEC_mosaicUpdatedSig, CALG_SHA }, - { szOID_INFOSEC_mosaicKMandUpdSig, CALG_DSS_SIGN }, -}; - -BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) -{ - switch (fdwReason) - { - case DLL_PROCESS_DETACH: - if (hDefProv) CryptReleaseContext(hDefProv, 0); - break; - } - return TRUE; -} - -HCRYPTPROV CRYPT_GetDefaultProvider(void) -{ - if (!hDefProv) - CryptAcquireContextW(&hDefProv, NULL, MS_ENHANCED_PROV_W, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - return hDefProv; -} - -/* this function is called by Internet Explorer when it is about to verify a downloaded component */ -BOOL WINAPI I_CryptCreateLruCache(DWORD x, DWORD y) -{ - FIXME("stub!\n"); - return FALSE; -} - -/* these functions all have an unknown number of args */ -BOOL WINAPI I_CryptFindLruEntryData(DWORD x) -{ - FIXME("stub!\n"); - return FALSE; -} - -BOOL WINAPI I_CryptFlushLruCache(DWORD x) -{ - FIXME("stub!\n"); - return FALSE; -} - -BOOL WINAPI I_CryptFreeLruCache(DWORD x) -{ - FIXME("stub!\n"); - return FALSE; -} - -BOOL WINAPI CryptSIPRemoveProvider(GUID *pgProv) -{ - FIXME("stub!\n"); - return FALSE; -} - -/* convert a guid to a wide character string */ -static void CRYPT_guid2wstr( LPGUID guid, LPWSTR wstr ) -{ - char str[40]; - - sprintf(str, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); - MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, 40 ); -} - -/* - * Helper for CryptSIPAddProvider - * - * Add a registry key containing a dll name and function under - * "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\\\" - */ -static LONG CRYPT_SIPWriteFunction( LPGUID guid, LPCWSTR szKey, - LPCWSTR szDll, LPCWSTR szFunction ) -{ - static const WCHAR szOID[] = { - 'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'C','r','y','p','t','o','g','r','a','p','h','y','\\', - 'O','I','D','\\', - 'E','n','c','o','d','i','n','g','T','y','p','e',' ','0','\\', - 'C','r','y','p','t','S','I','P','D','l','l', 0 }; - static const WCHAR szBackSlash[] = { '\\', 0 }; - static const WCHAR szDllName[] = { 'D','l','l',0 }; - static const WCHAR szFuncName[] = { 'F','u','n','c','N','a','m','e',0 }; - WCHAR szFullKey[ 0x100 ]; - LONG r; - HKEY hKey; - - if( !szFunction ) - return ERROR_SUCCESS; - - /* max length of szFullKey depends on our code only, so we won't overrun */ - lstrcpyW( szFullKey, szOID ); - lstrcatW( szFullKey, szKey ); - lstrcatW( szFullKey, szBackSlash ); - CRYPT_guid2wstr( guid, &szFullKey[ lstrlenW( szFullKey ) ] ); - lstrcatW( szFullKey, szBackSlash ); - - TRACE("key is %s\n", debugstr_w( szFullKey ) ); - - r = RegCreateKeyW( HKEY_LOCAL_MACHINE, szFullKey, &hKey ); - if( r != ERROR_SUCCESS ) - return r; - - /* write the values */ - RegSetValueExW( hKey, szFuncName, 0, REG_SZ, (const BYTE*) szFunction, - ( lstrlenW( szFunction ) + 1 ) * sizeof (WCHAR) ); - RegSetValueExW( hKey, szDllName, 0, REG_SZ, (const BYTE*) szDll, - ( lstrlenW( szDll ) + 1) * sizeof (WCHAR) ); - - RegCloseKey( hKey ); - - return ERROR_SUCCESS; -} - -BOOL WINAPI CryptSIPAddProvider(SIP_ADD_NEWPROVIDER *psNewProv) -{ - static const WCHAR szCreate[] = { - 'C','r','e','a','t','e', - 'I','n','d','i','r','e','c','t','D','a','t','a',0}; - static const WCHAR szGetSigned[] = { - 'G','e','t','S','i','g','n','e','d','D','a','t','a','M','s','g',0}; - static const WCHAR szIsMyFile[] = { - 'I','s','M','y','F','i','l','e','T','y','p','e', 0 }; - static const WCHAR szPutSigned[] = { - 'P','u','t','S','i','g','n','e','d','D','a','t','a','M','s','g',0}; - static const WCHAR szRemoveSigned[] = { - 'R','e','m','o','v','e', - 'S','i','g','n','e','d','D','a','t','a','M','s','g',0}; - static const WCHAR szVerify[] = { - 'V','e','r','i','f','y', - 'I','n','d','i','r','e','c','t','D','a','t','a',0}; - - TRACE("%p\n", psNewProv); - - if( !psNewProv ) - return FALSE; - - TRACE("%s %s %s %s\n", - debugstr_guid( psNewProv->pgSubject ), - debugstr_w( psNewProv->pwszDLLFileName ), - debugstr_w( psNewProv->pwszMagicNumber ), - debugstr_w( psNewProv->pwszIsFunctionName ) ); - -#define CRYPT_SIPADDPROV( key, field ) \ - CRYPT_SIPWriteFunction( psNewProv->pgSubject, key, \ - psNewProv->pwszDLLFileName, psNewProv->field) - - CRYPT_SIPADDPROV( szGetSigned, pwszGetFuncName ); - CRYPT_SIPADDPROV( szPutSigned, pwszPutFuncName ); - CRYPT_SIPADDPROV( szCreate, pwszCreateFuncName ); - CRYPT_SIPADDPROV( szVerify, pwszVerifyFuncName ); - CRYPT_SIPADDPROV( szRemoveSigned, pwszRemoveFuncName ); - CRYPT_SIPADDPROV( szIsMyFile, pwszIsFunctionNameFmt2 ); - -#undef CRYPT_SIPADDPROV - - return TRUE; -} - -BOOL WINAPI CryptSIPRetrieveSubjectGuid - (LPCWSTR FileName, HANDLE hFileIn, GUID *pgSubject) -{ - FIXME("stub!\n"); - return FALSE; -} - -BOOL WINAPI CryptSIPLoad - (const GUID *pgSubject, DWORD dwFlags, SIP_DISPATCH_INFO *pSipDispatch) -{ - FIXME("stub!\n"); - return FALSE; -} - -BOOL WINAPI CryptRegisterDefaultOIDFunction(DWORD dwEncodingType, - LPCSTR pszFuncName, DWORD dwIndex, - LPCWSTR pwszDll) -{ - FIXME("(%lx,%s,%lx,%s) stub!\n", dwEncodingType, pszFuncName, dwIndex, - debugstr_w(pwszDll)); - return FALSE; -} - -LPCSTR WINAPI CertAlgIdToOID(DWORD dwAlgId) -{ - switch (dwAlgId) - { - case CALG_RSA_KEYX: - return szOID_RSA_RSA; - case CALG_DH_EPHEM: - return szOID_RSA_SMIMEalgESDH; - case CALG_MD2: - return szOID_RSA_MD2; - case CALG_MD4: - return szOID_RSA_MD4; - case CALG_MD5: - return szOID_RSA_MD5; - case CALG_RC2: - return szOID_RSA_RC2CBC; - case CALG_RC4: - return szOID_RSA_RC4; - case CALG_3DES: - return szOID_RSA_DES_EDE3_CBC; - case CALG_DH_SF: - return szOID_ANSI_X942_DH; - case CALG_DSS_SIGN: - return szOID_X957_DSA; - case CALG_DES: - return szOID_OIWSEC_desCBC; - case CALG_SHA: - return szOID_OIWSEC_sha1; - default: - return NULL; - } -} - -DWORD WINAPI CertOIDToAlgId(LPCSTR pszObjId) -{ - int i; - - if (pszObjId) - { - for (i = 0; i < sizeof(oidToAlgID) / sizeof(oidToAlgID[0]); i++) - { - if (!strcmp(pszObjId, oidToAlgID[i].oid)) - return oidToAlgID[i].algID; - } - } - return 0; -} - -LPVOID WINAPI CryptMemAlloc(ULONG cbSize) -{ - return HeapAlloc(GetProcessHeap(), 0, cbSize); -} - -LPVOID WINAPI CryptMemRealloc(LPVOID pv, ULONG cbSize) -{ - return HeapReAlloc(GetProcessHeap(), 0, pv, cbSize); -} - -VOID WINAPI CryptMemFree(LPVOID pv) -{ - HeapFree(GetProcessHeap(), 0, pv); -} - -DWORD WINAPI I_CryptAllocTls(void) -{ - return TlsAlloc(); -} - -LPVOID WINAPI I_CryptDetachTls(DWORD dwTlsIndex) -{ - LPVOID ret; - - ret = TlsGetValue(dwTlsIndex); - - TlsSetValue(dwTlsIndex, NULL); - return ret; -} - -LPVOID WINAPI I_CryptGetTls(DWORD dwTlsIndex) -{ - return TlsGetValue(dwTlsIndex); -} - -BOOL WINAPI I_CryptSetTls(DWORD dwTlsIndex, LPVOID lpTlsValue) -{ - return TlsSetValue(dwTlsIndex, lpTlsValue); -} - -BOOL WINAPI I_CryptFreeTls(DWORD dwTlsIndex, DWORD unknown) -{ - TRACE("(%ld, %ld)\n", dwTlsIndex, unknown); - return TlsFree(dwTlsIndex); -} diff --git a/reactos/lib/crypt32/precomp.h b/reactos/lib/crypt32/precomp.h deleted file mode 100644 index 4e7ae8259a0..00000000000 --- a/reactos/lib/crypt32/precomp.h +++ /dev/null @@ -1,20 +0,0 @@ - -#include "config.h" - -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wincrypt.h" -#include "winreg.h" -#include "snmp.h" -#include "winnls.h" -#include "mssip.h" -#include "crypt32_private.h" -#include "wine/debug.h" - -#define NTOS_MODE_USER -#include diff --git a/reactos/lib/crypt32/protectdata.c b/reactos/lib/crypt32/protectdata.c deleted file mode 100644 index d62f8372e79..00000000000 --- a/reactos/lib/crypt32/protectdata.c +++ /dev/null @@ -1,1128 +0,0 @@ -/* - * Copyright 2005 Kees Cook - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* - * The Win32 CryptProtectData and CryptUnprotectData functions are meant - * to provide a mechanism for encrypting data on a machine where other users - * of the system can't be trusted. It is used in many examples as a way - * to store username and password information to the registry, but store - * it not in the clear. - * - * The encryption is symmetric, but the method is unknown. However, since - * it is keyed to the machine and the user, it is unlikely that the values - * would be portable. Since programs must first call CryptProtectData to - * get a cipher text, the underlying system doesn't have to exactly - * match the real Windows version. However, attempts have been made to - * at least try to look like the Windows version, including guesses at the - * purpose of various portions of the "opaque data blob" that is used. - * - */ - -#include "precomp.h" - -WINE_DEFAULT_DEBUG_CHANNEL(crypt); - -#define CRYPT32_PROTECTDATA_PROV PROV_RSA_FULL -#define CRYPT32_PROTECTDATA_HASH_CALG CALG_MD5 -#define CRYPT32_PROTECTDATA_KEY_CALG CALG_RC2 -#define CRYPT32_PROTECTDATA_SALT_LEN 16 - -static const BYTE crypt32_protectdata_secret[] = { - 'I','\'','m',' ','h','u','n','t','i','n','g',' ', - 'w','a','b','b','i','t','s',0 -}; - -/* - * The data format returned by the real Windows CryptProtectData seems - * to be something like this: - - DWORD count0; - how many "info0_*[16]" blocks follow (was always 1) - BYTE info0_0[16]; - unknown information - ... - DWORD count1; - how many "info1_*[16]" blocks follow (was always 1) - BYTE info1_0[16]; - unknown information - ... - DWORD null0; - NULL "end of records"? - DWORD str_len; - length of WCHAR string including term - WCHAR str[str_len]; - The "dataDescription" value - DWORD unknown0; - unknown value (seems large, but only WORD large) - DWORD unknown1; - unknown value (seems small, less than a BYTE) - DWORD data_len; - length of data (was 16 in samples) - BYTE data[data_len]; - unknown data (fingerprint?) - DWORD null1; - NULL ? - DWORD unknown2; - unknown value (seems large, but only WORD large) - DWORD unknown3; - unknown value (seems small, less than a BYTE) - DWORD salt_len; - length of salt(?) data - BYTE salt[salt_len]; - salt(?) for symmetric encryption - DWORD cipher_len; - length of cipher(?) data - was close to plain len - BYTE cipher[cipher_len]; - cipher text? - DWORD crc_len; - length of fingerprint(?) data - was 20 byte==160b SHA1 - BYTE crc[crc_len]; - fingerprint of record? - - * The data structures used in Wine are modelled after this guess. - */ - -struct protect_data_t -{ - DWORD count0; - DATA_BLOB info0; /* using this to hold crypt_magic_str */ - DWORD count1; - DATA_BLOB info1; - DWORD null0; - WCHAR * szDataDescr; /* serialized differently than the DATA_BLOBs */ - DWORD unknown0; /* perhaps the HASH alg const should go here? */ - DWORD unknown1; - DATA_BLOB data0; - DWORD null1; - DWORD unknown2; /* perhaps the KEY alg const should go here? */ - DWORD unknown3; - DATA_BLOB salt; - DATA_BLOB cipher; - DATA_BLOB fingerprint; -}; - -/* this is used to check if an incoming structure was built by Wine */ -static const char * crypt_magic_str = "Wine Crypt32 ok"; - -/* debugging tool to print strings of hex chars */ -static const char * -hex_str(unsigned char *p, int n) -{ - const char * ptr; - char report[80]; - int r=-1; - report[0]='\0'; - ptr = wine_dbg_sprintf("%s",""); - while (--n >= 0) - { - if (r++ % 20 == 19) - { - ptr = wine_dbg_sprintf("%s%s",ptr,report); - report[0]='\0'; - } - sprintf(report+strlen(report),"%s%02x", r ? "," : "", *p++); - } - return wine_dbg_sprintf("%s%s",ptr,report); -} - -#define TRACE_DATA_BLOB(blob) do { \ - TRACE("%s cbData: %u\n", #blob ,(unsigned int)((blob)->cbData)); \ - TRACE("%s pbData @ %p:%s\n", #blob ,(blob)->pbData, \ - hex_str((blob)->pbData, (blob)->cbData)); \ -} while (0) - -static -void serialize_dword(DWORD value,BYTE ** ptr) -{ - /*TRACE("called\n");*/ - - memcpy(*ptr,&value,sizeof(DWORD)); - *ptr+=sizeof(DWORD); -} - -static -void serialize_string(BYTE * str,BYTE ** ptr,DWORD len, DWORD width, - BOOL prepend_len) -{ - /*TRACE("called %ux%u\n",(unsigned int)len,(unsigned int)width);*/ - - if (prepend_len) - { - serialize_dword(len,ptr); - } - memcpy(*ptr,str,len*width); - *ptr+=len*width; -} - -static -BOOL unserialize_dword(BYTE * ptr, DWORD *index, DWORD size, DWORD * value) -{ - /*TRACE("called\n");*/ - - if (!ptr || !index || !value) return FALSE; - - if (*index+sizeof(DWORD)>size) - { - return FALSE; - } - - memcpy(value,&(ptr[*index]),sizeof(DWORD)); - *index+=sizeof(DWORD); - - return TRUE; -} - -static -BOOL unserialize_string(BYTE * ptr, DWORD *index, DWORD size, - DWORD len, DWORD width, BOOL inline_len, - BYTE ** data, DWORD * stored) -{ - /*TRACE("called\n");*/ - - if (!ptr || !data) return FALSE; - - if (inline_len) { - if (!unserialize_dword(ptr,index,size,&len)) - return FALSE; - } - - if (*index+len*width>size) - { - return FALSE; - } - - if (!(*data = CryptMemAlloc( len*width))) - { - return FALSE; - } - - memcpy(*data,&(ptr[*index]),len*width); - if (stored) - { - *stored = len; - } - *index+=len*width; - - return TRUE; -} - -static -BOOL serialize(struct protect_data_t * pInfo, DATA_BLOB * pSerial) -{ - BYTE * ptr; - DWORD dwStrLen; - DWORD dwStruct; - - TRACE("called\n"); - - if (!pInfo || !pInfo->szDataDescr || !pSerial || - !pInfo->info0.pbData || !pInfo->info1.pbData || - !pInfo->data0.pbData || !pInfo->salt.pbData || - !pInfo->cipher.pbData || !pInfo->fingerprint.pbData) - { - return FALSE; - } - - if (pInfo->info0.cbData!=16) - { - ERR("protect_data_t info0 not 16 bytes long\n"); - } - - if (pInfo->info1.cbData!=16) - { - ERR("protect_data_t info1 not 16 bytes long\n"); - } - - dwStrLen=lstrlenW(pInfo->szDataDescr); - - pSerial->cbData=0; - pSerial->cbData+=sizeof(DWORD)*8; /* 8 raw DWORDs */ - pSerial->cbData+=sizeof(DWORD)*4; /* 4 BLOBs with size */ - pSerial->cbData+=pInfo->info0.cbData; - pSerial->cbData+=pInfo->info1.cbData; - pSerial->cbData+=(dwStrLen+1)*sizeof(WCHAR) + 4; /* str, null, size */ - pSerial->cbData+=pInfo->data0.cbData; - pSerial->cbData+=pInfo->salt.cbData; - pSerial->cbData+=pInfo->cipher.cbData; - pSerial->cbData+=pInfo->fingerprint.cbData; - - /* save the actual structure size */ - dwStruct = pSerial->cbData; - /* There may be a 256 byte minimum, but I can't prove it. */ - /*if (pSerial->cbData<256) pSerial->cbData=256;*/ - - pSerial->pbData=LocalAlloc(LPTR,pSerial->cbData); - if (!pSerial->pbData) return FALSE; - - ptr=pSerial->pbData; - - /* count0 */ - serialize_dword(pInfo->count0,&ptr); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* info0 */ - serialize_string(pInfo->info0.pbData,&ptr, - pInfo->info0.cbData,sizeof(BYTE),FALSE); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* count1 */ - serialize_dword(pInfo->count1,&ptr); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* info1 */ - serialize_string(pInfo->info1.pbData,&ptr, - pInfo->info1.cbData,sizeof(BYTE),FALSE); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* null0 */ - serialize_dword(pInfo->null0,&ptr); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* szDataDescr */ - serialize_string((BYTE*)pInfo->szDataDescr,&ptr, - (dwStrLen+1)*sizeof(WCHAR),sizeof(BYTE),TRUE); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* unknown0 */ - serialize_dword(pInfo->unknown0,&ptr); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - /* unknown1 */ - serialize_dword(pInfo->unknown1,&ptr); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* data0 */ - serialize_string(pInfo->data0.pbData,&ptr, - pInfo->data0.cbData,sizeof(BYTE),TRUE); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* null1 */ - serialize_dword(pInfo->null1,&ptr); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* unknown2 */ - serialize_dword(pInfo->unknown2,&ptr); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - /* unknown3 */ - serialize_dword(pInfo->unknown3,&ptr); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* salt */ - serialize_string(pInfo->salt.pbData,&ptr, - pInfo->salt.cbData,sizeof(BYTE),TRUE); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* cipher */ - serialize_string(pInfo->cipher.pbData,&ptr, - pInfo->cipher.cbData,sizeof(BYTE),TRUE); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - /* fingerprint */ - serialize_string(pInfo->fingerprint.pbData,&ptr, - pInfo->fingerprint.cbData,sizeof(BYTE),TRUE); - /*TRACE("used %u\n",ptr-pSerial->pbData);*/ - - if (ptr - pSerial->pbData != dwStruct) - { - ERR("struct size changed!? %u != expected %u\n", - ptr - pSerial->pbData, (unsigned int)dwStruct); - LocalFree(pSerial->pbData); - pSerial->pbData=NULL; - pSerial->cbData=0; - return FALSE; - } - - return TRUE; -} - -static -BOOL unserialize(DATA_BLOB * pSerial, struct protect_data_t * pInfo) -{ - BYTE * ptr; - DWORD index; - DWORD size; - BOOL status=TRUE; - - TRACE("called\n"); - - if (!pInfo || !pSerial || !pSerial->pbData) - return FALSE; - - index=0; - ptr=pSerial->pbData; - size=pSerial->cbData; - - /* count0 */ - if (!unserialize_dword(ptr,&index,size,&pInfo->count0)) - { - ERR("reading count0 failed!\n"); - return FALSE; - } - - /* info0 */ - if (!unserialize_string(ptr,&index,size,16,sizeof(BYTE),FALSE, - &pInfo->info0.pbData, &pInfo->info0.cbData)) - { - ERR("reading info0 failed!\n"); - return FALSE; - } - - /* count1 */ - if (!unserialize_dword(ptr,&index,size,&pInfo->count1)) - { - ERR("reading count1 failed!\n"); - return FALSE; - } - - /* info1 */ - if (!unserialize_string(ptr,&index,size,16,sizeof(BYTE),FALSE, - &pInfo->info1.pbData, &pInfo->info1.cbData)) - { - ERR("reading info1 failed!\n"); - return FALSE; - } - - /* null0 */ - if (!unserialize_dword(ptr,&index,size,&pInfo->null0)) - { - ERR("reading null0 failed!\n"); - return FALSE; - } - - /* szDataDescr */ - if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE, - (BYTE**)&pInfo->szDataDescr, NULL)) - { - ERR("reading szDataDescr failed!\n"); - return FALSE; - } - - /* unknown0 */ - if (!unserialize_dword(ptr,&index,size,&pInfo->unknown0)) - { - ERR("reading unknown0 failed!\n"); - return FALSE; - } - - /* unknown1 */ - if (!unserialize_dword(ptr,&index,size,&pInfo->unknown1)) - { - ERR("reading unknown1 failed!\n"); - return FALSE; - } - - /* data0 */ - if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE, - &pInfo->data0.pbData, &pInfo->data0.cbData)) - { - ERR("reading data0 failed!\n"); - return FALSE; - } - - /* null1 */ - if (!unserialize_dword(ptr,&index,size,&pInfo->null1)) - { - ERR("reading null1 failed!\n"); - return FALSE; - } - - /* unknown2 */ - if (!unserialize_dword(ptr,&index,size,&pInfo->unknown2)) - { - ERR("reading unknown2 failed!\n"); - return FALSE; - } - - /* unknown3 */ - if (!unserialize_dword(ptr,&index,size,&pInfo->unknown3)) - { - ERR("reading unknown3 failed!\n"); - return FALSE; - } - - /* salt */ - if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE, - &pInfo->salt.pbData, &pInfo->salt.cbData)) - { - ERR("reading salt failed!\n"); - return FALSE; - } - - /* cipher */ - if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE, - &pInfo->cipher.pbData, &pInfo->cipher.cbData)) - { - ERR("reading cipher failed!\n"); - return FALSE; - } - - /* fingerprint */ - if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE, - &pInfo->fingerprint.pbData, &pInfo->fingerprint.cbData)) - { - ERR("reading fingerprint failed!\n"); - return FALSE; - } - - /* allow structure size to be too big (since some applications - * will pad this up to 256 bytes, it seems) */ - if (index>size) - { - /* this is an impossible-to-reach test, but if the padding - * issue is ever understood, this may become more useful */ - ERR("loaded corrupt structure! (used %u expected %u)\n", - (unsigned int)index, (unsigned int)size); - status=FALSE; - } - - return status; -} - -/* perform sanity checks */ -static -BOOL valid_protect_data(struct protect_data_t * pInfo) -{ - BOOL status=TRUE; - - TRACE("called\n"); - - if (pInfo->count0 != 0x0001) - { - ERR("count0 != 0x0001 !\n"); - status=FALSE; - } - if (pInfo->count1 != 0x0001) - { - ERR("count0 != 0x0001 !\n"); - status=FALSE; - } - if (pInfo->null0 != 0x0000) - { - ERR("null0 != 0x0000 !\n"); - status=FALSE; - } - if (pInfo->null1 != 0x0000) - { - ERR("null1 != 0x0000 !\n"); - status=FALSE; - } - /* since we have no idea what info0 is used for, and it seems - * rather constant, we can test for a Wine-specific magic string - * there to be reasonably sure we're using data created by the Wine - * implementation of CryptProtectData. - */ - if (pInfo->info0.cbData!=strlen(crypt_magic_str)+1 || - strcmp( (LPCSTR)pInfo->info0.pbData,crypt_magic_str) != 0) - { - ERR("info0 magic value not matched !\n"); - status=FALSE; - } - - if (!status) - { - ERR("unrecognized CryptProtectData block\n"); - } - - return status; -} - -static -void free_protect_data(struct protect_data_t * pInfo) -{ - TRACE("called\n"); - - if (!pInfo) return; - - if (pInfo->info0.pbData) - CryptMemFree(pInfo->info0.pbData); - if (pInfo->info1.pbData) - CryptMemFree(pInfo->info1.pbData); - if (pInfo->szDataDescr) - CryptMemFree(pInfo->szDataDescr); - if (pInfo->data0.pbData) - CryptMemFree(pInfo->data0.pbData); - if (pInfo->salt.pbData) - CryptMemFree(pInfo->salt.pbData); - if (pInfo->cipher.pbData) - CryptMemFree(pInfo->cipher.pbData); - if (pInfo->fingerprint.pbData) - CryptMemFree(pInfo->fingerprint.pbData); -} - -/* copies a string into a data blob */ -static -BYTE * convert_str_to_blob(char* str, DATA_BLOB* blob) -{ - if (!str || !blob) return NULL; - - blob->cbData=strlen(str)+1; - if (!(blob->pbData=CryptMemAlloc(blob->cbData))) - { - blob->cbData=0; - } - else { - strcpy((LPSTR)blob->pbData, str); - } - - return blob->pbData; -} - -/* - * Populates everything except "cipher" and "fingerprint". - */ -static -BOOL fill_protect_data(struct protect_data_t * pInfo, LPCWSTR szDataDescr, - HCRYPTPROV hProv) -{ - DWORD dwStrLen; - - TRACE("called\n"); - - if (!pInfo) return FALSE; - - dwStrLen=lstrlenW(szDataDescr); - - memset(pInfo,0,sizeof(*pInfo)); - - pInfo->count0=0x0001; - - convert_str_to_blob((char*)crypt_magic_str,&pInfo->info0); - - pInfo->count1=0x0001; - - convert_str_to_blob((char*)crypt_magic_str,&pInfo->info1); - - pInfo->null0=0x0000; - - if ((pInfo->szDataDescr=CryptMemAlloc((dwStrLen+1)*sizeof(WCHAR)))) - { - memcpy(pInfo->szDataDescr,szDataDescr,(dwStrLen+1)*sizeof(WCHAR)); - } - - pInfo->unknown0=0x0000; - pInfo->unknown1=0x0000; - - convert_str_to_blob((char*)crypt_magic_str,&pInfo->data0); - - pInfo->null1=0x0000; - pInfo->unknown2=0x0000; - pInfo->unknown3=0x0000; - - /* allocate memory to hold a salt */ - pInfo->salt.cbData=CRYPT32_PROTECTDATA_SALT_LEN; - if ((pInfo->salt.pbData=CryptMemAlloc(pInfo->salt.cbData))) - { - /* generate random salt */ - if (!CryptGenRandom(hProv, pInfo->salt.cbData, pInfo->salt.pbData)) - { - ERR("CryptGenRandom\n"); - free_protect_data(pInfo); - return FALSE; - } - } - - /* debug: show our salt */ - TRACE_DATA_BLOB(&pInfo->salt); - - pInfo->cipher.cbData=0; - pInfo->cipher.pbData=NULL; - - pInfo->fingerprint.cbData=0; - pInfo->fingerprint.pbData=NULL; - - /* check all the allocations at once */ - if (!pInfo->info0.pbData || - !pInfo->info1.pbData || - !pInfo->szDataDescr || - !pInfo->data0.pbData || - !pInfo->salt.pbData - ) - { - ERR("could not allocate protect_data structures\n"); - free_protect_data(pInfo); - return FALSE; - } - - return TRUE; -} - -static -BOOL convert_hash_to_blob(HCRYPTHASH hHash, DATA_BLOB * blob) -{ - DWORD dwSize; - - TRACE("called\n"); - - if (!blob) return FALSE; - - dwSize=sizeof(DWORD); - if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&blob->cbData, - &dwSize, 0)) - { - ERR("failed to get hash size\n"); - return FALSE; - } - - if (!(blob->pbData=CryptMemAlloc(blob->cbData))) - { - ERR("failed to allocate blob memory\n"); - return FALSE; - } - - dwSize=blob->cbData; - if (!CryptGetHashParam(hHash, HP_HASHVAL, blob->pbData, &dwSize, 0)) - { - ERR("failed to get hash value\n"); - CryptMemFree(blob->pbData); - blob->pbData=NULL; - blob->cbData=0; - return FALSE; - } - - return TRUE; -} - -/* test that a given hash matches an exported-to-blob hash value */ -static -BOOL hash_matches_blob(HCRYPTHASH hHash, DATA_BLOB * two) -{ - BOOL rc = FALSE; - DATA_BLOB one; - - if (!two || !two->pbData) return FALSE; - - if (!convert_hash_to_blob(hHash,&one)) { - return FALSE; - } - - if ( one.cbData == two->cbData && - memcmp( one.pbData, two->pbData, one.cbData ) == 0 ) - { - rc = TRUE; - } - - CryptMemFree(one.pbData); - return rc; -} - -/* create an encryption key from a given salt and optional entropy */ -static -BOOL load_encryption_key(HCRYPTPROV hProv, DATA_BLOB * salt, - DATA_BLOB * pOptionalEntropy, HCRYPTKEY * phKey) -{ - BOOL rc = TRUE; - HCRYPTHASH hSaltHash; - char * szUsername = NULL; - DWORD dwUsernameLen; - DWORD dwError; - - /* create hash for salt */ - if (!salt || !phKey || - !CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hSaltHash)) - { - ERR("CryptCreateHash\n"); - return FALSE; - } - - /* This should be the "logon credentials" instead of username */ - dwError=GetLastError(); - dwUsernameLen = 0; - if (!GetUserNameA(NULL,&dwUsernameLen) && - GetLastError()==ERROR_MORE_DATA && dwUsernameLen && - (szUsername = CryptMemAlloc(dwUsernameLen))) - { - szUsername[0]='\0'; - GetUserNameA( szUsername, &dwUsernameLen ); - } - SetLastError(dwError); - - /* salt the hash with: - * - the user id - * - an "internal secret" - * - randomness (from the salt) - * - user-supplied entropy - */ - if ((szUsername && !CryptHashData(hSaltHash,(LPBYTE)szUsername,dwUsernameLen,0)) || - !CryptHashData(hSaltHash,crypt32_protectdata_secret, - sizeof(crypt32_protectdata_secret)-1,0) || - !CryptHashData(hSaltHash,salt->pbData,salt->cbData,0) || - (pOptionalEntropy && !CryptHashData(hSaltHash, - pOptionalEntropy->pbData, - pOptionalEntropy->cbData,0))) - { - ERR("CryptHashData\n"); - rc = FALSE; - } - - /* produce a symmetric key */ - if (rc && !CryptDeriveKey(hProv,CRYPT32_PROTECTDATA_KEY_CALG, - hSaltHash,CRYPT_EXPORTABLE,phKey)) - { - ERR("CryptDeriveKey\n"); - rc = FALSE; - } - - /* clean up */ - CryptDestroyHash(hSaltHash); - if (szUsername) CryptMemFree(szUsername); - - return rc; -} - -/* debugging tool to print the structures of a ProtectData call */ -static void -report(DATA_BLOB* pDataIn, DATA_BLOB* pOptionalEntropy, - CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags) -{ - TRACE("pPromptStruct: %p\n", pPromptStruct); - if (pPromptStruct) - { - TRACE(" cbSize: 0x%x\n",(unsigned int)pPromptStruct->cbSize); - TRACE(" dwPromptFlags: 0x%x\n",(unsigned int)pPromptStruct->dwPromptFlags); - TRACE(" hwndApp: %p\n", pPromptStruct->hwndApp); - TRACE(" szPrompt: %p %s\n", - pPromptStruct->szPrompt, - pPromptStruct->szPrompt ? debugstr_w(pPromptStruct->szPrompt) - : ""); - } - TRACE("dwFlags: 0x%04x\n",(unsigned int)dwFlags); - TRACE_DATA_BLOB(pDataIn); - if (pOptionalEntropy) - { - TRACE_DATA_BLOB(pOptionalEntropy); - TRACE(" %s\n",debugstr_an((LPCSTR)pOptionalEntropy->pbData,pOptionalEntropy->cbData)); - } - -} - - -/*************************************************************************** - * CryptProtectData [CRYPT32.@] - * - * Generate Cipher data from given Plain and Entropy data. - * - * PARAMS - * pDataIn [I] Plain data to be enciphered - * szDataDescr [I] Optional Unicode string describing the Plain data - * pOptionalEntropy [I] Optional entropy data to adjust cipher, can be NULL - * pvReserved [I] Reserved, must be NULL - * pPromptStruct [I] Structure describing if/how to prompt during ciphering - * dwFlags [I] Flags describing options to the ciphering - * pDataOut [O] Resulting Cipher data, for calls to CryptUnprotectData - * - * RETURNS - * TRUE If a Cipher was generated. - * FALSE If something failed and no Cipher is available. - * - * FIXME - * The true Windows encryption and keying mechanisms are unknown. - * - * dwFlags and pPromptStruct are currently ignored. - * - * NOTES - * Memory allocated in pDataOut must be freed with LocalFree. - * - */ -BOOL WINAPI CryptProtectData(DATA_BLOB* pDataIn, - LPCWSTR szDataDescr, - DATA_BLOB* pOptionalEntropy, - PVOID pvReserved, - CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, - DWORD dwFlags, - DATA_BLOB* pDataOut) -{ - BOOL rc = FALSE; - - HCRYPTPROV hProv; - struct protect_data_t protect_data; - HCRYPTHASH hHash; - HCRYPTKEY hKey; - DWORD dwLength; - - TRACE("called\n"); - - SetLastError(ERROR_SUCCESS); - - if (!pDataIn || !pDataOut) - { - SetLastError(ERROR_INVALID_PARAMETER); - goto finished; - } - - /* debug: show our arguments */ - report(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags); - TRACE("\tszDataDescr: %p %s\n", szDataDescr, - szDataDescr ? debugstr_w(szDataDescr) : ""); - - /* Windows appears to create an empty szDataDescr instead of maintaining - * a NULL */ - if (!szDataDescr) - szDataDescr=(WCHAR[]){'\0'}; - - /* get crypt context */ - if (!CryptAcquireContextW(&hProv,NULL,NULL,CRYPT32_PROTECTDATA_PROV,CRYPT_VERIFYCONTEXT)) - { - ERR("CryptAcquireContextW failed\n"); - goto finished; - } - - /* populate our structure */ - if (!fill_protect_data(&protect_data,szDataDescr,hProv)) - { - ERR("fill_protect_data\n"); - goto free_context; - } - - /* load key */ - if (!load_encryption_key(hProv,&protect_data.salt,pOptionalEntropy,&hKey)) - { - goto free_protect_data; - } - - /* create a hash for the encryption validation */ - if (!CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hHash)) - { - ERR("CryptCreateHash\n"); - goto free_key; - } - - /* calculate storage required */ - dwLength=pDataIn->cbData; - if (CryptEncrypt(hKey, 0, TRUE, 0, pDataIn->pbData, &dwLength, 0) || - GetLastError()!=ERROR_MORE_DATA) - { - ERR("CryptEncrypt\n"); - goto free_hash; - } - TRACE("required encrypted storage: %u\n",(unsigned int)dwLength); - - /* copy plain text into cipher area for CryptEncrypt call */ - protect_data.cipher.cbData=dwLength; - if (!(protect_data.cipher.pbData=CryptMemAlloc( - protect_data.cipher.cbData))) - { - ERR("CryptMemAlloc\n"); - goto free_hash; - } - memcpy(protect_data.cipher.pbData,pDataIn->pbData,pDataIn->cbData); - - /* encrypt! */ - dwLength=pDataIn->cbData; - if (!CryptEncrypt(hKey, hHash, TRUE, 0, protect_data.cipher.pbData, - &dwLength, protect_data.cipher.cbData)) - { - ERR("CryptEncrypt %u\n",(unsigned int)GetLastError()); - goto free_hash; - } - protect_data.cipher.cbData=dwLength; - - /* debug: show the cipher */ - TRACE_DATA_BLOB(&protect_data.cipher); - - /* attach our fingerprint */ - if (!convert_hash_to_blob(hHash, &protect_data.fingerprint)) - { - ERR("convert_hash_to_blob\n"); - goto free_hash; - } - - /* serialize into an opaque blob */ - if (!serialize(&protect_data, pDataOut)) - { - ERR("serialize\n"); - goto free_hash; - } - - /* success! */ - rc=TRUE; - -free_hash: - CryptDestroyHash(hHash); -free_key: - CryptDestroyKey(hKey); -free_protect_data: - free_protect_data(&protect_data); -free_context: - CryptReleaseContext(hProv,0); -finished: - /* If some error occurred, and no error code was set, force one. */ - if (!rc && GetLastError()==ERROR_SUCCESS) - { - SetLastError(ERROR_INVALID_DATA); - } - - if (rc) - { - SetLastError(ERROR_SUCCESS); - - TRACE_DATA_BLOB(pDataOut); - } - - TRACE("returning %s\n", rc ? "ok" : "FAIL"); - - return rc; -} - - -/*************************************************************************** - * CryptUnprotectData [CRYPT32.@] - * - * Generate Plain data and Description from given Cipher and Entropy data. - * - * PARAMS - * pDataIn [I] Cipher data to be decoded - * ppszDataDescr [O] Optional Unicode string describing the Plain data - * pOptionalEntropy [I] Optional entropy data to adjust cipher, can be NULL - * pvReserved [I] Reserved, must be NULL - * pPromptStruct [I] Structure describing if/how to prompt during decoding - * dwFlags [I] Flags describing options to the decoding - * pDataOut [O] Resulting Plain data, from calls to CryptProtectData - * - * RETURNS - * TRUE If a Plain was generated. - * FALSE If something failed and no Plain is available. - * - * FIXME - * The true Windows encryption and keying mechanisms are unknown. - * - * dwFlags and pPromptStruct are currently ignored. - * - * NOTES - * Memory allocated in pDataOut and non-NULL ppszDataDescr must be freed - * with LocalFree. - * - */ -BOOL WINAPI CryptUnprotectData(DATA_BLOB* pDataIn, - LPWSTR * ppszDataDescr, - DATA_BLOB* pOptionalEntropy, - PVOID pvReserved, - CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, - DWORD dwFlags, - DATA_BLOB* pDataOut) -{ - BOOL rc = FALSE; - - HCRYPTPROV hProv; - struct protect_data_t protect_data; - HCRYPTHASH hHash; - HCRYPTKEY hKey; - DWORD dwLength; - - const char * announce_bad_opaque_data = "CryptUnprotectData received a DATA_BLOB that seems to have NOT been generated by Wine. Please enable tracing ('export WINEDEBUG=crypt') to see details."; - - TRACE("called\n"); - - SetLastError(ERROR_SUCCESS); - - if (!pDataIn || !pDataOut) - { - SetLastError(ERROR_INVALID_PARAMETER); - goto finished; - } - - /* debug: show our arguments */ - report(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags); - TRACE("\tppszDataDescr: %p\n", ppszDataDescr); - - /* take apart the opaque blob */ - if (!unserialize(pDataIn, &protect_data)) - { - SetLastError(ERROR_INVALID_DATA); - FIXME("%s\n",announce_bad_opaque_data); - goto finished; - } - - /* perform basic validation on the resulting structure */ - if (!valid_protect_data(&protect_data)) - { - SetLastError(ERROR_INVALID_DATA); - FIXME("%s\n",announce_bad_opaque_data); - goto free_protect_data; - } - - /* get a crypt context */ - if (!CryptAcquireContextW(&hProv,NULL,NULL,CRYPT32_PROTECTDATA_PROV,CRYPT_VERIFYCONTEXT)) - { - ERR("CryptAcquireContextW failed\n"); - goto free_protect_data; - } - - /* load key */ - if (!load_encryption_key(hProv,&protect_data.salt,pOptionalEntropy,&hKey)) - { - goto free_context; - } - - /* create a hash for the decryption validation */ - if (!CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hHash)) - { - ERR("CryptCreateHash\n"); - goto free_key; - } - - /* prepare for plaintext */ - pDataOut->cbData=protect_data.cipher.cbData; - if (!(pDataOut->pbData=LocalAlloc( LPTR, pDataOut->cbData))) - { - ERR("CryptMemAlloc\n"); - goto free_hash; - } - memcpy(pDataOut->pbData,protect_data.cipher.pbData,protect_data.cipher.cbData); - - /* decrypt! */ - if (!CryptDecrypt(hKey, hHash, TRUE, 0, pDataOut->pbData, - &pDataOut->cbData) || - /* check the hash fingerprint */ - pDataOut->cbData > protect_data.cipher.cbData || - !hash_matches_blob(hHash, &protect_data.fingerprint)) - { - SetLastError(ERROR_INVALID_DATA); - - LocalFree( pDataOut->pbData ); - pDataOut->pbData = NULL; - pDataOut->cbData = 0; - - goto free_hash; - } - - /* Copy out the description */ - dwLength = (lstrlenW(protect_data.szDataDescr)+1) * sizeof(WCHAR); - if (ppszDataDescr) - { - if (!(*ppszDataDescr = LocalAlloc(LPTR,dwLength))) - { - ERR("LocalAlloc (ppszDataDescr)\n"); - goto free_hash; - } - else { - memcpy(*ppszDataDescr,protect_data.szDataDescr,dwLength); - } - } - - /* success! */ - rc = TRUE; - -free_hash: - CryptDestroyHash(hHash); -free_key: - CryptDestroyKey(hKey); -free_context: - CryptReleaseContext(hProv,0); -free_protect_data: - free_protect_data(&protect_data); -finished: - /* If some error occurred, and no error code was set, force one. */ - if (!rc && GetLastError()==ERROR_SUCCESS) - { - SetLastError(ERROR_INVALID_DATA); - } - - if (rc) { - SetLastError(ERROR_SUCCESS); - - if (ppszDataDescr) - { - TRACE("szDataDescr: %s\n",debugstr_w(*ppszDataDescr)); - } - TRACE_DATA_BLOB(pDataOut); - } - - TRACE("returning %s\n", rc ? "ok" : "FAIL"); - - return rc; -}