crypt32: Add support for encoding OCSP requests.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2022-03-04 13:57:15 +01:00 committed by Alexandre Julliard
parent 39d6ac0d9c
commit 92821ebd49
2 changed files with 277 additions and 0 deletions

View File

@ -4472,6 +4472,195 @@ BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData,
ARRAY_SIZE(items), 0, NULL, pvData, pcbData);
}
static BOOL WINAPI CRYPT_AsnEncodeCertId(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
__TRY
{
const OCSP_CERT_ID *id = pvStructInfo;
struct AsnEncodeSequenceItem items[] = {
{ &id->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
{ &id->IssuerNameHash, CRYPT_AsnEncodeOctets, 0 },
{ &id->IssuerKeyHash, CRYPT_AsnEncodeOctets, 0 },
{ &id->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
};
ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeOCSPRequestEntry(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
__TRY
{
const OCSP_REQUEST_ENTRY *info = pvStructInfo;
struct AsnEncodeSequenceItem items[] = {
{ &info->CertId, CRYPT_AsnEncodeCertId, 0 },
};
if (info->cExtension)
{
FIXME("extensions not supported\n");
SetLastError(E_INVALIDARG);
ret = FALSE;
}
else
{
ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
}
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
struct ocsp_request_list
{
DWORD count;
OCSP_REQUEST_ENTRY *entry;
};
static BOOL WINAPI CRYPT_AsnEncodeOCSPRequestEntries(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
__TRY
{
DWORD bytesNeeded, dataLen, lenBytes, i;
const struct ocsp_request_list *list = pvStructInfo;
ret = TRUE;
for (i = 0, dataLen = 0; ret && i < list->count; i++)
{
DWORD size;
ret = CRYPT_AsnEncodeOCSPRequestEntry(dwCertEncodingType, lpszStructType, &list->entry[i],
dwFlags, pEncodePara, NULL, &size);
if (ret)
dataLen += size;
}
if (ret)
{
CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + dataLen;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; i < list->count; i++)
{
DWORD size = dataLen;
ret = CRYPT_AsnEncodeOCSPRequestEntry(dwCertEncodingType, lpszStructType,
&list->entry[i], dwFlags, pEncodePara, out, &size);
out += size;
dataLen -= size;
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeOCSPRequest(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
__TRY
{
const OCSP_REQUEST_INFO *info = pvStructInfo;
if (info->dwVersion != OCSP_REQUEST_V1)
{
FIXME("version %lu not supported\n", info->dwVersion);
SetLastError(E_INVALIDARG);
ret = FALSE;
}
else
{
if (info->cExtension)
{
FIXME("extensions not supported\n");
SetLastError(E_INVALIDARG);
ret = FALSE;
}
else
{
struct AsnConstructedItem name;
struct AsnEncodeSequenceItem items[2];
DWORD count = 1;
name.tag = 1;
name.pvStructInfo = info->pRequestorName;
name.encodeFunc = CRYPT_AsnEncodeAltNameEntry;
items[0].pvStructInfo = &name;
items[0].encodeFunc = CRYPT_AsnEncodeConstructed;
if (info->cRequestEntry)
{
items[1].pvStructInfo = &info->cRequestEntry;
items[1].encodeFunc = CRYPT_AsnEncodeOCSPRequestEntries;
count++;
}
ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
count, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
}
}
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
LPCSTR lpszStructType)
{
@ -4612,6 +4801,9 @@ static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
case LOWORD(CNG_RSA_PUBLIC_KEY_BLOB):
encodeFunc = CRYPT_AsnEncodeRsaPubKey_Bcrypt;
break;
case LOWORD(OCSP_REQUEST):
encodeFunc = CRYPT_AsnEncodeOCSPRequest;
break;
default:
FIXME("Unimplemented encoder for lpszStructType OID %d\n", LOWORD(lpszStructType));
}

View File

@ -8633,6 +8633,90 @@ static void testPortPublicKeyInfo(void)
ok(ret,"CryptAcquireContextA failed\n");
}
static void test_encodeOCSPRequestInfo(DWORD dwEncoding)
{
static const BYTE expected[] =
{0x30, 0x68, 0xa1, 0x17, 0x82, 0x15, 0x2a, 0x2e, 0x63, 0x6d, 0x2e, 0x73, 0x74, 0x65, 0x61, 0x6d,
0x70, 0x6f, 0x77, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x4d, 0x30, 0x4b, 0x30,
0x49, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0xe4, 0xe3,
0x95, 0xa2, 0x29, 0xd3, 0xd4, 0xc1, 0xc3, 0x1f, 0xf0, 0x98 ,0x0c, 0x0b, 0x4e, 0xc0, 0x09, 0x8a,
0xab, 0xd8, 0x04, 0x14, 0xb7, 0x6b, 0xa2, 0xea, 0xa8, 0xaa, 0x84, 0x8c, 0x79, 0xea, 0xb4, 0xda,
0x0f, 0x98, 0xb2, 0xc5, 0x95, 0x76, 0xb9, 0xf4, 0x02, 0x10, 0xb1, 0xc1, 0x87, 0x54, 0x54, 0xac,
0x1e, 0x55, 0x40, 0xfb, 0xef, 0xd9, 0x6d, 0x8f, 0x49, 0x08};
static const BYTE expected2[] =
{0x30, 0x81, 0xb6, 0xa1, 0x17, 0x82, 0x15, 0x2a, 0x2e, 0x63, 0x6d, 0x2e, 0x73, 0x74, 0x65, 0x61,
0x6d, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x81, 0x9a, 0x30,
0x4b, 0x30, 0x49, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
0xe4, 0xe3, 0x95, 0xa2, 0x29, 0xd3, 0xd4, 0xc1, 0xc3, 0x1f, 0xf0, 0x98, 0x0c, 0x0b, 0x4e, 0xc0,
0x09, 0x8a, 0xab, 0xd8, 0x04, 0x14, 0xb7, 0x6b, 0xa2, 0xea, 0xa8, 0xaa, 0x84, 0x8c, 0x79, 0xea,
0xb4, 0xda, 0x0f, 0x98, 0xb2, 0xc5, 0x95, 0x76, 0xb9, 0xf4, 0x02, 0x10, 0xb1, 0xc1, 0x87, 0x54,
0x54, 0xac, 0x1e, 0x55, 0x40, 0xfb, 0xef, 0xd9, 0x6d, 0x8f, 0x49, 0x08, 0x30, 0x4b, 0x30, 0x49,
0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0xe4, 0xe3, 0x95,
0xa2, 0x29, 0xd3, 0xd4, 0xc1, 0xc3, 0x1f, 0xf0, 0x98, 0x0c, 0x0b, 0x4e, 0xc0, 0x09, 0x8a, 0xab,
0xd8, 0x04, 0x14, 0xb7, 0x6b, 0xa2, 0xea, 0xa8, 0xaa, 0x84, 0x8c, 0x79, 0xea, 0xb4, 0xda, 0x0f,
0x98, 0xb2, 0xc5, 0x95, 0x76, 0xb9, 0xf4, 0x02, 0x10, 0xb1, 0xc1, 0x87, 0x54, 0x54, 0xac, 0x1e,
0x55, 0x40, 0xfb, 0xef, 0xd9, 0x6d, 0x8f, 0x49, 0x08};
static const BYTE issuer_name[] =
{0xe4, 0xe3 ,0x95, 0xa2, 0x29, 0xd3, 0xd4, 0xc1, 0xc3, 0x1f, 0xf0, 0x98, 0x0c, 0x0b, 0x4e, 0xc0,
0x09, 0x8a, 0xab, 0xd8};
static const BYTE issuer_key[] =
{0xb7, 0x6b, 0xa2, 0xea, 0xa8, 0xaa, 0x84, 0x8c, 0x79, 0xea, 0xb4, 0xda, 0x0f, 0x98, 0xb2, 0xc5,
0x95, 0x76, 0xb9, 0xf4};
static const BYTE serial[] =
{0x08, 0x49, 0x8f, 0x6d, 0xd9, 0xef, 0xfb, 0x40, 0x55, 0x1e, 0xac, 0x54, 0x54, 0x87, 0xc1, 0xb1};
OCSP_REQUEST_ENTRY entry[2];
CERT_ALT_NAME_ENTRY name;
OCSP_REQUEST_INFO info;
DWORD size;
BYTE *buf;
BOOL ret;
memset(&entry, 0, sizeof(entry));
entry[0].CertId.HashAlgorithm.pszObjId = (char *)szOID_OIWSEC_sha1;
entry[0].CertId.IssuerNameHash.cbData = sizeof(issuer_name);
entry[0].CertId.IssuerNameHash.pbData = (BYTE *)issuer_name;
entry[0].CertId.IssuerKeyHash.cbData = sizeof(issuer_key);
entry[0].CertId.IssuerKeyHash.pbData = (BYTE *)issuer_key;
entry[0].CertId.SerialNumber.cbData = sizeof(serial);
entry[0].CertId.SerialNumber.pbData = (BYTE *)serial;
name.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
name.pwszDNSName = (WCHAR *)L"*.cm.steampowered.com";
info.dwVersion = OCSP_REQUEST_V1;
info.pRequestorName = &name;
info.cRequestEntry = 1;
info.rgRequestEntry = entry;
info.cExtension = 0;
info.rgExtension = NULL;
size = 0;
SetLastError(0xdeadbeef);
ret = pCryptEncodeObjectEx(dwEncoding, OCSP_REQUEST, &info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
ok(ret, "got %08lx\n", GetLastError());
ok(size == sizeof(expected), "got %lu\n", size);
ok(!memcmp(buf, expected, sizeof(expected)), "unexpected value\n");
LocalFree(buf);
/* two entries */
entry[1].CertId.HashAlgorithm.pszObjId = (char *)szOID_OIWSEC_sha1;
entry[1].CertId.IssuerNameHash.cbData = sizeof(issuer_name);
entry[1].CertId.IssuerNameHash.pbData = (BYTE *)issuer_name;
entry[1].CertId.IssuerKeyHash.cbData = sizeof(issuer_key);
entry[1].CertId.IssuerKeyHash.pbData = (BYTE *)issuer_key;
entry[1].CertId.SerialNumber.cbData = sizeof(serial);
entry[1].CertId.SerialNumber.pbData = (BYTE *)serial;
info.cRequestEntry = 2;
size = 0;
SetLastError(0xdeadbeef);
ret = pCryptEncodeObjectEx(dwEncoding, OCSP_REQUEST, &info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
ok(ret, "got %08lx\n", GetLastError());
ok(size == sizeof(expected2), "got %lu\n", size);
ok(!memcmp(buf, expected2, sizeof(expected2)), "unexpected value\n");
LocalFree(buf);
}
START_TEST(encode)
{
static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
@ -8726,6 +8810,7 @@ START_TEST(encode)
test_encodeCertPolicyConstraints(encodings[i]);
test_decodeCertPolicyConstraints(encodings[i]);
test_decodeRsaPrivateKey(encodings[i]);
test_encodeOCSPRequestInfo(encodings[i]);
}
testPortPublicKeyInfo();
}