crypt32(4/11): Implement getting signer info from a decoded signed message

Juan Lang juan.lang at gmail.com
Mon Jul 30 14:18:27 CDT 2007


--Juan
-------------- next part --------------
From c8b7b508c13dfff31af32d10832f2ae25f844f78 Mon Sep 17 00:00:00 2001
From: Juan Lang <juanlang at juan.corp.google.com>
Date: Mon, 30 Jul 2007 12:05:15 -0700
Subject: [PATCH] Implement getting signer info from a decoded signed message
---
 dlls/crypt32/msg.c       |  179 ++++++++++++++++++++++++++++++++++++++++++----
 dlls/crypt32/tests/msg.c |    1 
 2 files changed, 164 insertions(+), 16 deletions(-)

diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c
index 0f33382..aca6a03 100644
--- a/dlls/crypt32/msg.c
+++ b/dlls/crypt32/msg.c
@@ -608,7 +608,7 @@ typedef struct _CSignerHandles
     HCRYPTKEY        key;
 } CSignerHandles;
 
-static BOOL CRYPT_CopyBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in)
+static BOOL CRYPT_ConstructBlob(CRYPT_DATA_BLOB *out, const CRYPT_DATA_BLOB *in)
 {
     BOOL ret = TRUE;
 
@@ -632,7 +632,7 @@ typedef struct _BlobArray
     PCRYPT_DATA_BLOB blobs;
 } BlobArray;
 
