BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext) { BOOL ret; TRACE("(%p)\n", pCtlContext); if (!pCtlContext) ret = TRUE; else if (!pCtlContext->hCertStore) { ret = TRUE; CertFreeCTLContext(pCtlContext); } else { PWINECRYPT_CERTSTORE hcs = (PWINECRYPT_CERTSTORE)pCtlContext->hCertStore; if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) ret = FALSE; else ret = hcs->ctls.deleteContext(hcs, (void *)pCtlContext); CertFreeCTLContext(pCtlContext); } return ret; }
static void testCTLProperties(void) { PCCTL_CONTEXT ctl; BOOL ret; DWORD propID, numProps, access, size; ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent)); if (!ctl) { skip("CertCreateCTLContext failed: %08x\n", GetLastError()); return; } /* No properties as yet */ propID = 0; numProps = 0; do { propID = CertEnumCTLContextProperties(ctl, propID); if (propID) numProps++; } while (propID != 0); ok(numProps == 0, "Expected 0 properties, got %d\n", numProps); /* An implicit property */ ret = CertGetCTLContextProperty(ctl, CERT_ACCESS_STATE_PROP_ID, NULL, &size); ok(ret || broken(GetLastError() == CRYPT_E_NOT_FOUND /* some win98 */), "CertGetCTLContextProperty failed: %08x\n", GetLastError()); ret = CertGetCTLContextProperty(ctl, CERT_ACCESS_STATE_PROP_ID, &access, &size); ok(ret || broken(GetLastError() == CRYPT_E_NOT_FOUND /* some win98 */), "CertGetCTLContextProperty failed: %08x\n", GetLastError()); if (ret) ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG), "Didn't expect a persisted cert\n"); checkHash(signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent), CALG_SHA1, ctl, CERT_HASH_PROP_ID); /* Now that the hash property is set, we should get one property when * enumerating. */ propID = 0; numProps = 0; do { propID = CertEnumCTLContextProperties(ctl, propID); if (propID) numProps++; } while (propID != 0); ok(numProps == 1, "Expected 1 properties, got %d\n", numProps); checkHash(signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent), CALG_MD5, ctl, CERT_MD5_HASH_PROP_ID); CertFreeCTLContext(ctl); }
static BOOL CRYPT_MemDeleteCtl(PWINECRYPT_CERTSTORE store, void *pCtlContext) { WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; BOOL ret; if (ContextList_Remove(ms->ctls, pCtlContext)) ret = CertFreeCTLContext(pCtlContext); else ret = TRUE; return ret; }
static void testDupCTL(void) { PCCTL_CONTEXT context, dupContext; BOOL res; context = CertDuplicateCTLContext(NULL); ok(context == NULL, "expected NULL\n"); context = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent)); dupContext = CertDuplicateCTLContext(context); ok(dupContext != NULL, "expected a context\n"); ok(dupContext == context, "expected identical context addresses\n"); res = CertFreeCTLContext(dupContext); ok(res, "CertFreeCTLContext failed\n"); res = CertFreeCTLContext(context); ok(res, "CertFreeCTLContext failed\n"); res = CertFreeCTLContext(NULL); ok(res, "CertFreeCTLContext failed\n"); }
BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded, DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext) { PCCTL_CONTEXT ctl = CertCreateCTLContext(dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded); BOOL ret; TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore, dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition, ppCtlContext); if (ctl) { ret = CertAddCTLContextToStore(hCertStore, ctl, dwAddDisposition, ppCtlContext); CertFreeCTLContext(ctl); } else ret = FALSE; return ret; }
BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore, PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition, PCCTL_CONTEXT* ppStoreContext) { PWINECRYPT_CERTSTORE store = hCertStore; BOOL ret = TRUE; PCCTL_CONTEXT toAdd = NULL, existing = NULL; TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCtlContext, dwAddDisposition, ppStoreContext); if (dwAddDisposition != CERT_STORE_ADD_ALWAYS) { existing = CertFindCTLInStore(hCertStore, 0, 0, CTL_FIND_EXISTING, pCtlContext, NULL); } switch (dwAddDisposition) { case CERT_STORE_ADD_ALWAYS: toAdd = CertDuplicateCTLContext(pCtlContext); break; case CERT_STORE_ADD_NEW: if (existing) { TRACE("found matching CTL, not adding\n"); SetLastError(CRYPT_E_EXISTS); ret = FALSE; } else toAdd = CertDuplicateCTLContext(pCtlContext); break; case CERT_STORE_ADD_NEWER: if (existing) { LONG newer = CompareFileTime(&existing->pCtlInfo->ThisUpdate, &pCtlContext->pCtlInfo->ThisUpdate); if (newer < 0) toAdd = CertDuplicateCTLContext(pCtlContext); else { TRACE("existing CTL is newer, not adding\n"); SetLastError(CRYPT_E_EXISTS); ret = FALSE; } } else toAdd = CertDuplicateCTLContext(pCtlContext); break; case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES: if (existing) { LONG newer = CompareFileTime(&existing->pCtlInfo->ThisUpdate, &pCtlContext->pCtlInfo->ThisUpdate); if (newer < 0) { toAdd = CertDuplicateCTLContext(pCtlContext); CtlContext_CopyProperties(existing, pCtlContext); } else { TRACE("existing CTL is newer, not adding\n"); SetLastError(CRYPT_E_EXISTS); ret = FALSE; } } else toAdd = CertDuplicateCTLContext(pCtlContext); break; case CERT_STORE_ADD_REPLACE_EXISTING: toAdd = CertDuplicateCTLContext(pCtlContext); break; case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES: toAdd = CertDuplicateCTLContext(pCtlContext); if (existing) CtlContext_CopyProperties(toAdd, existing); break; case CERT_STORE_ADD_USE_EXISTING: if (existing) { CtlContext_CopyProperties(existing, pCtlContext); if (ppStoreContext) *ppStoreContext = CertDuplicateCTLContext(existing); } else toAdd = CertDuplicateCTLContext(pCtlContext); break; default: FIXME("Unimplemented add disposition %d\n", dwAddDisposition); ret = FALSE; } if (toAdd) { if (store) ret = store->ctls.addContext(store, (void *)toAdd, (void *)existing, (const void **)ppStoreContext); else if (ppStoreContext) *ppStoreContext = CertDuplicateCTLContext(toAdd); CertFreeCTLContext(toAdd); } CertFreeCTLContext(existing); TRACE("returning %d\n", ret); return ret; }
PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded) { PCTL_CONTEXT ctl = NULL; HCRYPTMSG msg; BOOL ret; BYTE *content = NULL; DWORD contentSize = 0, size; PCTL_INFO ctlInfo = NULL; TRACE("(%08x, %p, %d)\n", dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded); if (GET_CERT_ENCODING_TYPE(dwMsgAndCertEncodingType) != X509_ASN_ENCODING) { SetLastError(E_INVALIDARG); return NULL; } if (!pbCtlEncoded || !cbCtlEncoded) { SetLastError(ERROR_INVALID_DATA); return NULL; } msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, 0, NULL, NULL); if (!msg) return NULL; ret = CryptMsgUpdate(msg, pbCtlEncoded, cbCtlEncoded, TRUE); if (!ret) { SetLastError(ERROR_INVALID_DATA); goto end; } /* Check that it's really a CTL */ ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL, &size); if (ret) { char *innerContent = CryptMemAlloc(size); if (innerContent) { ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, innerContent, &size); if (ret) { if (strcmp(innerContent, szOID_CTL)) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; } } CryptMemFree(innerContent); } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } if (!ret) goto end; ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &contentSize); if (!ret) goto end; content = CryptMemAlloc(contentSize); if (content) { ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, content, &contentSize); if (ret) { ret = CryptDecodeObjectEx(dwMsgAndCertEncodingType, PKCS_CTL, content, contentSize, CRYPT_DECODE_ALLOC_FLAG, NULL, &ctlInfo, &size); if (ret) { ctl = Context_CreateDataContext(sizeof(CTL_CONTEXT)); if (ctl) { BYTE *data = CryptMemAlloc(cbCtlEncoded); if (data) { memcpy(data, pbCtlEncoded, cbCtlEncoded); ctl->dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; ctl->pbCtlEncoded = data; ctl->cbCtlEncoded = cbCtlEncoded; ctl->pCtlInfo = ctlInfo; ctl->hCertStore = NULL; ctl->hCryptMsg = msg; ctl->pbCtlContext = content; ctl->cbCtlContext = contentSize; } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } } } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } end: if (!ret) { CertFreeCTLContext(ctl); ctl = NULL; LocalFree(ctlInfo); CryptMemFree(content); CryptMsgClose(msg); } return ctl; }
static void testCreateCTL(void) { PCCTL_CONTEXT ctl; SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(0, NULL, 0); ok(!ctl && GetLastError() == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", GetLastError()); SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(X509_ASN_ENCODING, NULL, 0); ok(!ctl && (GetLastError() == ERROR_INVALID_DATA || GetLastError() == OSS_MORE_INPUT), /* win9x */ "expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(), GetLastError()); /* An empty CTL can't be created.. */ SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(X509_ASN_ENCODING, emptyCTL, sizeof(emptyCTL)); ok(!ctl && (GetLastError() == ERROR_INVALID_DATA || GetLastError() == OSS_DATA_ERROR), /* win9x */ "expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(), GetLastError()); /* Nor can any of these "signed" CTLs whose inner content OID isn't * szOID_CTL. */ SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTL, sizeof(signedCTL)); ok(!ctl && (GetLastError() == ERROR_INVALID_DATA || GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE /* win9x */ || GetLastError() == ERROR_SUCCESS /* some win98 */), "expected ERROR_INVALID_DATA, CRYPT_E_UNEXPECTED_MSG_TYPE, or ERROR_SUCCESS, got %d (0x%08x)\n", GetLastError(), GetLastError()); SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(X509_ASN_ENCODING, ctlWithOneEntry, sizeof(ctlWithOneEntry)); ok(!ctl && (GetLastError() == ERROR_INVALID_DATA || GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE /* win9x */ || GetLastError() == OSS_DATA_ERROR /* some win98 */ || GetLastError() == ERROR_SUCCESS /* some win98 */), "expected ERROR_INVALID_DATA, CRYPT_E_UNEXPECTED_MSG_TYPE, OSS_DATA_ERROR, or ERROR_SUCCESS, got %d (0x%08x)\n", GetLastError(), GetLastError()); SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithSubjectAlgorithm, sizeof(signedCTLWithSubjectAlgorithm)); ok(!ctl && (GetLastError() == ERROR_INVALID_DATA || GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE /* win9x */ || GetLastError() == ERROR_SUCCESS /* some win98 */), "expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(), GetLastError()); /* This signed CTL with the appropriate inner content type can be decoded. */ ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent)); ok(ctl != NULL, "CertCreateCTLContext failed: %08x\n", GetLastError()); if (ctl) { /* Even though the CTL was decoded with X509_ASN_ENCODING, the * message encoding type is included in the CTL's encoding type. */ ok(ctl->dwMsgAndCertEncodingType == (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING), "expected X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, got %08x\n", ctl->dwMsgAndCertEncodingType); CertFreeCTLContext(ctl); } /* This CTL with a bad signature can also be decoded, so the sig isn't * checked when loading the CTL. */ ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContentAndBadSig, sizeof(signedCTLWithCTLInnerContentAndBadSig)); ok(ctl != NULL, "CertCreateCTLContext failed: %08x\n", GetLastError()); if (ctl) CertFreeCTLContext(ctl); }