Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/crypt32/encode.c | 192 ++++++++++++++++++++++++++++++++++++
dlls/crypt32/tests/encode.c | 85 ++++++++++++++++
2 files changed, 277 insertions(+)
diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c
index 7668d0ddb2c..a506f197be1 100644
--- a/dlls/crypt32/encode.c
+++ b/dlls/crypt32/encode.c
@@ -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));
}
diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c
index 3ba6b2680a7..9d12223c54c 100644
--- a/dlls/crypt32/tests/encode.c
+++ b/dlls/crypt32/tests/encode.c
@@ -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();
}
--
2.30.2