crypt32(3/20): Introduce function to encode an array of items as a set

Juan Lang juan.lang at gmail.com
Mon Jul 23 20:26:59 CDT 2007


--Juan
-------------- next part --------------
From 1069b25d00aae52a09cfdd3eb256a51ddb89c1db Mon Sep 17 00:00:00 2001
From: Juan Lang <juanlang at juan.corp.google.com>
Date: Mon, 23 Jul 2007 15:29:15 -0700
Subject: [PATCH] Introduce function to encode an array of items as a set
---
 dlls/crypt32/encode.c |  126 +++++++++++++++++++++++++++++++++++--------------
 1 files changed, 89 insertions(+), 37 deletions(-)

diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c
index a7cb661..e2fcc99 100644
--- a/dlls/crypt32/encode.c
+++ b/dlls/crypt32/encode.c
@@ -1210,6 +1210,91 @@ static BOOL WINAPI CRYPT_DEREncodeSet(DW
     return ret;
 }
 
+struct DERSetDescriptor
+{
+    DWORD                   cItems;
+    const void             *items;
+    size_t                  itemSize;
+    off_t                   itemOffset;
+    CryptEncodeObjectExFunc encode;
+};
+
+static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
+ PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
+{
+    const struct DERSetDescriptor *desc =
+     (const struct DERSetDescriptor *)pvStructInfo;
+    CRYPT_SET_OF setOf = { 0, NULL };
+    BOOL ret = TRUE;
+    DWORD i;
+
+    if (desc->cItems)
+    {
+        setOf.rgValue = CryptMemAlloc(setOf.cValue * sizeof(CRYPT_DER_BLOB));
+        if (!setOf.rgValue)
+            ret = FALSE;
+        else
+        {
+            setOf.cValue = desc->cItems;
+            memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
+        }
+    }
+    for (i = 0; ret && i < setOf.cValue; i++)
+    {
+        ret = desc->encode(dwCertEncodingType, lpszStructType,
+         (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
+         0, NULL, NULL, &setOf.rgValue[i].cbData);
+        if (ret)
+        {
+            setOf.rgValue[i].pbData = CryptMemAlloc(setOf.rgValue[i].cbData);
+            if (!setOf.rgValue[i].pbData)
+                ret = FALSE;
+            else
+                ret = desc->encode(dwCertEncodingType, lpszStructType,
+                 (const BYTE *)desc->items + i * desc->itemSize +
+                 desc->itemOffset, 0, NULL, setOf.rgValue[i].pbData,
+                 &setOf.rgValue[i].cbData);
+        }
+        /* Some functions propagate their errors through the size */
+        if (!ret)
+            *pcbEncoded = setOf.rgValue[i].cbData;
+    }
+    if (ret)
+    {
+        DWORD bytesNeeded = 0, lenBytes;
+        BOOL ret;
+
+        for (i = 0; i < setOf.cValue; i++)
+            bytesNeeded += setOf.rgValue[i].cbData;
+        CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
+        bytesNeeded += 1 + lenBytes;
+        if (!pbEncoded)
+            *pcbEncoded = bytesNeeded;
+        else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
+         pbEncoded, pcbEncoded, bytesNeeded)))
+        {
+            if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
+                pbEncoded = *(BYTE **)pbEncoded;
+            qsort(setOf.rgValue, setOf.cValue, sizeof(CRYPT_DER_BLOB),
+             BLOBComp);
+            *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
+            CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
+            pbEncoded += lenBytes;
+            for (i = 0; i < setOf.cValue; i++)
+            {
+                memcpy(pbEncoded, setOf.rgValue[i].pbData,
+                 setOf.rgValue[i].cbData);
+                pbEncoded += setOf.rgValue[i].cbData;
+            }
+        }
+    }
+    for (i = 0; i < setOf.cValue; i++)
+        CryptMemFree(setOf.rgValue[i].pbData);
+    CryptMemFree(setOf.rgValue);
+    return ret;
+}
+
 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
  CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
  DWORD *pcbEncoded)
@@ -1394,55 +1479,22 @@ static BOOL WINAPI CRYPT_AsnEncodePKCSAt
  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
 {
     BOOL ret = FALSE;
-    CRYPT_SET_OF setOf = { 0, NULL };
 
     __TRY
     {
-        DWORD i;
         const CRYPT_ATTRIBUTES *attributes =
          (const CRYPT_ATTRIBUTES *)pvStructInfo;
+        struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
+         sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
 
-        ret = TRUE;
-        if (attributes->cAttr)
-        {
-            setOf.cValue = attributes->cAttr;
-            setOf.rgValue = CryptMemAlloc(attributes->cAttr *
-             sizeof(CRYPT_DER_BLOB));
-            if (!setOf.rgValue)
-                ret = FALSE;
-            else
-                memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
-        }
-        for (i = 0; ret && i < attributes->cAttr; i++)
-        {
-            ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
-             &attributes->rgAttr[i], 0, NULL, NULL, &setOf.rgValue[i].cbData);
-            if (ret)
-            {
-                setOf.rgValue[i].pbData =
-                 CryptMemAlloc(setOf.rgValue[i].cbData);
-                if (!setOf.rgValue[i].pbData)
-                    ret = FALSE;
-                else
-                {
-                    ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
-                     &attributes->rgAttr[i], 0, NULL, setOf.rgValue[i].pbData,
-                     &setOf.rgValue[i].cbData);
-                }
-            }
-        }
-        if (ret)
-            ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, dwFlags,
-             pEncodePara, pbEncoded, pcbEncoded);
-        for (i = 0; i < setOf.cValue; i++)
-            CryptMemFree(setOf.rgValue[i].pbData);
+        ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
+         &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
     }
     __EXCEPT_PAGE_FAULT
     {
         SetLastError(STATUS_ACCESS_VIOLATION);
     }
     __ENDTRY
-    CryptMemFree(setOf.rgValue);
     return ret;
 }
 
-- 
1.4.1


More information about the wine-patches mailing list