From 514da7876a9db63a6bbba277971522dadc294836 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Thu, 27 Sep 2007 13:49:16 -0700 Subject: [PATCH] Implement CertSaveStore --- dlls/crypt32/store.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 252 insertions(+), 2 deletions(-) diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c index 57a7804..6a71b2e 100644 --- a/dlls/crypt32/store.c +++ b/dlls/crypt32/store.c @@ -788,12 +788,262 @@ HCERTSTORE WINAPI CertOpenSystemStoreW(H CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol); } +static BOOL CRYPT_SavePKCSToMem(HCERTSTORE store, + DWORD dwMsgAndCertEncodingType, void *handle) +{ + CERT_BLOB *blob = (CERT_BLOB *)handle; + CRYPT_SIGNED_INFO signedInfo = { 0 }; + PCCERT_CONTEXT cert = NULL; + PCCRL_CONTEXT crl = NULL; + DWORD size; + BOOL ret = TRUE; + + TRACE("(%d, %p)\n", blob->pbData ? blob->cbData : 0, blob->pbData); + + do { + cert = CertEnumCertificatesInStore(store, cert); + if (cert) + signedInfo.cCertEncoded++; + } while (cert); + if (signedInfo.cCertEncoded) + { + signedInfo.rgCertEncoded = CryptMemAlloc( + signedInfo.cCertEncoded * sizeof(CERT_BLOB)); + if (!signedInfo.rgCertEncoded) + { + SetLastError(ERROR_OUTOFMEMORY); + ret = FALSE; + } + else + { + DWORD i = 0; + + do { + cert = CertEnumCertificatesInStore(store, cert); + if (cert) + { + signedInfo.rgCertEncoded[i].cbData = cert->cbCertEncoded; + signedInfo.rgCertEncoded[i].pbData = cert->pbCertEncoded; + i++; + } + } while (cert); + } + } + + do { + crl = CertEnumCRLsInStore(store, crl); + if (crl) + signedInfo.cCrlEncoded++; + } while (crl); + if (signedInfo.cCrlEncoded) + { + signedInfo.rgCrlEncoded = CryptMemAlloc( + signedInfo.cCrlEncoded * sizeof(CERT_BLOB)); + if (!signedInfo.rgCrlEncoded) + { + SetLastError(ERROR_OUTOFMEMORY); + ret = FALSE; + } + else + { + DWORD i = 0; + + do { + crl = CertEnumCRLsInStore(store, crl); + if (crl) + { + signedInfo.rgCrlEncoded[i].cbData = crl->cbCrlEncoded; + signedInfo.rgCrlEncoded[i].pbData = crl->pbCrlEncoded; + i++; + } + } while (crl); + } + } + if (ret) + { + ret = CRYPT_AsnEncodePKCSSignedInfo(&signedInfo, NULL, &size); + if (ret) + { + if (!blob->pbData) + blob->cbData = size; + else if (blob->cbData < size) + { + blob->cbData = size; + SetLastError(ERROR_MORE_DATA); + ret = FALSE; + } + else + { + blob->cbData = size; + ret = CRYPT_AsnEncodePKCSSignedInfo(&signedInfo, blob->pbData, + &blob->cbData); + } + } + } + CryptMemFree(signedInfo.rgCertEncoded); + CryptMemFree(signedInfo.rgCrlEncoded); + TRACE("returning %d\n", ret); + return ret; +} + +static BOOL CRYPT_SavePKCSToFile(HCERTSTORE store, + DWORD dwMsgAndCertEncodingType, void *handle) +{ + CERT_BLOB blob = { 0, NULL }; + BOOL ret; + + TRACE("(%p)\n", handle); + + ret = CRYPT_SavePKCSToMem(store, dwMsgAndCertEncodingType, &blob); + if (ret) + { + blob.pbData = CryptMemAlloc(blob.cbData); + if (blob.pbData) + { + ret = CRYPT_SavePKCSToMem(store, dwMsgAndCertEncodingType, &blob); + if (ret) + ret = WriteFile((HANDLE)handle, blob.pbData, blob.cbData, + &blob.cbData, NULL); + } + else + { + SetLastError(ERROR_OUTOFMEMORY); + ret = FALSE; + } + } + TRACE("returning %d\n", ret); + return ret; +} + +static BOOL CRYPT_SaveSerializedToFile(HCERTSTORE store, + DWORD dwMsgAndCertEncodingType, void *handle) +{ + return CRYPT_WriteSerializedStoreToFile((HANDLE)handle, store); +} + +struct MemWrittenTracker +{ + DWORD cbData; + BYTE *pbData; + DWORD written; +}; + +/* handle is a pointer to a MemWrittenTracker. Assumes its pointer is valid. */ +static BOOL CRYPT_MemOutputFunc(void *handle, const void *buffer, DWORD size) +{ + struct MemWrittenTracker *tracker = (struct MemWrittenTracker *)handle; + BOOL ret; + + if (tracker->written + size > tracker->cbData) + { + SetLastError(ERROR_MORE_DATA); + /* Update written so caller can notify its caller of the required size + */ + tracker->written += size; + ret = FALSE; + } + else + { + memcpy(tracker->pbData + tracker->written, buffer, size); + tracker->written += size; + ret = TRUE; + } + return ret; +} + +static BOOL CRYPT_CountSerializedBytes(void *handle, const void *buffer, + DWORD size) +{ + *(DWORD *)handle += size; + return TRUE; +} + +static BOOL CRYPT_SaveSerializedToMem(HCERTSTORE store, + DWORD dwMsgAndCertEncodingType, void *handle) +{ + CERT_BLOB *blob = (CERT_BLOB *)handle; + DWORD size; + BOOL ret; + + ret = CRYPT_WriteSerializedStoreToStream(store, CRYPT_CountSerializedBytes, + &size); + if (ret) + { + if (!blob->pbData) + blob->cbData = size; + else if (blob->cbData < size) + { + SetLastError(ERROR_MORE_DATA); + blob->cbData = size; + ret = FALSE; + } + else + { + struct MemWrittenTracker tracker = { blob->cbData, blob->pbData, + 0 }; + + ret = CRYPT_WriteSerializedStoreToStream(store, CRYPT_MemOutputFunc, + &tracker); + if (!ret && GetLastError() == ERROR_MORE_DATA) + blob->cbData = tracker.written; + } + } + TRACE("returning %d\n", ret); + return ret; +} + BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType, DWORD dwSaveAs, DWORD dwSaveTo, void* pvSaveToPara, DWORD dwFlags) { - FIXME("(%p,%d,%d,%d,%p,%08x) stub!\n", hCertStore, + BOOL (*saveFunc)(HCERTSTORE, DWORD, void *); + void *handle; + BOOL ret; + + TRACE("(%p, %08x, %d, %d, %p, %08x)\n", hCertStore, dwMsgAndCertEncodingType, dwSaveAs, dwSaveTo, pvSaveToPara, dwFlags); - return TRUE; + + switch (dwSaveAs) + { + case CERT_STORE_SAVE_AS_STORE: + case CERT_STORE_SAVE_AS_PKCS7: + break; + default: + WARN("unimplemented for %d\n", dwSaveAs); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + switch (dwSaveTo) + { + case CERT_STORE_SAVE_TO_FILE: + handle = (HANDLE)pvSaveToPara; + saveFunc = dwSaveAs == CERT_STORE_SAVE_AS_STORE ? + CRYPT_SaveSerializedToFile : CRYPT_SavePKCSToFile; + break; + case CERT_STORE_SAVE_TO_FILENAME_A: + handle = CreateFileA((LPCSTR)pvSaveToPara, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, 0, NULL); + saveFunc = dwSaveAs == CERT_STORE_SAVE_AS_STORE ? + CRYPT_SaveSerializedToFile : CRYPT_SavePKCSToFile; + break; + case CERT_STORE_SAVE_TO_FILENAME_W: + handle = CreateFileW((LPCWSTR)pvSaveToPara, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, 0, NULL); + saveFunc = dwSaveAs == CERT_STORE_SAVE_AS_STORE ? + CRYPT_SaveSerializedToFile : CRYPT_SavePKCSToFile; + break; + case CERT_STORE_SAVE_TO_MEMORY: + handle = pvSaveToPara; + saveFunc = dwSaveAs == CERT_STORE_SAVE_AS_STORE ? + CRYPT_SaveSerializedToMem : CRYPT_SavePKCSToMem; + break; + default: + WARN("unimplemented for %d\n", dwSaveTo); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + ret = saveFunc(hCertStore, dwMsgAndCertEncodingType, handle); + TRACE("returning %d\n", ret); + return ret; } #define CertContext_CopyProperties(to, from) \ -- 1.4.1