static void test_cryptAllocate(void) { LPVOID buf; buf = CryptMemAlloc(0); ok(buf != NULL, "CryptMemAlloc failed: %08x\n", GetLastError()); CryptMemFree(buf); /* CryptMemRealloc(NULL, 0) fails pre-Vista */ buf = CryptMemAlloc(0); buf = CryptMemRealloc(buf, 1); ok(buf != NULL, "CryptMemRealloc failed: %08x\n", GetLastError()); CryptMemFree(buf); }
static BOOL CRYPT_ValueToRDN(DWORD dwCertEncodingType, PCERT_NAME_INFO info, PCCRYPT_OID_INFO keyOID, struct X500TokenW *value, LPCWSTR *ppszError) { BOOL ret = FALSE; TRACE("OID %s, value %s\n", debugstr_a(keyOID->pszOID), debugstr_wn(value->start, value->end - value->start)); if (!info->rgRDN) info->rgRDN = CryptMemAlloc(sizeof(CERT_RDN)); else info->rgRDN = CryptMemRealloc(info->rgRDN, (info->cRDN + 1) * sizeof(CERT_RDN)); if (info->rgRDN) { /* FIXME: support multiple RDN attrs */ info->rgRDN[info->cRDN].rgRDNAttr = CryptMemAlloc(sizeof(CERT_RDN_ATTR)); if (info->rgRDN[info->cRDN].rgRDNAttr) { static const DWORD defaultTypes[] = { CERT_RDN_PRINTABLE_STRING, CERT_RDN_BMP_STRING, 0 }; const DWORD *types; info->rgRDN[info->cRDN].cRDNAttr = 1; info->rgRDN[info->cRDN].rgRDNAttr[0].pszObjId = (LPSTR)keyOID->pszOID; info->rgRDN[info->cRDN].rgRDNAttr[0].dwValueType = CERT_RDN_ENCODED_BLOB; if (keyOID->ExtraInfo.cbData) types = (const DWORD *)keyOID->ExtraInfo.pbData; else types = defaultTypes; /* Remove surrounding quotes */ if (value->start[0] == '"') { value->start++; value->end--; } ret = CRYPT_EncodeValue(dwCertEncodingType, value, &info->rgRDN[info->cRDN].rgRDNAttr[0].Value, types, ppszError); } else SetLastError(ERROR_OUTOFMEMORY); info->cRDN++; } else SetLastError(ERROR_OUTOFMEMORY); return ret; }
BOOL WINAPI CertStrToNameA(DWORD dwCertEncodingType, LPCSTR pszX500, DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded, LPCSTR *ppszError) { LPWSTR x500, errorStr; BOOL ret; int len; TRACE("(%08lx, %s, %08lx, %p, %p, %p, %p)\n", dwCertEncodingType, debugstr_a(pszX500), dwStrType, pvReserved, pbEncoded, pcbEncoded, ppszError); len = MultiByteToWideChar(CP_ACP, 0, pszX500, -1, NULL, 0); x500 = CryptMemAlloc(len * sizeof(WCHAR)); if (x500) { MultiByteToWideChar(CP_ACP, 0, pszX500, -1, x500, len); ret = CertStrToNameW(dwCertEncodingType, x500, dwStrType, pvReserved, pbEncoded, pcbEncoded, ppszError ? (LPCWSTR *)&errorStr : NULL); if (ppszError) { DWORD i; *ppszError = pszX500; for (i = 0; i < errorStr - x500; i++) CharNextA(*ppszError); } CryptMemFree(x500); } else ret = FALSE; return ret; }
static BOOL CRYPT_ReadBlobFromFile(LPCWSTR fileName, PCERT_BLOB blob) { BOOL ret = FALSE; HANDLE file; TRACE("%s\n", debugstr_w(fileName)); file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (file != INVALID_HANDLE_VALUE) { ret = TRUE; blob->cbData = GetFileSize(file, NULL); if (blob->cbData) { blob->pbData = CryptMemAlloc(blob->cbData); if (blob->pbData) { DWORD read; ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL); } } CloseHandle(file); } TRACE("returning %d\n", ret); return ret; }
static BOOL CRYPT_SerializeContextsToStream(SerializedOutputFunc output, void *handle, const WINE_CONTEXT_INTERFACE *contextInterface, HCERTSTORE store) { const void *context = NULL; BOOL ret; do { context = contextInterface->enumContextsInStore(store, context); if (context) { 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 = output(handle, buf, size); } CryptMemFree(buf); } else ret = TRUE; } while (ret && context != NULL); if (context) contextInterface->free(context); return ret; }
context_t *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *vtbl, WINECRYPT_CERTSTORE *store) { context_t *context; context = CryptMemAlloc(sizeof(context_t) + contextSize); if (!context) return NULL; context->properties = ContextPropertyList_Create(); if (!context->properties) { CryptMemFree(context); return NULL; } context->vtbl = vtbl; context->ref = 1; context->linked = NULL; store->vtbl->addref(store); context->store = store; TRACE("returning %p\n", context); return context; }
/* Opens path, which must be a directory, and imports certificates from every * file in the directory into store. * Returns TRUE if any certificates were successfully imported. */ static BOOL import_certs_from_dir(LPCSTR path, HCERTSTORE store) { BOOL ret = FALSE; DIR *dir; TRACE("(%s, %p)\n", debugstr_a(path), store); dir = opendir(path); if (dir) { size_t bufsize = strlen(path) + 1 + PATH_MAX + 1; char *filebuf = CryptMemAlloc(bufsize); if (filebuf) { struct dirent *entry; while ((entry = readdir(dir))) { if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) { snprintf(filebuf, bufsize, "%s/%s", path, entry->d_name); if (import_certs_from_path(filebuf, store, FALSE) && !ret) ret = TRUE; } } closedir(dir); CryptMemFree(filebuf); } } 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, blob.pbData, blob.cbData, &blob.cbData, NULL); } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } TRACE("returning %d\n", ret); return ret; }
static BOOL check_buffer_resize(char **ptr_buf, size_t *buf_size, size_t check_size) { if (check_size > *buf_size) { *buf_size = check_size; if (*ptr_buf) { char *realloc_buf = CryptMemRealloc(*ptr_buf, *buf_size); if (!realloc_buf) return FALSE; *ptr_buf = realloc_buf; } else { *ptr_buf = CryptMemAlloc(*buf_size); if (!*ptr_buf) return FALSE; } } return TRUE; }
static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) { int len; PWINECRYPT_CERTSTORE ret = NULL; TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, debugstr_a(pvPara)); if (!pvPara) { SetLastError(ERROR_FILE_NOT_FOUND); return NULL; } len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0); if (len) { LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR)); if (storeName) { MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len); ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName); CryptMemFree(storeName); } } return ret; }
BOOL WINAPI CertStrToNameA(DWORD dwCertEncodingType, LPCSTR pszX500, DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded, LPCSTR *ppszError) { BOOL ret; int len; TRACE("(%08x, %s, %08x, %p, %p, %p, %p)\n", dwCertEncodingType, debugstr_a(pszX500), dwStrType, pvReserved, pbEncoded, pcbEncoded, ppszError); len = MultiByteToWideChar(CP_ACP, 0, pszX500, -1, NULL, 0); if (len) { LPWSTR x500, errorStr; if ((x500 = CryptMemAlloc(len * sizeof(WCHAR)))) { MultiByteToWideChar(CP_ACP, 0, pszX500, -1, x500, len); ret = CertStrToNameW(dwCertEncodingType, x500, dwStrType, pvReserved, pbEncoded, pcbEncoded, ppszError ? (LPCWSTR *)&errorStr : NULL); if (ppszError) { if (!ret) { DWORD i; *ppszError = pszX500; for (i = 0; i < errorStr - x500; i++) *ppszError = CharNextA(*ppszError); } else *ppszError = NULL; } CryptMemFree(x500); } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } else { SetLastError(CRYPT_E_INVALID_X500_STRING); if (ppszError) *ppszError = pszX500; ret = FALSE; } return ret; }
/* Encodes the string represented by value as the string type type into the * CERT_NAME_BLOB output. If there is an error and ppszError is not NULL, * *ppszError is set to the first failing character. If there is no error, * output's pbData must be freed with LocalFree. */ static BOOL CRYPT_EncodeValueWithType(DWORD dwCertEncodingType, const struct X500TokenW *value, PCERT_NAME_BLOB output, DWORD type, LPCWSTR *ppszError) { CERT_NAME_VALUE nameValue = { type, { 0, NULL } }; BOOL ret = TRUE; if (value->end > value->start) { nameValue.Value.pbData = CryptMemAlloc((value->end - value->start) * sizeof(WCHAR)); if (!nameValue.Value.pbData) { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } if (ret) { if (value->end > value->start) { DWORD i; LPWSTR ptr = (LPWSTR)nameValue.Value.pbData; for (i = 0; i < value->end - value->start; i++) { *ptr++ = value->start[i]; if (value->start[i] == '"') i++; } nameValue.Value.cbData = (LPBYTE)ptr - nameValue.Value.pbData; } ret = CryptEncodeObjectEx(dwCertEncodingType, X509_UNICODE_NAME_VALUE, &nameValue, CRYPT_ENCODE_ALLOC_FLAG, NULL, &output->pbData, &output->cbData); if (!ret && ppszError) { if (type == CERT_RDN_NUMERIC_STRING && GetLastError() == CRYPT_E_INVALID_NUMERIC_STRING) *ppszError = value->start + output->cbData; else if (type == CERT_RDN_PRINTABLE_STRING && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING) *ppszError = value->start + output->cbData; else if (type == CERT_RDN_IA5_STRING && GetLastError() == CRYPT_E_INVALID_IA5_STRING) *ppszError = value->start + output->cbData; } CryptMemFree(nameValue.Value.pbData); } return ret; }
/* Reads any base64-encoded certificates present in fp and adds them to store. * Returns TRUE if any certificates were successfully imported. */ static BOOL import_base64_certs_from_fp(FILE *fp, HCERTSTORE store) { char line[1024]; BOOL in_cert = FALSE; struct DynamicBuffer saved_cert = { 0, 0, NULL }; int num_certs = 0; TRACE("\n"); while (fgets(line, sizeof(line), fp)) { static const char header[] = "-----BEGIN CERTIFICATE-----"; static const char trailer[] = "-----END CERTIFICATE-----"; if (!strncmp(line, header, strlen(header))) { TRACE("begin new certificate\n"); in_cert = TRUE; reset_buffer(&saved_cert); } else if (!strncmp(line, trailer, strlen(trailer))) { DWORD size; TRACE("end of certificate, adding cert\n"); in_cert = FALSE; if (CryptStringToBinaryA((char *)saved_cert.data, saved_cert.used, CRYPT_STRING_BASE64, NULL, &size, NULL, NULL)) { LPBYTE buf = CryptMemAlloc(size); if (buf) { CryptStringToBinaryA((char *)saved_cert.data, saved_cert.used, CRYPT_STRING_BASE64, buf, &size, NULL, NULL); if (CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_NEW, NULL)) num_certs++; CryptMemFree(buf); } } } else if (in_cert) add_line_to_buffer(&saved_cert, line); } CryptMemFree(saved_cert.data); TRACE("Read %d certs\n", num_certs); return num_certs > 0; }
static BOOL CRYPT_ReadBlobFromFile(HANDLE file, PCERT_BLOB blob) { BOOL ret = TRUE; blob->cbData = GetFileSize(file, NULL); if (blob->cbData) { blob->pbData = CryptMemAlloc(blob->cbData); if (blob->pbData) { DWORD read; ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL); } } return ret; }
PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType, const BYTE* pbCrlEncoded, DWORD cbCrlEncoded) { PCRL_CONTEXT crl = NULL; BOOL ret; PCRL_INFO crlInfo = NULL; DWORD size = 0; TRACE("(%08x, %p, %d)\n", dwCertEncodingType, pbCrlEncoded, cbCrlEncoded); if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING) { SetLastError(E_INVALIDARG); return NULL; } ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED, pbCrlEncoded, cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &crlInfo, &size); if (ret) { BYTE *data = NULL; crl = Context_CreateDataContext(sizeof(CRL_CONTEXT)); if (!crl) goto end; data = CryptMemAlloc(cbCrlEncoded); if (!data) { CertFreeCRLContext(crl); crl = NULL; goto end; } memcpy(data, pbCrlEncoded, cbCrlEncoded); crl->dwCertEncodingType = dwCertEncodingType; crl->pbCrlEncoded = data; crl->cbCrlEncoded = cbCrlEncoded; crl->pCrlInfo = crlInfo; crl->hCertStore = 0; } end: return crl; }
static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) { PWINE_MEMSTORE store; TRACE("(%ld, %08x, %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, dwFlags, StoreTypeMem); store->hdr.closeStore = CRYPT_MemCloseStore; store->hdr.certs.addContext = CRYPT_MemAddCert; store->hdr.certs.enumContext = CRYPT_MemEnumCert; store->hdr.certs.deleteContext = CRYPT_MemDeleteCert; store->hdr.crls.addContext = CRYPT_MemAddCrl; store->hdr.crls.enumContext = CRYPT_MemEnumCrl; store->hdr.crls.deleteContext = CRYPT_MemDeleteCrl; store->hdr.ctls.addContext = CRYPT_MemAddCtl; store->hdr.ctls.enumContext = CRYPT_MemEnumCtl; store->hdr.ctls.deleteContext = CRYPT_MemDeleteCtl; store->hdr.control = CRYPT_MemControl; store->certs = ContextList_Create(pCertInterface, sizeof(CERT_CONTEXT)); store->crls = ContextList_Create(pCRLInterface, sizeof(CRL_CONTEXT)); store->ctls = ContextList_Create(pCTLInterface, sizeof(CTL_CONTEXT)); /* Mem store doesn't need crypto provider, so close it */ if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) CryptReleaseContext(hCryptProv, 0); } } return (PWINECRYPT_CERTSTORE)store; }
static void CRYPT_KeynameKeeperFromTokenW(struct KeynameKeeper *keeper, struct X500TokenW *key) { DWORD len = key->end - key->start; if (len > keeper->keyLen) { if (keeper->keyName == keeper->buf) keeper->keyName = CryptMemAlloc(len * sizeof(WCHAR)); else keeper->keyName = CryptMemRealloc(keeper->keyName, len * sizeof(WCHAR)); keeper->keyLen = len; } memcpy(keeper->keyName, key->start, (key->end - key->start) * sizeof(WCHAR)); keeper->keyName[len] = '\0'; TRACE("Keyname is %s\n", debugstr_w(keeper->keyName)); }
PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType, const BYTE* pbCrlEncoded, DWORD cbCrlEncoded) { crl_t *crl = NULL; BOOL ret; PCRL_INFO crlInfo = NULL; BYTE *data = NULL; DWORD size = 0; TRACE("(%08x, %p, %d)\n", dwCertEncodingType, pbCrlEncoded, cbCrlEncoded); if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING) { SetLastError(E_INVALIDARG); return NULL; } ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED, pbCrlEncoded, cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &crlInfo, &size); if (!ret) return NULL; crl = (crl_t*)Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, &empty_store); if (!crl) return NULL; data = CryptMemAlloc(cbCrlEncoded); if (!data) { Context_Release(&crl->base); return NULL; } memcpy(data, pbCrlEncoded, cbCrlEncoded); crl->ctx.dwCertEncodingType = dwCertEncodingType; crl->ctx.pbCrlEncoded = data; crl->ctx.cbCrlEncoded = cbCrlEncoded; crl->ctx.pCrlInfo = crlInfo; crl->ctx.hCertStore = &empty_store; return &crl->ctx; }
DWORD WINAPI CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara, LPSTR pszNameString, DWORD cchNameString) { DWORD ret; TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType, dwFlags, pvTypePara, pszNameString, cchNameString); if (pszNameString) { LPWSTR wideName; DWORD nameLen; nameLen = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0); wideName = CryptMemAlloc(nameLen * sizeof(WCHAR)); if (wideName) { CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, wideName, nameLen); nameLen = WideCharToMultiByte(CP_ACP, 0, wideName, nameLen, pszNameString, cchNameString, NULL, NULL); if (nameLen <= cchNameString) ret = nameLen; else { pszNameString[cchNameString - 1] = '\0'; ret = cchNameString; } CryptMemFree(wideName); } else { *pszNameString = '\0'; ret = 1; } } else ret = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0); return ret; }
BOOL CRYPT_SerializeContextsToReg(HKEY key, DWORD flags, 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, flags, hash, buf, size); } CryptMemFree(buf); } } else ret = TRUE; } while (ret && context != NULL); if (context) Context_Release(context_from_ptr(context)); return ret; }
static BOOL add_line_to_buffer(struct DynamicBuffer *buffer, LPCSTR line) { BOOL ret; if (buffer->used + strlen(line) + 1 > buffer->allocated) { if (!buffer->allocated) { buffer->data = CryptMemAlloc(INITIAL_CERT_BUFFER); if (buffer->data) { buffer->data[0] = 0; buffer->allocated = INITIAL_CERT_BUFFER; } } else { DWORD new_size = max(buffer->allocated * 2, buffer->used + strlen(line) + 1); buffer->data = CryptMemRealloc(buffer->data, new_size); if (buffer->data) buffer->allocated = new_size; } } if (buffer->data) { strcpy((char *)buffer->data + strlen((char *)buffer->data), line); /* Not strlen + 1, otherwise we'd count the NULL for every line's * addition (but we overwrite the previous NULL character.) Not an * overrun, we allocate strlen + 1 bytes above. */ buffer->used += strlen(line); ret = TRUE; } else ret = FALSE; return ret; }
context_t *Context_CreateLinkContext(unsigned int contextSize, context_t *linked, WINECRYPT_CERTSTORE *store) { context_t *context; TRACE("(%d, %p)\n", contextSize, linked); context = CryptMemAlloc(sizeof(context_t) + contextSize); if (!context) return NULL; memcpy(context_ptr(context), context_ptr(linked), contextSize); context->vtbl = linked->vtbl; context->ref = 1; context->linked = linked; context->properties = linked->properties; Context_AddRef(linked); store->vtbl->addref(store); context->store = store; TRACE("returning %p\n", context); return context; }
static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link) { crl_t *crl; if(use_link) { crl = (crl_t*)Context_CreateLinkContext(sizeof(CRL_CONTEXT), context, store); if(!crl) return NULL; }else { const crl_t *cloned = (const crl_t*)context; DWORD size = 0; BOOL res; crl = (crl_t*)Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, store); if(!crl) return NULL; Context_CopyProperties(&crl->ctx, &cloned->ctx); crl->ctx.dwCertEncodingType = cloned->ctx.dwCertEncodingType; crl->ctx.pbCrlEncoded = CryptMemAlloc(cloned->ctx.cbCrlEncoded); memcpy(crl->ctx.pbCrlEncoded, cloned->ctx.pbCrlEncoded, cloned->ctx.cbCrlEncoded); crl->ctx.cbCrlEncoded = cloned->ctx.cbCrlEncoded; /* FIXME: We don't need to decode the object here, we could just clone crl info. */ res = CryptDecodeObjectEx(crl->ctx.dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED, crl->ctx.pbCrlEncoded, crl->ctx.cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &crl->ctx.pCrlInfo, &size); if(!res) { CertFreeCRLContext(&crl->ctx); return NULL; } } crl->ctx.hCertStore = store; return &crl->base; }
static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg, DWORD dwSignerIndex) { CERT_INFO *certInfo = NULL; DWORD size; if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL, &size)) { certInfo = CryptMemAlloc(size); if (certInfo) { if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, certInfo, &size)) { CryptMemFree(certInfo); certInfo = NULL; } } } else SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE); return certInfo; }
static PWINECRYPT_CERTSTORE CRYPT_CreateFileStore(DWORD dwFlags, HCERTSTORE memStore, HANDLE file, DWORD type) { PWINECRYPT_CERTSTORE store = NULL; PWINE_FILESTOREINFO info = CryptMemAlloc(sizeof(WINE_FILESTOREINFO)); if (info) { CERT_STORE_PROV_INFO provInfo = { 0 }; info->dwOpenFlags = dwFlags; info->memStore = memStore; info->file = file; info->type = type; info->dirty = FALSE; provInfo.cbSize = sizeof(provInfo); provInfo.cStoreProvFunc = sizeof(fileProvFuncs) / sizeof(fileProvFuncs[0]); provInfo.rgpvStoreProvFunc = fileProvFuncs; provInfo.hStoreProv = info; store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo); } return store; }
static BOOL CRYPT_SavePKCSToMem(HCERTSTORE store, DWORD dwMsgAndCertEncodingType, void *handle) { CERT_BLOB *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_AsnEncodeCMSSignedInfo(&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_AsnEncodeCMSSignedInfo(&signedInfo, blob->pbData, &blob->cbData); } } } CryptMemFree(signedInfo.rgCertEncoded); CryptMemFree(signedInfo.rgCrlEncoded); TRACE("returning %d\n", ret); return ret; }
static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) { static const WCHAR fmt[] = { '%','s','\\','%','s',0 }; LPCWSTR storeName = pvPara; LPWSTR storePath; PWINECRYPT_CERTSTORE store = NULL; HKEY root; LPCWSTR base; TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, debugstr_w(pvPara)); if (!pvPara) { SetLastError(E_INVALIDARG); return NULL; } /* FIXME: In Windows, the root store (even the current user location) is * protected: adding to it or removing from it present a user interface, * and the keys are owned by the system process, not the current user. * Wine's registry doesn't implement access controls, so a similar * mechanism isn't possible yet. */ if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) == CERT_SYSTEM_STORE_LOCAL_MACHINE && !lstrcmpiW(storeName, rootW)) return CRYPT_RootOpenStore(hCryptProv, dwFlags); 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(E_INVALIDARG); 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 BOOL CRYPT_ReadSerializedStore(void *handle, read_serialized_func read_func, HCERTSTORE store) { BYTE fileHeaderBuf[sizeof(fileHeader)]; DWORD read; BOOL ret; /* Failure reading is non-critical, we'll leave the store empty */ ret = read_func(handle, fileHeaderBuf, sizeof(fileHeaderBuf), &read); if (ret) { if (!read) ; /* an empty file is okay */ else if (read != sizeof(fileHeaderBuf)) ret = FALSE; else if (!memcmp(fileHeaderBuf, fileHeader, read)) { WINE_CERT_PROP_HEADER propHdr; const void *context = NULL; const WINE_CONTEXT_INTERFACE *contextInterface = NULL; LPBYTE buf = NULL; DWORD bufSize = 0; do { ret = read_func(handle, &propHdr, sizeof(propHdr), &read); if (ret && read == sizeof(propHdr)) { if (contextInterface && context && (propHdr.propID == CERT_CERT_PROP_ID || propHdr.propID == CERT_CRL_PROP_ID || propHdr.propID == CERT_CTL_PROP_ID)) { /* We have a new context, so free the existing one */ contextInterface->free(context); } if (propHdr.cb > bufSize) { /* Not reusing realloc, because the old data aren't * needed any longer. */ CryptMemFree(buf); buf = CryptMemAlloc(propHdr.cb); bufSize = propHdr.cb; } if (!propHdr.cb) ; /* Property is empty, nothing to do */ else if (buf) { ret = read_func(handle, buf, propHdr.cb, &read); if (ret && read == propHdr.cb) { if (propHdr.propID == CERT_CERT_PROP_ID) { contextInterface = pCertInterface; ret = contextInterface->addEncodedToStore(store, X509_ASN_ENCODING, buf, read, CERT_STORE_ADD_NEW, &context); } else if (propHdr.propID == CERT_CRL_PROP_ID) { contextInterface = pCRLInterface; ret = contextInterface->addEncodedToStore(store, X509_ASN_ENCODING, buf, read, CERT_STORE_ADD_NEW, &context); } else if (propHdr.propID == CERT_CTL_PROP_ID) { contextInterface = pCTLInterface; ret = contextInterface->addEncodedToStore(store, X509_ASN_ENCODING, buf, read, CERT_STORE_ADD_NEW, &context); } else { if (!contextInterface) { WARN("prop id %d before a context id\n", propHdr.propID); ret = FALSE; } else ret = CRYPT_ReadContextProp( contextInterface, context, &propHdr, buf, read); } } } else ret = FALSE; } } while (ret && read > 0 && propHdr.cb); if (contextInterface && context) { /* Free the last context added */ contextInterface->free(context); } CryptMemFree(buf); ret = TRUE; } else ret = FALSE; } else ret = TRUE; return ret; }
static BOOL CRYPT_SerializeStoreElement(const void *context, const BYTE *encodedContext, DWORD cbEncodedContext, DWORD contextPropID, PCWINE_CONTEXT_INTERFACE contextInterface, DWORD dwFlags, BOOL omitHashes, BYTE *pbElement, DWORD *pcbElement) { BOOL ret; TRACE("(%p, %p, %08x, %d, %p, %p)\n", context, contextInterface, dwFlags, omitHashes, pbElement, pcbElement); if (context) { DWORD bytesNeeded = sizeof(WINE_CERT_PROP_HEADER) + cbEncodedContext; DWORD prop = 0; ret = TRUE; do { prop = contextInterface->enumProps(context, prop); if (prop && (!omitHashes || !IS_CERT_HASH_PROP_ID(prop))) { DWORD propSize = 0; ret = contextInterface->getProp(context, prop, NULL, &propSize); if (ret) bytesNeeded += sizeof(WINE_CERT_PROP_HEADER) + propSize; } } while (ret && prop != 0); if (!pbElement) { *pcbElement = bytesNeeded; ret = TRUE; } else if (*pcbElement < bytesNeeded) { *pcbElement = bytesNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else { PWINE_CERT_PROP_HEADER hdr; DWORD bufSize = 0; LPBYTE buf = NULL; prop = 0; do { prop = contextInterface->enumProps(context, prop); if (prop && (!omitHashes || !IS_CERT_HASH_PROP_ID(prop))) { DWORD propSize = 0; ret = contextInterface->getProp(context, prop, NULL, &propSize); if (ret) { if (bufSize < propSize) { if (buf) buf = CryptMemRealloc(buf, propSize); else buf = CryptMemAlloc(propSize); bufSize = propSize; } if (buf) { ret = contextInterface->getProp(context, prop, buf, &propSize); if (ret) { hdr = (PWINE_CERT_PROP_HEADER)pbElement; hdr->propID = prop; hdr->unknown = 1; hdr->cb = propSize; pbElement += sizeof(WINE_CERT_PROP_HEADER); if (propSize) { memcpy(pbElement, buf, propSize); pbElement += propSize; } } } else ret = FALSE; } } } while (ret && prop != 0); CryptMemFree(buf); hdr = (PWINE_CERT_PROP_HEADER)pbElement; hdr->propID = contextPropID; hdr->unknown = 1; hdr->cb = cbEncodedContext; memcpy(pbElement + sizeof(WINE_CERT_PROP_HEADER), encodedContext, cbEncodedContext); } } else ret = FALSE; return ret; }
static PWINECRYPT_CERTSTORE CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) { PWINECRYPT_CERTSTORE store = NULL; HCRYPTMSG msg = (HCRYPTMSG)pvPara; PWINECRYPT_CERTSTORE memStore; TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara); memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); if (memStore) { BOOL ret; DWORD size, count, i; size = sizeof(count); ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size); for (i = 0; ret && i < count; i++) { size = 0; ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size); if (ret) { LPBYTE buf = CryptMemAlloc(size); if (buf) { ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size); if (ret) ret = CertAddEncodedCertificateToStore(memStore, X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS, NULL); CryptMemFree(buf); } } } size = sizeof(count); ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size); for (i = 0; ret && i < count; i++) { size = 0; ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size); if (ret) { LPBYTE buf = CryptMemAlloc(size); if (buf) { ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size); if (ret) ret = CertAddEncodedCRLToStore(memStore, X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS, NULL); CryptMemFree(buf); } } } if (ret) { CERT_STORE_PROV_INFO provInfo = { 0 }; provInfo.cbSize = sizeof(provInfo); provInfo.cStoreProvFunc = sizeof(msgProvFuncs) / sizeof(msgProvFuncs[0]); provInfo.rgpvStoreProvFunc = msgProvFuncs; provInfo.hStoreProv = CryptMsgDuplicate(msg); store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo); /* Msg store doesn't need crypto provider, so close it */ if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) CryptReleaseContext(hCryptProv, 0); } else CertCloseStore(memStore, 0); } TRACE("returning %p\n", store); return store; }