[PATCH 2/2] crypt32: Add support for encoding OCSP requests.

Hans Leidekker hans at codeweavers.com
Fri Mar 4 06:57:15 CST 2022


Signed-off-by: Hans Leidekker <hans at 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




More information about the wine-devel mailing list