📄 cert.c
字号:
{
BOOL ret;
TRACE("(%p, %p)\n", pCertContext, pUsage);
if (pUsage)
{
CRYPT_DATA_BLOB blob = { 0, NULL };
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE,
pUsage, CRYPT_ENCODE_ALLOC_FLAG, NULL, &blob.pbData, &blob.cbData);
if (ret)
{
ret = CertSetCertificateContextProperty(pCertContext,
CERT_ENHKEY_USAGE_PROP_ID, 0, &blob);
LocalFree(blob.pbData);
}
}
else
ret = CertSetCertificateContextProperty(pCertContext,
CERT_ENHKEY_USAGE_PROP_ID, 0, NULL);
return ret;
}
BOOL WINAPI CertAddEnhancedKeyUsageIdentifier(PCCERT_CONTEXT pCertContext,
LPCSTR pszUsageIdentifier)
{
BOOL ret;
DWORD size;
TRACE("(%p, %s)\n", pCertContext, debugstr_a(pszUsageIdentifier));
if (CertGetEnhancedKeyUsage(pCertContext,
CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size))
{
PCERT_ENHKEY_USAGE usage = CryptMemAlloc(size);
if (usage)
{
ret = CertGetEnhancedKeyUsage(pCertContext,
CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, usage, &size);
if (ret)
{
PCERT_ENHKEY_USAGE newUsage = CryptMemAlloc(size +
sizeof(LPSTR) + strlen(pszUsageIdentifier) + 1);
if (newUsage)
{
LPSTR nextOID;
DWORD i;
newUsage->rgpszUsageIdentifier =
(LPSTR *)((LPBYTE)newUsage + sizeof(CERT_ENHKEY_USAGE));
nextOID = (LPSTR)((LPBYTE)newUsage->rgpszUsageIdentifier +
(usage->cUsageIdentifier + 1) * sizeof(LPSTR));
for (i = 0; i < usage->cUsageIdentifier; i++)
{
newUsage->rgpszUsageIdentifier[i] = nextOID;
strcpy(nextOID, usage->rgpszUsageIdentifier[i]);
nextOID += strlen(nextOID) + 1;
}
newUsage->rgpszUsageIdentifier[i] = nextOID;
strcpy(nextOID, pszUsageIdentifier);
newUsage->cUsageIdentifier = i + 1;
ret = CertSetEnhancedKeyUsage(pCertContext, newUsage);
CryptMemFree(newUsage);
}
}
CryptMemFree(usage);
}
else
ret = FALSE;
}
else
{
PCERT_ENHKEY_USAGE usage = CryptMemAlloc(sizeof(CERT_ENHKEY_USAGE) +
sizeof(LPSTR) + strlen(pszUsageIdentifier) + 1);
if (usage)
{
usage->rgpszUsageIdentifier =
(LPSTR *)((LPBYTE)usage + sizeof(CERT_ENHKEY_USAGE));
usage->rgpszUsageIdentifier[0] = (LPSTR)((LPBYTE)usage +
sizeof(CERT_ENHKEY_USAGE) + sizeof(LPSTR));
strcpy(usage->rgpszUsageIdentifier[0], pszUsageIdentifier);
usage->cUsageIdentifier = 1;
ret = CertSetEnhancedKeyUsage(pCertContext, usage);
CryptMemFree(usage);
}
else
ret = FALSE;
}
return ret;
}
BOOL WINAPI CertRemoveEnhancedKeyUsageIdentifier(PCCERT_CONTEXT pCertContext,
LPCSTR pszUsageIdentifier)
{
BOOL ret;
DWORD size;
CERT_ENHKEY_USAGE usage;
TRACE("(%p, %s)\n", pCertContext, debugstr_a(pszUsageIdentifier));
size = sizeof(usage);
ret = CertGetEnhancedKeyUsage(pCertContext,
CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, &usage, &size);
if (!ret && GetLastError() == ERROR_MORE_DATA)
{
PCERT_ENHKEY_USAGE pUsage = CryptMemAlloc(size);
if (pUsage)
{
ret = CertGetEnhancedKeyUsage(pCertContext,
CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
if (ret)
{
if (pUsage->cUsageIdentifier)
{
DWORD i;
BOOL found = FALSE;
for (i = 0; i < pUsage->cUsageIdentifier; i++)
{
if (!strcmp(pUsage->rgpszUsageIdentifier[i],
pszUsageIdentifier))
found = TRUE;
if (found && i < pUsage->cUsageIdentifier - 1)
pUsage->rgpszUsageIdentifier[i] =
pUsage->rgpszUsageIdentifier[i + 1];
}
pUsage->cUsageIdentifier--;
/* Remove the usage if it's empty */
if (pUsage->cUsageIdentifier)
ret = CertSetEnhancedKeyUsage(pCertContext, pUsage);
else
ret = CertSetEnhancedKeyUsage(pCertContext, NULL);
}
}
CryptMemFree(pUsage);
}
else
ret = FALSE;
}
else
{
/* it fit in an empty usage, therefore there's nothing to remove */
ret = TRUE;
}
return ret;
}
BOOL WINAPI CertGetValidUsages(DWORD cCerts, PCCERT_CONTEXT *rghCerts,
int *cNumOIDSs, LPSTR *rghOIDs, DWORD *pcbOIDs)
{
BOOL ret = TRUE;
DWORD i, cbOIDs = 0;
BOOL allUsagesValid = TRUE;
CERT_ENHKEY_USAGE validUsages = { 0, NULL };
TRACE("(%d, %p, %p, %p, %d)\n", cCerts, *rghCerts, cNumOIDSs,
rghOIDs, *pcbOIDs);
for (i = 0; ret && i < cCerts; i++)
{
CERT_ENHKEY_USAGE usage;
DWORD size = sizeof(usage);
ret = CertGetEnhancedKeyUsage(rghCerts[i], 0, &usage, &size);
/* Success is deliberately ignored: it implies all usages are valid */
if (!ret && GetLastError() == ERROR_MORE_DATA)
{
PCERT_ENHKEY_USAGE pUsage = CryptMemAlloc(size);
allUsagesValid = FALSE;
if (pUsage)
{
ret = CertGetEnhancedKeyUsage(rghCerts[i], 0, pUsage, &size);
if (ret)
{
if (!validUsages.cUsageIdentifier)
{
DWORD j;
cbOIDs = pUsage->cUsageIdentifier * sizeof(LPSTR);
validUsages.cUsageIdentifier = pUsage->cUsageIdentifier;
for (j = 0; j < validUsages.cUsageIdentifier; j++)
cbOIDs += lstrlenA(pUsage->rgpszUsageIdentifier[j])
+ 1;
validUsages.rgpszUsageIdentifier =
CryptMemAlloc(cbOIDs);
if (validUsages.rgpszUsageIdentifier)
{
LPSTR nextOID = (LPSTR)
((LPBYTE)validUsages.rgpszUsageIdentifier +
validUsages.cUsageIdentifier * sizeof(LPSTR));
for (j = 0; j < validUsages.cUsageIdentifier; j++)
{
validUsages.rgpszUsageIdentifier[j] = nextOID;
lstrcpyA(validUsages.rgpszUsageIdentifier[j],
pUsage->rgpszUsageIdentifier[j]);
nextOID += lstrlenA(nextOID) + 1;
}
}
else
ret = FALSE;
}
else
{
DWORD j, k, validIndexes = 0, numRemoved = 0;
/* Merge: build a bitmap of all the indexes of
* validUsages.rgpszUsageIdentifier that are in pUsage.
*/
for (j = 0; j < pUsage->cUsageIdentifier; j++)
{
for (k = 0; k < validUsages.cUsageIdentifier; k++)
{
if (!strcmp(pUsage->rgpszUsageIdentifier[j],
validUsages.rgpszUsageIdentifier[k]))
{
validIndexes |= (1 << k);
break;
}
}
}
/* Merge by removing from validUsages those that are
* not in the bitmap.
*/
for (j = 0; j < validUsages.cUsageIdentifier; j++)
{
if (!(validIndexes & (1 << j)))
{
if (j < validUsages.cUsageIdentifier - 1)
{
memcpy(&validUsages.rgpszUsageIdentifier[j],
&validUsages.rgpszUsageIdentifier[j +
numRemoved + 1],
(validUsages.cUsageIdentifier - numRemoved
- j - 1) * sizeof(LPSTR));
cbOIDs -= lstrlenA(
validUsages.rgpszUsageIdentifier[j]) + 1 +
sizeof(LPSTR);
numRemoved++;
}
else
validUsages.cUsageIdentifier--;
}
}
}
}
CryptMemFree(pUsage);
}
else
ret = FALSE;
}
}
if (ret)
{
if (allUsagesValid)
{
*cNumOIDSs = -1;
*pcbOIDs = 0;
}
else
{
if (!rghOIDs || *pcbOIDs < cbOIDs)
{
*pcbOIDs = cbOIDs;
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
LPSTR nextOID = (LPSTR)((LPBYTE)rghOIDs +
validUsages.cUsageIdentifier * sizeof(LPSTR));
*pcbOIDs = cbOIDs;
*cNumOIDSs = validUsages.cUsageIdentifier;
for (i = 0; i < validUsages.cUsageIdentifier; i++)
{
rghOIDs[i] = nextOID;
lstrcpyA(nextOID, validUsages.rgpszUsageIdentifier[i]);
nextOID += lstrlenA(nextOID) + 1;
}
}
}
}
CryptMemFree(validUsages.rgpszUsageIdentifier);
return ret;
}
/* Sets the CERT_KEY_PROV_INFO_PROP_ID property of context from pInfo, or, if
* pInfo is NULL, from the attributes of hProv.
*/
static void CertContext_SetKeyProvInfo(PCCERT_CONTEXT context,
const CRYPT_KEY_PROV_INFO *pInfo, HCRYPTPROV hProv)
{
CRYPT_KEY_PROV_INFO info = { 0 };
BOOL ret;
if (!pInfo)
{
DWORD size;
int len;
ret = CryptGetProvParam(hProv, PP_CONTAINER, NULL, &size, 0);
if (ret)
{
LPSTR szContainer = CryptMemAlloc(size);
if (szContainer)
{
ret = CryptGetProvParam(hProv, PP_CONTAINER,
(BYTE *)szContainer, &size, 0);
if (ret)
{
len = MultiByteToWideChar(CP_ACP, 0, szContainer, -1,
NULL, 0);
if (len)
{
info.pwszContainerName = CryptMemAlloc(len *
sizeof(WCHAR));
len = MultiByteToWideChar(CP_ACP, 0, szContainer, -1,
info.pwszContainerName, len);
}
}
CryptMemFree(szContainer);
}
}
ret = CryptGetProvParam(hProv, PP_NAME, NULL, &size, 0);
if (ret)
{
LPSTR szProvider = CryptMemAlloc(size);
if (szProvider)
{
ret = CryptGetProvParam(hProv, PP_NAME, (BYTE *)szProvider,
&size, 0);
if (ret)
{
len = MultiByteToWideChar(CP_ACP, 0, szProvider, -1,
NULL, 0);
if (len)
{
info.pwszProvName = CryptMemAlloc(len *
sizeof(WCHAR));
len = MultiByteToWideChar(CP_ACP, 0, szProvider, -1,
info.pwszProvName, len);
}
}
CryptMemFree(szProvider);
}
}
size = sizeof(info.dwKeySpec);
ret = CryptGetProvParam(hProv, PP_KEYSPEC, (LPBYTE)&info.dwKeySpec,
&size, 0);
if (!ret)
info.dwKeySpec = AT_SIGNATURE;
size = sizeof(info.dwProvType);
ret = CryptGetProvParam(hProv, PP_PROVTYPE, (LPBYTE)&info.dwProvType,
&size, 0);
if (!ret)
info.dwProvType = PROV_RSA_FULL;
pInfo = &info;
}
ret = CertSetCertificateContextProperty(context, CERT_KEY_PROV_INFO_PROP_ID,
0, pInfo);
if (pInfo == &info)
{
CryptMemFree(info.pwszContainerName);
CryptMemFree(info.pwszProvName);
}
}
/* Creates a signed certificate context from the unsigned, encoded certificate
* in blob, using the crypto provider hProv and the signature algorithm sigAlgo.
*/
static PCCERT_CONTEXT CRYPT_CreateSignedCert(const CRYPT_DER_BLOB *blob,
HCRYPTPROV hProv, PCRYPT_ALGORITHM_IDENTIFIER sigAlgo)
{
PCCERT_CONTEXT context = NULL;
BOOL ret;
DWORD sigSize = 0;
ret = CryptSignCertificate(hProv, AT_SIGNATURE, X509_ASN_ENCODING,
blob->pbData, blob->cbData, sigAlgo, NULL, NULL, &sigSize);
if (ret)
{
LPBYTE sig = CryptMemAlloc(sigSize);
ret = CryptSignCertificate(hProv, AT_SIGNATURE, X509_ASN_ENCODING,
blob->pbData, blob->cbData, sigAlgo, NULL, sig, &sigSize);
if (ret)
{
CERT_SIGNED_CONTENT_INFO signedInfo;
BYTE *encodedSignedCert = NULL;
DWORD encodedSignedCertSize =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -