Module: wine Branch: master Commit: 97f2c658fd8f8ec4b3fd30b8638231a7753b2571 URL: http://source.winehq.org/git/wine.git/?a=commit;h=97f2c658fd8f8ec4b3fd30b863...
Author: Juan Lang juan_lang@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(); }