📄 cert.c
字号:
static BOOL CertContext_SetKeyProvInfoProperty(PCONTEXT_PROPERTY_LIST properties,
const CRYPT_KEY_PROV_INFO *info)
{
BOOL ret;
LPBYTE buf = NULL;
DWORD size = sizeof(CRYPT_KEY_PROV_INFO), i, containerSize, provNameSize;
if (info->pwszContainerName)
containerSize = (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR);
else
containerSize = 0;
if (info->pwszProvName)
provNameSize = (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR);
else
provNameSize = 0;
size += containerSize + provNameSize;
for (i = 0; i < info->cProvParam; i++)
size += sizeof(CRYPT_KEY_PROV_PARAM) + info->rgProvParam[i].cbData;
buf = CryptMemAlloc(size);
if (buf)
{
CRYPT_CopyKeyProvInfo((PCRYPT_KEY_PROV_INFO)buf, info);
ret = ContextPropertyList_SetProperty(properties,
CERT_KEY_PROV_INFO_PROP_ID, buf, size);
CryptMemFree(buf);
}
else
ret = FALSE;
return ret;
}
static BOOL WINAPI CertContext_SetProperty(void *context, DWORD dwPropId,
DWORD dwFlags, const void *pvData)
{
PCONTEXT_PROPERTY_LIST properties =
Context_GetProperties(context, sizeof(CERT_CONTEXT));
BOOL ret;
TRACE("(%p, %d, %08x, %p)\n", context, dwPropId, dwFlags, pvData);
if (!properties)
ret = FALSE;
else
{
switch (dwPropId)
{
case CERT_AUTO_ENROLL_PROP_ID:
case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */
case CERT_DESCRIPTION_PROP_ID:
case CERT_FRIENDLY_NAME_PROP_ID:
case CERT_HASH_PROP_ID:
case CERT_KEY_IDENTIFIER_PROP_ID:
case CERT_MD5_HASH_PROP_ID:
case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
case CERT_PUBKEY_ALG_PARA_PROP_ID:
case CERT_PVK_FILE_PROP_ID:
case CERT_SIGNATURE_HASH_PROP_ID:
case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
case CERT_ENROLLMENT_PROP_ID:
case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
case CERT_RENEWAL_PROP_ID:
{
if (pvData)
{
const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvData;
ret = ContextPropertyList_SetProperty(properties, dwPropId,
blob->pbData, blob->cbData);
}
else
{
ContextPropertyList_RemoveProperty(properties, dwPropId);
ret = TRUE;
}
break;
}
case CERT_DATE_STAMP_PROP_ID:
if (pvData)
ret = ContextPropertyList_SetProperty(properties, dwPropId,
(const BYTE *)pvData, sizeof(FILETIME));
else
{
ContextPropertyList_RemoveProperty(properties, dwPropId);
ret = TRUE;
}
break;
case CERT_KEY_CONTEXT_PROP_ID:
{
if (pvData)
{
const CERT_KEY_CONTEXT *keyContext = (const CERT_KEY_CONTEXT *)pvData;
ret = ContextPropertyList_SetProperty(properties, dwPropId,
(const BYTE *)keyContext, keyContext->cbSize);
}
else
{
ContextPropertyList_RemoveProperty(properties, dwPropId);
ret = TRUE;
}
break;
}
case CERT_KEY_PROV_INFO_PROP_ID:
if (pvData)
ret = CertContext_SetKeyProvInfoProperty(properties,
(const CRYPT_KEY_PROV_INFO *)pvData);
else
{
ContextPropertyList_RemoveProperty(properties, dwPropId);
ret = TRUE;
}
break;
case CERT_KEY_PROV_HANDLE_PROP_ID:
{
CERT_KEY_CONTEXT keyContext;
DWORD size = sizeof(keyContext);
ret = CertContext_GetProperty(context, CERT_KEY_CONTEXT_PROP_ID,
&keyContext, &size);
if (ret)
{
if (!(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
CryptReleaseContext(keyContext.hCryptProv, 0);
if (pvData)
keyContext.hCryptProv = *(const HCRYPTPROV *)pvData;
else
keyContext.hCryptProv = 0;
ret = CertContext_SetProperty(context, CERT_KEY_CONTEXT_PROP_ID,
0, &keyContext);
}
break;
}
default:
FIXME("%d: stub\n", dwPropId);
ret = FALSE;
}
}
TRACE("returning %d\n", ret);
return ret;
}
BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
DWORD dwPropId, DWORD dwFlags, const void *pvData)
{
BOOL ret;
TRACE("(%p, %d, %08x, %p)\n", pCertContext, dwPropId, dwFlags, pvData);
/* Handle special cases for "read-only"/invalid prop IDs. Windows just
* crashes on most of these, I'll be safer.
*/
switch (dwPropId)
{
case 0:
case CERT_ACCESS_STATE_PROP_ID:
case CERT_CERT_PROP_ID:
case CERT_CRL_PROP_ID:
case CERT_CTL_PROP_ID:
SetLastError(E_INVALIDARG);
return FALSE;
}
ret = CertContext_SetProperty((void *)pCertContext, dwPropId, dwFlags,
pvData);
TRACE("returning %d\n", ret);
return ret;
}
/* Acquires the private key using the key provider info, retrieving info from
* the certificate if info is NULL. The acquired provider is returned in
* *phCryptProv, and the key spec for the provider is returned in *pdwKeySpec.
*/
static BOOL CRYPT_AcquirePrivateKeyFromProvInfo(PCCERT_CONTEXT pCert,
PCRYPT_KEY_PROV_INFO info, HCRYPTPROV *phCryptProv, DWORD *pdwKeySpec)
{
DWORD size = 0;
BOOL allocated = FALSE, ret = TRUE;
if (!info)
{
ret = CertGetCertificateContextProperty(pCert,
CERT_KEY_PROV_INFO_PROP_ID, 0, &size);
if (ret)
{
info = (PCRYPT_KEY_PROV_INFO)HeapAlloc(GetProcessHeap(), 0, size);
if (info)
{
ret = CertGetCertificateContextProperty(pCert,
CERT_KEY_PROV_INFO_PROP_ID, info, &size);
allocated = TRUE;
}
}
else
SetLastError(CRYPT_E_NO_KEY_PROPERTY);
}
if (ret)
{
ret = CryptAcquireContextW(phCryptProv, info->pwszContainerName,
info->pwszProvName, info->dwProvType, 0);
if (ret)
{
DWORD i;
for (i = 0; i < info->cProvParam; i++)
{
CryptSetProvParam(*phCryptProv,
info->rgProvParam[i].dwParam, info->rgProvParam[i].pbData,
info->rgProvParam[i].dwFlags);
}
*pdwKeySpec = info->dwKeySpec;
}
else
SetLastError(CRYPT_E_NO_KEY_PROPERTY);
}
if (allocated)
HeapFree(GetProcessHeap(), 0, info);
return ret;
}
BOOL WINAPI CryptAcquireCertificatePrivateKey(PCCERT_CONTEXT pCert,
DWORD dwFlags, void *pvReserved, HCRYPTPROV *phCryptProv, DWORD *pdwKeySpec,
BOOL *pfCallerFreeProv)
{
BOOL ret = FALSE, cache = FALSE;
PCRYPT_KEY_PROV_INFO info = NULL;
CERT_KEY_CONTEXT keyContext;
DWORD size;
TRACE("(%p, %08x, %p, %p, %p, %p)\n", pCert, dwFlags, pvReserved,
phCryptProv, pdwKeySpec, pfCallerFreeProv);
if (dwFlags & CRYPT_ACQUIRE_USE_PROV_INFO_FLAG)
{
DWORD size = 0;
ret = CertGetCertificateContextProperty(pCert,
CERT_KEY_PROV_INFO_PROP_ID, 0, &size);
if (ret)
{
info = (PCRYPT_KEY_PROV_INFO)HeapAlloc(
GetProcessHeap(), 0, size);
ret = CertGetCertificateContextProperty(pCert,
CERT_KEY_PROV_INFO_PROP_ID, info, &size);
if (ret)
cache = info->dwFlags & CERT_SET_KEY_CONTEXT_PROP_ID;
}
}
else if (dwFlags & CRYPT_ACQUIRE_CACHE_FLAG)
cache = TRUE;
*phCryptProv = 0;
if (cache)
{
size = sizeof(keyContext);
ret = CertGetCertificateContextProperty(pCert, CERT_KEY_CONTEXT_PROP_ID,
&keyContext, &size);
if (ret)
{
*phCryptProv = keyContext.hCryptProv;
if (pdwKeySpec)
*pdwKeySpec = keyContext.dwKeySpec;
if (pfCallerFreeProv)
*pfCallerFreeProv = !cache;
}
}
if (!*phCryptProv)
{
ret = CRYPT_AcquirePrivateKeyFromProvInfo(pCert, info,
&keyContext.hCryptProv, &keyContext.dwKeySpec);
if (ret)
{
*phCryptProv = keyContext.hCryptProv;
if (pdwKeySpec)
*pdwKeySpec = keyContext.dwKeySpec;
if (cache)
{
keyContext.cbSize = sizeof(keyContext);
if (CertSetCertificateContextProperty(pCert,
CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext))
{
if (pfCallerFreeProv)
*pfCallerFreeProv = FALSE;
}
}
else
{
if (pfCallerFreeProv)
*pfCallerFreeProv = TRUE;
}
}
}
HeapFree(GetProcessHeap(), 0, info);
return ret;
}
BOOL WINAPI CertCompareCertificate(DWORD dwCertEncodingType,
PCERT_INFO pCertId1, PCERT_INFO pCertId2)
{
TRACE("(%08x, %p, %p)\n", dwCertEncodingType, pCertId1, pCertId2);
return CertCompareCertificateName(dwCertEncodingType, &pCertId1->Issuer,
&pCertId2->Issuer) && CertCompareIntegerBlob(&pCertId1->SerialNumber,
&pCertId2->SerialNumber);
}
BOOL WINAPI CertCompareCertificateName(DWORD dwCertEncodingType,
PCERT_NAME_BLOB pCertName1, PCERT_NAME_BLOB pCertName2)
{
BOOL ret;
TRACE("(%08x, %p, %p)\n", dwCertEncodingType, pCertName1, pCertName2);
if (pCertName1->cbData == pCertName2->cbData)
{
if (pCertName1->cbData)
ret = !memcmp(pCertName1->pbData, pCertName2->pbData,
pCertName1->cbData);
else
ret = TRUE;
}
else
ret = FALSE;
return ret;
}
/* Returns the number of significant bytes in pInt, where a byte is
* insignificant if it's a leading 0 for positive numbers or a leading 0xff
* for negative numbers. pInt is assumed to be little-endian.
*/
static DWORD CRYPT_significantBytes(const CRYPT_INTEGER_BLOB *pInt)
{
DWORD ret = pInt->cbData;
while (ret > 1)
{
if (pInt->pbData[ret - 2] <= 0x7f && pInt->pbData[ret - 1] == 0)
ret--;
else if (pInt->pbData[ret - 2] >= 0x80 && pInt->pbData[ret - 1] == 0xff)
ret--;
else
break;
}
return ret;
}
BOOL WINAPI CertCompareIntegerBlob(PCRYPT_INTEGER_BLOB pInt1,
PCRYPT_INTEGER_BLOB pInt2)
{
BOOL ret;
DWORD cb1, cb2;
TRACE("(%p, %p)\n", pInt1, pInt2);
cb1 = CRYPT_significantBytes(pInt1);
cb2 = CRYPT_significantBytes(pInt2);
if (cb1 == cb2)
{
if (cb1)
ret = !memcmp(pInt1->pbData, pInt1->pbData, cb1);
else
ret = TRUE;
}
else
ret = FALSE;
return ret;
}
BOOL WINAPI CertComparePublicKeyInfo(DWORD dwCertEncodingType,
PCERT_PUBLIC_KEY_INFO pPublicKey1, PCERT_PUBLIC_KEY_INFO pPublicKey2)
{
BOOL ret;
TRACE("(%08x, %p, %p)\n", dwCertEncodingType, pPublicKey1, pPublicKey2);
if (pPublicKey1->PublicKey.cbData == pPublicKey2->PublicKey.cbData &&
pPublicKey1->PublicKey.cUnusedBits == pPublicKey2->PublicKey.cUnusedBits)
{
if (pPublicKey2->PublicKey.cbData)
ret = !memcmp(pPublicKey1->PublicKey.pbData,
pPublicKey2->PublicKey.pbData, pPublicKey1->PublicKey.cbData);
else
ret = TRUE;
}
else
ret = FALSE;
return ret;
}
DWORD WINAPI CertGetPublicKeyLength(DWORD dwCertEncodingType,
PCERT_PUBLIC_KEY_INFO pPublicKey)
{
DWORD len = 0;
TRACE("(%08x, %p)\n", dwCertEncodingType, pPublicKey);
if (dwCertEncodingType != X509_ASN_ENCODING)
{
SetLastError(ERROR_FILE_NOT_FOUND);
return 0;
}
if (pPublicKey->Algorithm.pszObjId &&
!strcmp(pPublicKey->Algorithm.pszObjId, szOID_RSA_DH))
{
FIXME("unimplemented for DH public keys\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -