From 429b1e1b41f0d5b849c7ddc2c20712d53e47c8dc Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Fri, 29 Aug 2008 07:29:00 -0700 Subject: [PATCH] crypt32: Implement CertCreateCTLContext and CertFreeCTLContext. --- dlls/crypt32/Makefile.in | 1 + dlls/crypt32/ctl.c | 177 +++++++++++++++++++++++++++++++++++++++ dlls/crypt32/store.c | 14 ---- dlls/crypt32/tests/ctl.c | 8 -- 4 files changed, 178 insertions(+), 22 deletions(-) create mode 100644 dlls/crypt32/ctl.c diff --git a/dlls/crypt32/Makefile.in b/dlls/crypt32/Makefile.in index 16fbd5e86c1..10ffda94463 100644 --- a/dlls/crypt32/Makefile.in +++ b/dlls/crypt32/Makefile.in @@ -14,6 +14,7 @@ C_SRCS = \ collectionstore.c \ context.c \ crl.c \ + ctl.c \ decode.c \ encode.c \ filestore.c \ diff --git a/dlls/crypt32/ctl.c b/dlls/crypt32/ctl.c new file mode 100644 index 00000000000..728d008dc2e --- /dev/null +++ b/dlls/crypt32/ctl.c @@ -0,0 +1,177 @@ +/* + * Copyright 2008 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#include +#include + +#define NONAMELESSUNION +#include "windef.h" +#include "winbase.h" +#include "wincrypt.h" +#include "wine/debug.h" +#include "crypt32_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(crypt); + +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, + (BYTE *)&ctlInfo, &size); + if (ret) + { + ctl = (PCTL_CONTEXT)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) + { + CryptMemFree(ctl); + ctl = NULL; + LocalFree(ctlInfo); + CryptMemFree(content); + CryptMsgClose(msg); + } + return (PCCTL_CONTEXT)ctl; +} + +static void CTLDataContext_Free(void *context) +{ + PCTL_CONTEXT ctlContext = (PCTL_CONTEXT)context; + + CryptMsgClose(ctlContext->hCryptMsg); + CryptMemFree(ctlContext->pbCtlEncoded); + CryptMemFree(ctlContext->pbCtlContext); + LocalFree(ctlContext->pCtlInfo); +} + +BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCTLContext) +{ + TRACE("(%p)\n", pCTLContext); + + if (pCTLContext) + Context_Release((void *)pCTLContext, sizeof(CTL_CONTEXT), + CTLDataContext_Free); + return TRUE; +} diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c index 9534e5c2d3a..9ce6be4a574 100644 --- a/dlls/crypt32/store.c +++ b/dlls/crypt32/store.c @@ -1043,14 +1043,6 @@ PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore, return ret; } -PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwCertEncodingType, - const BYTE* pbCtlEncoded, DWORD cbCtlEncoded) -{ - FIXME("(%08x, %p, %08x): stub\n", dwCertEncodingType, pbCtlEncoded, - cbCtlEncoded); - return NULL; -} - BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded, DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext) @@ -1076,12 +1068,6 @@ PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext) return pCtlContext; } -BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCtlContext) -{ - FIXME("(%p): stub\n", pCtlContext ); - return TRUE; -} - BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext) { FIXME("(%p): stub\n", pCtlContext); diff --git a/dlls/crypt32/tests/ctl.c b/dlls/crypt32/tests/ctl.c index 215c057fee5..9d4eee4b7e9 100644 --- a/dlls/crypt32/tests/ctl.c +++ b/dlls/crypt32/tests/ctl.c @@ -113,19 +113,16 @@ static void testCreateCTL(void) SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(0, NULL, 0); - todo_wine ok(!ctl && GetLastError() == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", GetLastError()); SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(X509_ASN_ENCODING, NULL, 0); - todo_wine ok(!ctl && GetLastError() == ERROR_INVALID_DATA, "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)); - todo_wine ok(!ctl && GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(), GetLastError()); @@ -134,21 +131,18 @@ static void testCreateCTL(void) */ SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTL, sizeof(signedCTL)); - todo_wine ok(!ctl && GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(), GetLastError()); SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(X509_ASN_ENCODING, ctlWithOneEntry, sizeof(ctlWithOneEntry)); - todo_wine ok(!ctl && GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(), GetLastError()); SetLastError(0xdeadbeef); ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithSubjectAlgorithm, sizeof(signedCTLWithSubjectAlgorithm)); - todo_wine ok(!ctl && GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(), GetLastError()); @@ -156,7 +150,6 @@ static void testCreateCTL(void) */ ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent)); - todo_wine ok(ctl != NULL, "CertCreateCTLContext failed: %08x\n", GetLastError()); if (ctl) { @@ -175,7 +168,6 @@ static void testCreateCTL(void) ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContentAndBadSig, sizeof(signedCTLWithCTLInnerContentAndBadSig)); - todo_wine ok(ctl != NULL, "CertCreateCTLContext failed: %08x\n", GetLastError()); if (ctl) CertFreeCTLContext(ctl);