Juan Lang : crypt32: Implement PKCS_ATTRIBUTE encoding/decoding.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Jun 13 06:14:05 CDT 2007


Module: wine
Branch: master
Commit: 97f2c658fd8f8ec4b3fd30b8638231a7753b2571
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=97f2c658fd8f8ec4b3fd30b8638231a7753b2571

Author: Juan Lang <juan_lang at yahoo.com>
Date:   Tue Jun 12 15:00:01 2007 -0700

crypt32: Implement PKCS_ATTRIBUTE encoding/decoding.

---

 dlls/crypt32/decode.c       |   50 +++++++++++++++++++
 dlls/crypt32/encode.c       |   35 +++++++++++++
 dlls/crypt32/tests/encode.c |  111 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 196 insertions(+), 0 deletions(-)

diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c
index ac0a175..b68d5d3 100644
--- a/dlls/crypt32/decode.c
+++ b/dlls/crypt32/decode.c
@@ -1795,6 +1795,53 @@ static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
     return ret;
 }
 
+static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    BOOL ret;
+    struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
+     CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB), TRUE,
+     offsetof(CRYPT_DER_BLOB, pbData) };
+    struct GenericArray *array = (struct GenericArray *)pvStructInfo;
+
+    TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+     pDecodePara, pvStructInfo, *pcbStructInfo);
+
+    ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
+     pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
+    return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    BOOL ret = FALSE;
+
+    __TRY
+    {
+        struct AsnDecodeSequenceItem items[] = {
+         { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
+           CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
+           offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
+         { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
+           CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
+           offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
+        };
+
+        ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
+         sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
+         pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        SetLastError(STATUS_ACCESS_VIOLATION);
+    }
+    __ENDTRY
+    return ret;
+}
+
 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
  PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
@@ -3628,6 +3675,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
         case (WORD)X509_UNICODE_NAME:
             decodeFunc = CRYPT_AsnDecodeUnicodeName;
             break;
+        case (WORD)PKCS_ATTRIBUTE:
+            decodeFunc = CRYPT_AsnDecodePKCSAttribute;
+            break;
         case (WORD)X509_UNICODE_NAME_VALUE:
             decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
             break;
diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c
index 7748598..9cf70b8 100644
--- a/dlls/crypt32/encode.c
+++ b/dlls/crypt32/encode.c
@@ -1362,6 +1362,38 @@ static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
     return ret;
 }
 
+static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
+ PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
+{
+    BOOL ret = FALSE;
+
+    __TRY
+    {
+        const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
+
+        if (!attr->pszObjId)
+            SetLastError(E_INVALIDARG);
+        else
+        {
+            struct AsnEncodeSequenceItem items[2] = {
+             { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
+             { &attr->cValue, CRYPT_DEREncodeSet, 0 },
+            };
+
+            ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
+             sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
+             pcbEncoded);
+        }
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        SetLastError(STATUS_ACCESS_VIOLATION);
+    }
+    __ENDTRY
+    return ret;
+}
+
 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
  LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
  PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
@@ -3071,6 +3103,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
         case (WORD)PKCS_CONTENT_INFO:
             encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
             break;
+        case (WORD)PKCS_ATTRIBUTE:
+            encodeFunc = CRYPT_AsnEncodePKCSAttribute;
+            break;
         case (WORD)X509_UNICODE_NAME_VALUE:
             encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
             break;
diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c
index a655602..0cf9752 100644
--- a/dlls/crypt32/tests/encode.c
+++ b/dlls/crypt32/tests/encode.c
@@ -4631,6 +4631,115 @@ static void test_decodePKCSContentInfo(DWORD dwEncoding)
     }
 }
 
+static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
+ 0x00 };
+static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
+ 0x01 };
+static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
+ 0x02,0x01,0x01 };
+
+static void test_encodePKCSAttribute(DWORD dwEncoding)
+{
+    CRYPT_ATTRIBUTE attr = { 0 };
+    BOOL ret;
+    LPBYTE buf = NULL;
+    DWORD size = 0;
+    CRYPT_ATTR_BLOB blob;
+    char oid[] = "1.2.3";
+
+    SetLastError(0xdeadbeef);
+    ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
+     CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
+    ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
+     "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
+     CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
+    ok(!ret && GetLastError() == E_INVALIDARG,
+     "Expected E_INVALIDARG, got %x\n", GetLastError());
+    attr.pszObjId = oid;
+    ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
+     CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
+    ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
+    if (buf)
+    {
+        ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
+        ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
+        LocalFree(buf);
+    }
+    blob.cbData = sizeof(bogusDER);
+    blob.pbData = bogusDER;
+    attr.cValue = 1;
+    attr.rgValue = &blob;
+    ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
+     CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
+    ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
+    if (buf)
+    {
+        ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
+        ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
+        LocalFree(buf);
+    }
+    blob.pbData = (BYTE *)ints[0].encoded;
+    blob.cbData = ints[0].encoded[1] + 2;
+    ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
+     CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
+    if (buf)
+    {
+        ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
+        ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
+        LocalFree(buf);
+    }
+}
+
+static void test_decodePKCSAttribute(DWORD dwEncoding)
+{
+    BOOL ret;
+    LPBYTE buf = NULL;
+    DWORD size = 0;
+    CRYPT_ATTRIBUTE *attr;
+
+    ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
+     emptyPKCSAttr, sizeof(emptyPKCSAttr),
+     CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
+    ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
+    if (buf)
+    {
+        attr = (CRYPT_ATTRIBUTE *)buf;
+
+        ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
+         attr->pszObjId);
+        ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
+        LocalFree(buf);
+    }
+    SetLastError(0xdeadbeef);
+    ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
+     bogusPKCSAttr, sizeof(bogusPKCSAttr),
+     CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
+    /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
+     * I doubt an app depends on that.
+     */
+    ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
+     GetLastError() == CRYPT_E_ASN1_CORRUPT),
+     "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
+     GetLastError());
+    ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
+     intPKCSAttr, sizeof(intPKCSAttr),
+     CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
+    ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
+    if (buf)
+    {
+        attr = (CRYPT_ATTRIBUTE *)buf;
+
+        ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
+         attr->pszObjId);
+        ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
+        ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
+         "Unexpected size %d\n", attr->rgValue[0].cbData);
+        ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
+         attr->rgValue[0].cbData), "Unexpected value\n");
+    }
+}
 /* Free *pInfo with HeapFree */
 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
 {
@@ -4840,6 +4949,8 @@ START_TEST(encode)
         test_decodeAuthorityKeyId2(encodings[i]);
         test_encodePKCSContentInfo(encodings[i]);
         test_decodePKCSContentInfo(encodings[i]);
+        test_encodePKCSAttribute(encodings[i]);
+        test_decodePKCSAttribute(encodings[i]);
     }
     testPortPublicKeyInfo();
 }




More information about the wine-cvs mailing list