From c58cb379ebf5875ca241b609765554a9099e0e85 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Wed, 25 Jul 2007 18:13:45 -0700 Subject: [PATCH] crypt32: Test and fix encoding and decoding of attributes in PKCS signers. --- dlls/crypt32/decode.c | 27 ++++++++++-------- dlls/crypt32/encode.c | 32 +++++++++++++-------- dlls/crypt32/tests/encode.c | 55 +++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 22 deletions(-) diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c index 29e1a2d3278..52e207ecd38 100644 --- a/dlls/crypt32/decode.c +++ b/dlls/crypt32/decode.c @@ -1896,9 +1896,8 @@ static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal( DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) { - struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, - CRYPT_AsnDecodePKCSAttribute, sizeof(CRYPT_ATTRIBUTE), TRUE, - offsetof(CRYPT_ATTRIBUTE, pszObjId) }; + struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodePKCSAttribute, + sizeof(CRYPT_ATTRIBUTE), TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) }; PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo; BOOL ret; @@ -1921,8 +1920,12 @@ static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType, { DWORD bytesNeeded; - if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, + if (!cbEncoded) + SetLastError(CRYPT_E_ASN1_EOD); + else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF)) + SetLastError(CRYPT_E_ASN1_CORRUPT); + else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal( + dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded))) { if (!pvStructInfo) @@ -3813,19 +3816,21 @@ static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType, { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 }, + { ASN_CONSTRUCTOR | ASN_CONTEXT | 0, + offsetof(CMSG_SIGNER_INFO, AuthAttrs), + CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), + TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 }, { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm.pszObjId), 0 }, - { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, AuthAttrs), - CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), - TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 }, - { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, UnauthAttrs), - CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), - TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 }, { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash), CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 }, + { ASN_CONSTRUCTOR | ASN_CONTEXT | 1, + offsetof(CMSG_SIGNER_INFO, UnauthAttrs), + CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), + TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 }, }; ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c index e6695cf9a0c..b653a0dc644 100644 --- a/dlls/crypt32/encode.c +++ b/dlls/crypt32/encode.c @@ -3201,26 +3201,36 @@ static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType, { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 }, { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, - { &info->HashEncryptionAlgorithm, - CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, }; - DWORD cItem = 4; + struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; + DWORD cItem = 3, cSwapped = 0; if (info->AuthAttrs.cAttr) { - items[cItem].pvStructInfo = &info->AuthAttrs; - items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes; - cItem++; - } - if (info->UnauthAttrs.cAttr) - { - items[cItem].pvStructInfo = &info->UnauthAttrs; - items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes; + swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; + swapped[cSwapped].pvStructInfo = &info->AuthAttrs; + swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; + items[cItem].pvStructInfo = &swapped[cSwapped]; + items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; + cSwapped++; cItem++; } + items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm; + items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; + cItem++; items[cItem].pvStructInfo = &info->EncryptedHash; items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; cItem++; + if (info->UnauthAttrs.cAttr) + { + swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; + swapped[cSwapped].pvStructInfo = &info->UnauthAttrs; + swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; + items[cItem].pvStructInfo = &swapped[cSwapped]; + items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; + cSwapped++; + cItem++; + } ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded); } diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index 8173a128f25..467619a964b 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -4924,6 +4924,14 @@ static const BYTE PKCSSignerWithHash[] = { 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d, 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; +static const BYTE PKCSSignerWithAuthAttr[] = { +0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, +0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, +0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06, +0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55, +0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30, +0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05, +0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; static void test_encodePKCSSignerInfo(DWORD dwEncoding) { @@ -4932,6 +4940,10 @@ static void test_encodePKCSSignerInfo(DWORD dwEncoding) LPBYTE buf = NULL; DWORD size = 0; CMSG_SIGNER_INFO info = { 0 }; + char oid_common_name[] = szOID_COMMON_NAME; + CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName), + (LPBYTE)encodedCommonName }; + CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName }; SetLastError(0xdeadbeef); ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, @@ -5053,6 +5065,29 @@ static void test_encodePKCSSignerInfo(DWORD dwEncoding) LocalFree(buf); } } + info.AuthAttrs.cAttr = 1; + info.AuthAttrs.rgAttr = &attr; + SetLastError(0xdeadbeef); + ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + if (!(dwEncoding & PKCS_7_ASN_ENCODING)) + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + else + { + ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); + if (buf) + { + ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n", + size); + if (size == sizeof(PKCSSignerWithAuthAttr)) + ok(!memcmp(buf, PKCSSignerWithAuthAttr, size), + "Unexpected value\n"); + else + ok(0, "Unexpected value\n"); + LocalFree(buf); + } + } } static void test_decodePKCSSignerInfo(DWORD dwEncoding) @@ -5157,6 +5192,26 @@ static void test_decodePKCSSignerInfo(DWORD dwEncoding) "Unexpected value\n"); LocalFree(buf); } + ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, + PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr), + CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + if (buf) + { + info = (CMSG_SIGNER_INFO *)buf; + ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n", + info->AuthAttrs.cAttr); + ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME), + "Expected %s, got %s\n", szOID_COMMON_NAME, + info->AuthAttrs.rgAttr[0].pszObjId); + ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n", + info->AuthAttrs.rgAttr[0].cValue); + ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData == + sizeof(encodedCommonName), "Unexpected size %d\n", + info->AuthAttrs.rgAttr[0].rgValue[0].cbData); + ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData, + encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n"); + LocalFree(buf); + } } /* Free *pInfo with HeapFree */