From ff0760dcd39adae42cfa8bd3dca460de1e099eed Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Wed, 27 Aug 2008 14:15:57 -0700 Subject: [PATCH] crypt32: Implement CTL decoding. --- dlls/crypt32/decode.c | 118 ++++++++++++++++++++++++++++++++++++ dlls/crypt32/tests/encode.c | 16 +---- 2 files changed, 121 insertions(+), 13 deletions(-) diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c index 39a4684f68d..eb782d3e018 100644 --- a/dlls/crypt32/decode.c +++ b/dlls/crypt32/decode.c @@ -112,6 +112,9 @@ static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded, static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded); +static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded, + DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, + DWORD *pcbDecoded); /* Gets the number of length bytes from the given (leading) length byte */ #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f)) @@ -2033,6 +2036,116 @@ static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded, return ret; } +static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded, + DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) +{ + BOOL ret; + struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, + CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 }; + CTL_USAGE *usage = (CTL_USAGE *)pvStructInfo; + + ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, + NULL, pvStructInfo, pcbStructInfo, pcbDecoded, + usage ? usage->rgpszUsageIdentifier : NULL); + return ret; +} + +static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded, + DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) +{ + struct AsnDecodeSequenceItem items[] = { + { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier), + CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE, + offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 }, + { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute), + CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), FALSE, + TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 }, + }; + BOOL ret = TRUE; + CTL_ENTRY *entry = (CTL_ENTRY *)pvStructInfo; + + TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry, + *pcbStructInfo); + + ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), + pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, + pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL); + return ret; +} + +static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded, + DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) +{ + BOOL ret; + struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, + CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE, + offsetof(CTL_ENTRY, SubjectIdentifier.pbData) }; + struct GenericArray *entries = (struct GenericArray *)pvStructInfo; + + TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, + pvStructInfo, *pcbStructInfo, pcbDecoded); + + ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, + NULL, pvStructInfo, pcbStructInfo, pcbDecoded, + entries ? entries->rgItems : NULL); + return ret; +} + +static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType, + LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, + PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) +{ + BOOL ret = FALSE; + + TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, + pDecodePara, pvStructInfo, *pcbStructInfo); + + __TRY + { + struct AsnDecodeSequenceItem items[] = { + { ASN_INTEGER, offsetof(CTL_INFO, dwVersion), + CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 }, + { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage), + CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE, + offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 }, + { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier), + CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE, + TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 }, + { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber), + CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), + TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 }, + { 0, offsetof(CTL_INFO, ThisUpdate), + CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, + 0 }, + { 0, offsetof(CTL_INFO, NextUpdate), + CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE, + 0 }, + { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm), + CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), + FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 }, + { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry), + CRYPT_AsnDecodeCTLEntries, sizeof(struct GenericArray), + TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 }, + { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension), + CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE, + offsetof(CTL_INFO, rgExtension), 0 }, + }; + + TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, + pDecodePara, pvStructInfo, *pcbStructInfo); + + ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), + pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, + pcbStructInfo, NULL, NULL); + } + __EXCEPT_PAGE_FAULT + { + SetLastError(STATUS_ACCESS_VIOLATION); + } + __ENDTRY + return ret; +} + static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) @@ -4750,6 +4863,9 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType, case LOWORD(X509_ENHANCED_KEY_USAGE): decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage; break; + case LOWORD(PKCS_CTL): + decodeFunc = CRYPT_AsnDecodeCTL; + break; case LOWORD(PKCS_SMIME_CAPABILITIES): decodeFunc = CRYPT_AsnDecodeSMIMECapabilities; break; @@ -4810,6 +4926,8 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType, decodeFunc = CRYPT_AsnDecodeNameConstraints; else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS)) decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess; + else if (!strcmp(lpszStructType, szOID_CTL)) + decodeFunc = CRYPT_AsnDecodeCTL; return decodeFunc; } diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index 42209f00078..3f5b7638d14 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -5303,7 +5303,6 @@ static void test_decodeCTL(DWORD dwEncoding) memset(&info, 0, sizeof(info)); ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) { @@ -5315,7 +5314,6 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1, sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) { @@ -5329,7 +5327,6 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier, sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) { @@ -5343,7 +5340,6 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier, sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) { @@ -5357,7 +5353,6 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber, sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) { @@ -5370,7 +5365,6 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate, sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) { @@ -5382,7 +5376,6 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate, sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) { @@ -5398,7 +5391,6 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId, sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) { @@ -5410,9 +5402,9 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry, sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine - ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD, - "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); + ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT), + "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n", + GetLastError()); info.SubjectAlgorithm.Parameters.cbData = 0; info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0; info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0; @@ -5433,7 +5425,6 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry, sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) { @@ -5454,7 +5445,6 @@ static void test_decodeCTL(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries, sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (buf) {