-static BOOL CRYPT_CopyBlobArray(BlobArray *out, const BlobArray *in)
+static BOOL CRYPT_ConstructBlobArray(BlobArray *out, const BlobArray *in)
 {
     BOOL ret = TRUE;
 
@@ -646,7 +646,7 @@ static BOOL CRYPT_CopyBlobArray(BlobArra
 
             memset(out->blobs, 0, out->cBlobs * sizeof(CRYPT_DATA_BLOB));
             for (i = 0; ret && i < out->cBlobs; i++)
-                ret = CRYPT_CopyBlob(&out->blobs[i], &in->blobs[i]);
+                ret = CRYPT_ConstructBlob(&out->blobs[i], &in->blobs[i]);
         }
         else
             ret = FALSE;
@@ -663,7 +663,8 @@ static void CRYPT_FreeBlobArray(BlobArra
     CryptMemFree(array->blobs);
 }
 
-static BOOL CRYPT_CopyAttribute(CRYPT_ATTRIBUTE *out, const CRYPT_ATTRIBUTE *in)
+static BOOL CRYPT_ConstructAttribute(CRYPT_ATTRIBUTE *out,
+ const CRYPT_ATTRIBUTE *in)
 {
     BOOL ret;
 
@@ -671,7 +672,7 @@ static BOOL CRYPT_CopyAttribute(CRYPT_AT
     if (out->pszObjId)
     {
         strcpy(out->pszObjId, in->pszObjId);
-        ret = CRYPT_CopyBlobArray((BlobArray *)&out->cValue,
+        ret = CRYPT_ConstructBlobArray((BlobArray *)&out->cValue,
          (const BlobArray *)&in->cValue);
     }
     else
@@ -679,7 +680,7 @@ static BOOL CRYPT_CopyAttribute(CRYPT_AT
     return ret;
 }
 
-static BOOL CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out,
+static BOOL CRYPT_ConstructAttributes(CRYPT_ATTRIBUTES *out,
  const CRYPT_ATTRIBUTES *in)
 {
     BOOL ret = TRUE;
@@ -694,7 +695,7 @@ static BOOL CRYPT_CopyAttributes(CRYPT_A
 
             memset(out->rgAttr, 0, out->cAttr * sizeof(CRYPT_ATTRIBUTE));
             for (i = 0; ret && i < out->cAttr; i++)
-                ret = CRYPT_CopyAttribute(&out->rgAttr[i], &in->rgAttr[i]);
+                ret = CRYPT_ConstructAttribute(&out->rgAttr[i], &in->rgAttr[i]);
         }
         else
             ret = FALSE;
@@ -725,24 +726,24 @@ static BOOL CSignerInfo_Construct(CSigne
     {
         /* Note: needs to change if CMS fields are supported */
         info->dwVersion = CMSG_SIGNER_INFO_V1;
-        ret = CRYPT_CopyBlob(&info->Issuer, &in->pCertInfo->Issuer);
+        ret = CRYPT_ConstructBlob(&info->Issuer, &in->pCertInfo->Issuer);
         if (ret)
-            ret = CRYPT_CopyBlob(&info->SerialNumber,
+            ret = CRYPT_ConstructBlob(&info->SerialNumber,
              &in->pCertInfo->SerialNumber);
         /* Assumption:  algorithm IDs will point to static strings, not
          * stack-based ones, so copying the pointer values is safe.
          */
         info->HashAlgorithm.pszObjId = in->HashAlgorithm.pszObjId;
         if (ret)
-            ret = CRYPT_CopyBlob(&info->HashAlgorithm.Parameters,
+            ret = CRYPT_ConstructBlob(&info->HashAlgorithm.Parameters,
              &in->HashAlgorithm.Parameters);
         memset(&info->HashEncryptionAlgorithm, 0,
          sizeof(info->HashEncryptionAlgorithm));
         if (ret)
-            ret = CRYPT_CopyAttributes(&info->AuthAttrs,
+            ret = CRYPT_ConstructAttributes(&info->AuthAttrs,
              (CRYPT_ATTRIBUTES *)&in->cAuthAttr);
         if (ret)
-            ret = CRYPT_CopyAttributes(&info->UnauthAttrs,
+            ret = CRYPT_ConstructAttributes(&info->UnauthAttrs,
              (CRYPT_ATTRIBUTES *)&in->cUnauthAttr);
     }
     return ret;
@@ -918,7 +919,7 @@ static BOOL CRYPT_AppendAttribute(CRYPT_
      (out->cAttr + 1) * sizeof(CRYPT_ATTRIBUTE));
     if (out->rgAttr)
     {
-        ret = CRYPT_CopyAttribute(&out->rgAttr[out->cAttr], in);
+        ret = CRYPT_ConstructAttribute(&out->rgAttr[out->cAttr], in);
         if (ret)
             out->cAttr++;
     }
@@ -1162,10 +1163,10 @@ static HCRYPTMSG CSignedEncodeMsg_Open(D
                 ret = FALSE;
         }
         if (ret)
-            ret = CRYPT_CopyBlobArray((BlobArray *)&msg->info.cCertEncoded,
+            ret = CRYPT_ConstructBlobArray((BlobArray *)&msg->info.cCertEncoded,
              (const BlobArray *)&info->cCertEncoded);
         if (ret)
-            ret = CRYPT_CopyBlobArray((BlobArray *)&msg->info.cCrlEncoded,
+            ret = CRYPT_ConstructBlobArray((BlobArray *)&msg->info.cCrlEncoded,
              (const BlobArray *)&info->cCrlEncoded);
         if (!ret)
         {
@@ -1560,6 +1561,142 @@ static BOOL CDecodeHashMsg_GetParam(CDec
     return ret;
 }
 
+/* nextData is an in/out parameter - on input it's the memory location in
+ * which a copy of in's data should be made, and on output it's the memory
+ * location immediately after out's copy of in's data.
+ */
+static inline void CRYPT_CopyBlob(CRYPT_DATA_BLOB *out,
+ const CRYPT_DATA_BLOB *in, LPBYTE *nextData)
+{
+    out->cbData = in->cbData;
+    if (in->cbData)
+    {
+        out->pbData = *nextData;
+        memcpy(out->pbData, in->pbData, in->cbData);
+        *nextData += in->cbData;
+    }
+}
+
+static inline void CRYPT_CopyAlgorithmId(CRYPT_ALGORITHM_IDENTIFIER *out,
+ const CRYPT_ALGORITHM_IDENTIFIER *in, LPBYTE *nextData)
+{
+    if (in->pszObjId)
+    {
+        out->pszObjId = (LPSTR)*nextData;
+        strcpy(out->pszObjId, in->pszObjId);
+        *nextData += strlen(out->pszObjId) + 1;
+    }
+    CRYPT_CopyBlob(&out->Parameters, &in->Parameters, nextData);
+}
+
+static inline void CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out,
+ const CRYPT_ATTRIBUTES *in, LPBYTE *nextData)
+{
+    out->cAttr = in->cAttr;
+    if (in->cAttr)
+    {
+        DWORD i;
+
+        if ((*nextData - (LPBYTE)0) % sizeof(DWORD))
+            *nextData += (*nextData - (LPBYTE)0) % sizeof(DWORD);
+        out->rgAttr = (CRYPT_ATTRIBUTE *)*nextData;
+        *nextData += in->cAttr * sizeof(CRYPT_ATTRIBUTE);
+        for (i = 0; i < in->cAttr; i++)
+        {
+            if (in->rgAttr[i].pszObjId)
+            {
+                out->rgAttr[i].pszObjId = (LPSTR)*nextData;
+                strcpy(out->rgAttr[i].pszObjId, in->rgAttr[i].pszObjId);
+                *nextData += strlen(in->rgAttr[i].pszObjId) + 1;
+            }
+            if (in->rgAttr[i].cValue)
+            {
+                DWORD j;
+
+                out->rgAttr[i].cValue = in->rgAttr[i].cValue;
+                if ((*nextData - (LPBYTE)0) % sizeof(DWORD))
+                    *nextData += (*nextData - (LPBYTE)0) % sizeof(DWORD);
+                out->rgAttr[i].rgValue = (PCRYPT_DATA_BLOB)*nextData;
+                for (j = 0; j < in->rgAttr[i].cValue; j++)
+                    CRYPT_CopyBlob(&out->rgAttr[i].rgValue[j],
+                     &in->rgAttr[i].rgValue[j], nextData);
+            }
+        }
+    }
+}
+
+static DWORD CRYPT_SizeOfAttributes(const CRYPT_ATTRIBUTES *attr)
+{
+    DWORD size = attr->cAttr * sizeof(CRYPT_ATTRIBUTE), i, j;
+
+    for (i = 0; i < attr->cAttr; i++)
+    {
+        if (attr->rgAttr[i].pszObjId)
+            size += strlen(attr->rgAttr[i].pszObjId) + 1;
+        /* align pointer */
+        if (size % sizeof(DWORD))
+            size += size % sizeof(DWORD);
+        size += attr->rgAttr[i].cValue * sizeof(CRYPT_DATA_BLOB);
+        for (j = 0; j < attr->rgAttr[i].cValue; j++)
+            size += attr->rgAttr[i].rgValue[j].cbData;
+    }
+    return size;
+}
+
+static BOOL CRYPT_CopySignerInfo(void *pvData, DWORD *pcbData,
+ const CMSG_SIGNER_INFO *in)
+{
+    DWORD size = sizeof(CMSG_SIGNER_INFO);
+    BOOL ret;
+
+    size += in->Issuer.cbData;
+    size += in->SerialNumber.cbData;
+    if (in->HashAlgorithm.pszObjId)
+        size += strlen(in->HashAlgorithm.pszObjId) + 1;
+    size += in->HashAlgorithm.Parameters.cbData;
+    if (in->HashEncryptionAlgorithm.pszObjId)
+        size += strlen(in->HashEncryptionAlgorithm.pszObjId) + 1;
+    size += in->HashEncryptionAlgorithm.Parameters.cbData;
+    size += in->EncryptedHash.cbData;
+    /* align pointer */
+    if (size % sizeof(DWORD))
+        size += size % sizeof(DWORD);
+    size += CRYPT_SizeOfAttributes(&in->AuthAttrs);
+    size += CRYPT_SizeOfAttributes(&in->UnauthAttrs);
+    if (!pvData)
+    {
+        *pcbData = size;
+        ret = TRUE;
+    }
+    else if (*pcbData < size)
+    {
+        *pcbData = size;
+        SetLastError(ERROR_MORE_DATA);
+        ret = FALSE;
+    }
+    else
+    {
+        LPBYTE nextData = (BYTE *)pvData + sizeof(CMSG_SIGNER_INFO);
+        CMSG_SIGNER_INFO *out = (CMSG_SIGNER_INFO *)pvData;
+
+        out->dwVersion = in->dwVersion;
+        CRYPT_CopyBlob(&out->Issuer, &in->Issuer, &nextData);
+        CRYPT_CopyBlob(&out->SerialNumber, &in->SerialNumber, &nextData);
+        CRYPT_CopyAlgorithmId(&out->HashAlgorithm, &in->HashAlgorithm,
+         &nextData);
+        CRYPT_CopyAlgorithmId(&out->HashEncryptionAlgorithm,
+         &in->HashEncryptionAlgorithm, &nextData);
+        CRYPT_CopyBlob(&out->EncryptedHash, &in->EncryptedHash, &nextData);
+        /* align pointer */
+        if ((nextData - (LPBYTE)0) % sizeof(DWORD))
+            nextData += (nextData - (LPBYTE)0) % sizeof(DWORD);
+        CRYPT_CopyAttributes(&out->AuthAttrs, &in->AuthAttrs, &nextData);
+        CRYPT_CopyAttributes(&out->UnauthAttrs, &in->UnauthAttrs, &nextData);
+        ret = TRUE;
+    }
+    return ret;
+}
+
 static BOOL CDecodeSignedMsg_GetParam(CDecodeMsg *msg, DWORD dwParamType,
  DWORD dwIndex, void *pvData, DWORD *pcbData)
 {
@@ -1598,6 +1735,18 @@ static BOOL CDecodeSignedMsg_GetParam(CD
         else
             SetLastError(CRYPT_E_INVALID_MSG_TYPE);
         break;
+    case CMSG_SIGNER_INFO_PARAM:
+        if (msg->u.signedInfo)
+        {
+            if (dwIndex >= msg->u.signedInfo->cSignerInfo)
+                SetLastError(CRYPT_E_INVALID_INDEX);
+            else
+                ret = CRYPT_CopySignerInfo(pvData, pcbData,
+                 &msg->u.signedInfo->rgSignerInfo[dwIndex]);
+        }
+        else
+            SetLastError(CRYPT_E_INVALID_MSG_TYPE);
+        break;
     case CMSG_CERT_COUNT_PARAM:
         if (msg->u.signedInfo)
             ret = CRYPT_CopyParam(pvData, pcbData,
diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c
index 0e863f0..28b11e5 100644
--- a/dlls/crypt32/tests/msg.c
+++ b/dlls/crypt32/tests/msg.c
@@ -1988,7 +1988,6 @@ static void test_decode_msg_get_param(vo
     ok(value == 1, "Expected 1 signer, got %d\n", value);
     size = 0;
     ret = CryptMsgGetParam(msg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &size);
-    todo_wine
     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
     if (ret)
         buf = CryptMemAlloc(size);
-- 
1.4.1


More information about the wine-patches mailing list