📄 cert.c
字号:
/*
* Copyright 2004-2006 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 <assert.h>
#include <stdarg.h>
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "wincrypt.h"
#include "winnls.h"
#include "rpc.h"
#include "wine/debug.h"
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
/* Internal version of CertGetCertificateContextProperty that gets properties
* directly from the context (or the context it's linked to, depending on its
* type.) Doesn't handle 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 CertContext_GetProperty(void *context, DWORD dwPropId,
void *pvData, DWORD *pcbData);
/* Internal version of CertSetCertificateContextProperty that sets properties
* directly on the context (or the context it's linked to, depending on its
* type.) Doesn't handle special cases, since they're handled by
* CertSetCertificateContextProperty anyway.
*/
static BOOL WINAPI CertContext_SetProperty(void *context, DWORD dwPropId,
DWORD dwFlags, const void *pvData);
BOOL WINAPI CertAddEncodedCertificateToStore(HCERTSTORE hCertStore,
DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded,
DWORD dwAddDisposition, PCCERT_CONTEXT *ppCertContext)
{
PCCERT_CONTEXT cert = CertCreateCertificateContext(dwCertEncodingType,
pbCertEncoded, cbCertEncoded);
BOOL ret;
TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore, dwCertEncodingType,
pbCertEncoded, cbCertEncoded, dwAddDisposition, ppCertContext);
if (cert)
{
ret = CertAddCertificateContextToStore(hCertStore, cert,
dwAddDisposition, ppCertContext);
CertFreeCertificateContext(cert);
}
else
ret = FALSE;
return ret;
}
PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType,
const BYTE *pbCertEncoded, DWORD cbCertEncoded)
{
PCERT_CONTEXT cert = NULL;
BOOL ret;
PCERT_INFO certInfo = NULL;
DWORD size = 0;
TRACE("(%08x, %p, %d)\n", dwCertEncodingType, pbCertEncoded,
cbCertEncoded);
ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_TO_BE_SIGNED,
pbCertEncoded, cbCertEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
(BYTE *)&certInfo, &size);
if (ret)
{
BYTE *data = NULL;
cert = (PCERT_CONTEXT)Context_CreateDataContext(sizeof(CERT_CONTEXT));
if (!cert)
goto end;
data = CryptMemAlloc(cbCertEncoded);
if (!data)
{
CryptMemFree(cert);
cert = NULL;
goto end;
}
memcpy(data, pbCertEncoded, cbCertEncoded);
cert->dwCertEncodingType = dwCertEncodingType;
cert->pbCertEncoded = data;
cert->cbCertEncoded = cbCertEncoded;
cert->pCertInfo = certInfo;
cert->hCertStore = 0;
}
end:
return (PCCERT_CONTEXT)cert;
}
PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(
PCCERT_CONTEXT pCertContext)
{
TRACE("(%p)\n", pCertContext);
Context_AddRef((void *)pCertContext, sizeof(CERT_CONTEXT));
return pCertContext;
}
static void CertDataContext_Free(void *context)
{
PCERT_CONTEXT certContext = (PCERT_CONTEXT)context;
CryptMemFree(certContext->pbCertEncoded);
LocalFree(certContext->pCertInfo);
}
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
{
TRACE("(%p)\n", pCertContext);
if (pCertContext)
Context_Release((void *)pCertContext, sizeof(CERT_CONTEXT),
CertDataContext_Free);
return TRUE;
}
DWORD WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext,
DWORD dwPropId)
{
PCONTEXT_PROPERTY_LIST properties = Context_GetProperties(
(void *)pCertContext, sizeof(CERT_CONTEXT));
DWORD ret;
TRACE("(%p, %d)\n", pCertContext, dwPropId);
if (properties)
ret = ContextPropertyList_EnumPropIDs(properties, dwPropId);
else
ret = 0;
return ret;
}
static BOOL CertContext_GetHashProp(void *context, DWORD dwPropId,
ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
DWORD *pcbData)
{
BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData,
pcbData);
if (ret)
{
CRYPT_DATA_BLOB blob = { *pcbData, pvData };
ret = CertContext_SetProperty(context, dwPropId, 0, &blob);
}
return ret;
}
static BOOL WINAPI CertContext_GetProperty(void *context, DWORD dwPropId,
void *pvData, DWORD *pcbData)
{
PCCERT_CONTEXT pCertContext = (PCCERT_CONTEXT)context;
PCONTEXT_PROPERTY_LIST properties =
Context_GetProperties(context, sizeof(CERT_CONTEXT));
BOOL ret;
CRYPT_DATA_BLOB blob;
TRACE("(%p, %d, %p, %p)\n", context, dwPropId, pvData, pcbData);
if (properties)
ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob);
else
ret = FALSE;
if (ret)
{
if (!pvData)
{
*pcbData = blob.cbData;
ret = TRUE;
}
else if (*pcbData < blob.cbData)
{
SetLastError(ERROR_MORE_DATA);
*pcbData = blob.cbData;
}
else
{
memcpy(pvData, blob.pbData, blob.cbData);
*pcbData = blob.cbData;
ret = TRUE;
}
}
else
{
/* Implicit properties */
switch (dwPropId)
{
case CERT_SHA1_HASH_PROP_ID:
ret = CertContext_GetHashProp(context, dwPropId, CALG_SHA1,
pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, pvData,
pcbData);
break;
case CERT_MD5_HASH_PROP_ID:
ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5,
pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, pvData,
pcbData);
break;
case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5,
pCertContext->pCertInfo->Subject.pbData,
pCertContext->pCertInfo->Subject.cbData,
pvData, pcbData);
break;
case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
pvData, pcbData);
break;
case CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID:
ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5,
pCertContext->pCertInfo->SerialNumber.pbData,
pCertContext->pCertInfo->SerialNumber.cbData,
pvData, pcbData);
break;
case CERT_SIGNATURE_HASH_PROP_ID:
FIXME("CERT_SIGNATURE_HASH_PROP_ID unimplemented\n");
SetLastError(CRYPT_E_NOT_FOUND);
break;
default:
SetLastError(CRYPT_E_NOT_FOUND);
}
}
TRACE("returning %d\n", ret);
return ret;
}
void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info)
{
DWORD i, containerLen, provNameLen;
LPBYTE data = (LPBYTE)info + sizeof(CRYPT_KEY_PROV_INFO);
info->pwszContainerName = (LPWSTR)data;
containerLen = (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR);
data += containerLen;
info->pwszProvName = (LPWSTR)data;
provNameLen = (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR);
data += provNameLen;
info->rgProvParam = (PCRYPT_KEY_PROV_PARAM)data;
data += info->cProvParam * sizeof(CRYPT_KEY_PROV_PARAM);
for (i = 0; i < info->cProvParam; i++)
{
info->rgProvParam[i].pbData = data;
data += info->rgProvParam[i].cbData;
}
}
BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
DWORD dwPropId, void *pvData, DWORD *pcbData)
{
BOOL ret;
TRACE("(%p, %d, %p, %p)\n", pCertContext, dwPropId, pvData, pcbData);
switch (dwPropId)
{
case 0:
case CERT_CERT_PROP_ID:
case CERT_CRL_PROP_ID:
case CERT_CTL_PROP_ID:
SetLastError(E_INVALIDARG);
ret = FALSE;
break;
case CERT_ACCESS_STATE_PROP_ID:
if (!pvData)
{
*pcbData = sizeof(DWORD);
ret = TRUE;
}
else if (*pcbData < sizeof(DWORD))
{
SetLastError(ERROR_MORE_DATA);
*pcbData = sizeof(DWORD);
ret = FALSE;
}
else
{
*(DWORD *)pvData =
CertStore_GetAccessState(pCertContext->hCertStore);
ret = TRUE;
}
break;
case CERT_KEY_IDENTIFIER_PROP_ID:
ret = CertContext_GetProperty((void *)pCertContext, dwPropId,
pvData, pcbData);
if (!ret)
SetLastError(ERROR_INVALID_DATA);
break;
case CERT_KEY_PROV_HANDLE_PROP_ID:
{
CERT_KEY_CONTEXT keyContext;
DWORD size = sizeof(keyContext);
ret = CertContext_GetProperty((void *)pCertContext,
CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
if (ret)
{
if (!pvData)
{
*pcbData = sizeof(HCRYPTPROV);
ret = TRUE;
}
else if (*pcbData < sizeof(HCRYPTPROV))
{
SetLastError(ERROR_MORE_DATA);
*pcbData = sizeof(HCRYPTPROV);
ret = FALSE;
}
else
{
*(HCRYPTPROV *)pvData = keyContext.hCryptProv;
ret = TRUE;
}
}
break;
}
case CERT_KEY_PROV_INFO_PROP_ID:
ret = CertContext_GetProperty((void *)pCertContext, dwPropId, pvData,
pcbData);
if (ret && pvData)
CRYPT_FixKeyProvInfoPointers((PCRYPT_KEY_PROV_INFO)pvData);
break;
default:
ret = CertContext_GetProperty((void *)pCertContext, dwPropId, pvData,
pcbData);
}
TRACE("returning %d\n", ret);
return ret;
}
/* Copies key provider info from from into to, where to is assumed to be a
* contiguous buffer of memory large enough for from and all its associated
* data, but whose pointers are uninitialized.
* Upon return, to contains a contiguous copy of from, packed in the following
* order:
* - CRYPT_KEY_PROV_INFO
* - pwszContainerName
* - pwszProvName
* - rgProvParam[0]...
*/
static void CRYPT_CopyKeyProvInfo(PCRYPT_KEY_PROV_INFO to,
const CRYPT_KEY_PROV_INFO *from)
{
DWORD i;
LPBYTE nextData = (LPBYTE)to + sizeof(CRYPT_KEY_PROV_INFO);
if (from->pwszContainerName)
{
to->pwszContainerName = (LPWSTR)nextData;
lstrcpyW(to->pwszContainerName, from->pwszContainerName);
nextData += (lstrlenW(from->pwszContainerName) + 1) * sizeof(WCHAR);
}
else
to->pwszContainerName = NULL;
if (from->pwszProvName)
{
to->pwszProvName = (LPWSTR)nextData;
lstrcpyW(to->pwszProvName, from->pwszProvName);
nextData += (lstrlenW(from->pwszProvName) + 1) * sizeof(WCHAR);
}
else
to->pwszProvName = NULL;
to->dwProvType = from->dwProvType;
to->dwFlags = from->dwFlags;
to->cProvParam = from->cProvParam;
to->rgProvParam = (PCRYPT_KEY_PROV_PARAM)nextData;
nextData += to->cProvParam * sizeof(CRYPT_KEY_PROV_PARAM);
to->dwKeySpec = from->dwKeySpec;
for (i = 0; i < to->cProvParam; i++)
{
memcpy(&to->rgProvParam[i], &from->rgProvParam[i],
sizeof(CRYPT_KEY_PROV_PARAM));
to->rgProvParam[i].pbData = nextData;
memcpy(to->rgProvParam[i].pbData, from->rgProvParam[i].pbData,
from->rgProvParam[i].cbData);
nextData += from->rgProvParam[i].cbData;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -