diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c index c83b154afe..d3f3322b67 100644 --- a/dlls/crypt32/decode.c +++ b/dlls/crypt32/decode.c @@ -3659,6 +3659,86 @@ static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType, return ret; } +static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType, + LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, + PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) +{ + BOOL ret; + struct AsnDecodeSequenceItem items[] = { + { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob, + sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, + Issuer.pbData) }, + { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber), + CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, + TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 }, + }; + CERT_ISSUER_SERIAL_NUMBER *issuerSerial = + (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo; + + TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, + pDecodePara, pvStructInfo, *pcbStructInfo); + + ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, + sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, + dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, + issuerSerial ? issuerSerial->Issuer.pbData : NULL); + if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData) + { + SetLastError(CRYPT_E_ASN1_CORRUPT); + ret = FALSE; + } + TRACE("returning %d\n", ret); + return ret; +} + +static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(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(CMSG_SIGNER_INFO, dwVersion), + CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 }, + { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer), + CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER), + FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 }, + { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm), + CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), + FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 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 }, + }; + + 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 + TRACE("returning %d\n", ret); + return ret; +} + BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) @@ -3792,6 +3872,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, case (WORD)X509_ISSUING_DIST_POINT: decodeFunc = CRYPT_AsnDecodeIssuingDistPoint; break; + case (WORD)PKCS7_SIGNER_INFO: + decodeFunc = CRYPT_AsnDecodePKCSSignerInfo; + break; default: FIXME("%d: unimplemented\n", LOWORD(lpszStructType)); } diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c index 4e539cc3c3..aacef315ae 100644 --- a/dlls/crypt32/encode.c +++ b/dlls/crypt32/encode.c @@ -3078,6 +3078,80 @@ static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType, return ret; } +static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber( + DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, + DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, + DWORD *pcbEncoded) +{ + BOOL ret; + const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = + (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo; + struct AsnEncodeSequenceItem items[] = { + { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 }, + { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 }, + }; + + ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, + sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded, + pcbEncoded); + return ret; +} + +static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType, + LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, + PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) +{ + BOOL ret = FALSE; + + if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING)) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + + __TRY + { + const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo; + + if (!info->Issuer.cbData) + SetLastError(E_INVALIDARG); + else + { + struct AsnEncodeSequenceItem items[7] = { + { &info->dwVersion, CRYPT_AsnEncodeInt, 0 }, + { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 }, + { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, + { &info->HashEncryptionAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 }, + }; + DWORD cItem = 4; + + 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; + cItem++; + } + items[cItem].pvStructInfo = &info->EncryptedHash; + items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; + cItem++; + ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, + dwFlags, pEncodePara, pbEncoded, pcbEncoded); + } + } + __EXCEPT_PAGE_FAULT + { + SetLastError(STATUS_ACCESS_VIOLATION); + } + __ENDTRY + return ret; +} + BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, void *pvEncoded, DWORD *pcbEncoded) @@ -3201,6 +3275,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, case (WORD)X509_ISSUING_DIST_POINT: encodeFunc = CRYPT_AsnEncodeIssuingDistPoint; break; + case (WORD)PKCS7_SIGNER_INFO: + encodeFunc = CRYPT_AsnEncodePKCSSignerInfo; + break; default: FIXME("%d: unimplemented\n", LOWORD(lpszStructType)); } diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index b1c9dbe36f..387df64f53 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -4857,6 +4857,316 @@ static void test_decodePKCSAttributes(DWORD dwEncoding) } } +static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, + 0x67 }; +/* As with the algorithm ID tests, accept the algorithm ID parameters either as + * NULL or as nonexistent. + */ +static const BYTE minimalPKCSSigner[] = { + 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, + 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, + 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 }; +static const BYTE minimalPKCSSignerNoNull[] = { + 0x30,0x27,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, + 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, + 0x00,0x30,0x02,0x06,0x00,0x30,0x02,0x06,0x00,0x04,0x00 }; +static const BYTE PKCSSignerWithSerial[] = { + 0x30,0x2c,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,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04, + 0x00 }; +static const BYTE PKCSSignerWithSerialNoNull[] = { + 0x30,0x28,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,0x02,0x06,0x00,0x30,0x02,0x06,0x00,0x04,0x00 }; +static const BYTE PKCSSignerWithHashAlgo[] = { + 0x30,0x2e,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,0x30,0x04,0x06,0x00,0x05, + 0x00,0x04,0x00 }; +static const BYTE PKCSSignerWithHashAlgoNoNull[] = { + 0x30,0x2a,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,0x04,0x06,0x02,0x2a,0x03,0x30,0x02,0x06,0x00,0x04,0x00 }; +static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = { + 0x30,0x30,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,0x30,0x06,0x06,0x02,0x2d, + 0x06,0x05,0x00,0x04,0x00 }; +static const BYTE PKCSSignerWithHashAndEncryptionAlgoNoNull[] = { + 0x30,0x2c,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,0x04,0x06,0x02,0x2a,0x03,0x30,0x04,0x06,0x02,0x2d,0x06,0x04, + 0x00 }; +static const BYTE PKCSSignerWithHash[] = { + 0x30,0x40,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,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 PKCSSignerWithHashNoNull[] = { + 0x30,0x3c,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,0x04,0x06,0x02,0x2a,0x03,0x30,0x04,0x06,0x02,0x2d, + 0x06,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; + +static void test_encodePKCSSignerInfo(DWORD dwEncoding) +{ + static char oid1[] = "1.2.3", oid2[] = "1.5.6"; + BOOL ret; + LPBYTE buf = NULL; + DWORD size = 0; + CMSG_SIGNER_INFO info = { 0 }; + + SetLastError(0xdeadbeef); + ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + /* To be encoded, a signer must have an issuer at least, and the encoding + * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded, + * see decoding tests.) + */ + info.Issuer.cbData = sizeof(encodedCommonNameNoNull); + info.Issuer.pbData = encodedCommonNameNoNull; + 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(minimalPKCSSigner) || + size == sizeof(minimalPKCSSignerNoNull), "Unexpected size %d\n", + size); + if (size == sizeof(minimalPKCSSigner)) + ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n"); + else if (size == sizeof(minimalPKCSSignerNoNull)) + ok(!memcmp(buf, minimalPKCSSignerNoNull, size), + "Unexpected value\n"); + else + ok(0, "Unexpected value\n"); + LocalFree(buf); + } + } + info.SerialNumber.cbData = sizeof(serialNum); + info.SerialNumber.pbData = (BYTE *)serialNum; + 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(PKCSSignerWithSerial) || + size == sizeof(PKCSSignerWithSerialNoNull), "Unexpected size %d\n", + size); + if (size == sizeof(PKCSSignerWithSerial)) + ok(!memcmp(buf, PKCSSignerWithSerial, size), + "Unexpected value\n"); + else if (size == sizeof(PKCSSignerWithSerialNoNull)) + ok(!memcmp(buf, PKCSSignerWithSerialNoNull, size), + "Unexpected value\n"); + else + ok(0, "Unexpected value\n"); + LocalFree(buf); + } + } + info.HashAlgorithm.pszObjId = oid1; + 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(PKCSSignerWithHashAlgo) || + size == sizeof(PKCSSignerWithHashAlgoNoNull), + "Unexpected size %d\n", size); + if (size == sizeof(PKCSSignerWithHashAlgo)) + ok(!memcmp(buf, PKCSSignerWithHashAlgo, size), + "Unexpected value\n"); + else if (size == sizeof(PKCSSignerWithHashAlgoNoNull)) + ok(!memcmp(buf, PKCSSignerWithHashAlgoNoNull, size), + "Unexpected value\n"); + else + ok(0, "Unexpected value\n"); + LocalFree(buf); + } + } + info.HashEncryptionAlgorithm.pszObjId = oid2; + 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(PKCSSignerWithHashAndEncryptionAlgo) || + size == sizeof(PKCSSignerWithHashAndEncryptionAlgoNoNull), + "Unexpected size %d\n", size); + if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo)) + ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size), + "Unexpected value\n"); + else if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgoNoNull)) + ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgoNoNull, + size), "Unexpected value\n"); + else + ok(0, "Unexpected value\n"); + LocalFree(buf); + } + } + info.EncryptedHash.cbData = sizeof(hash); + info.EncryptedHash.pbData = (BYTE *)hash; + 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(PKCSSignerWithHash) || + size == sizeof(PKCSSignerWithHashNoNull), "Unexpected size %d\n", + size); + if (size == sizeof(PKCSSignerWithHash)) + ok(!memcmp(buf, PKCSSignerWithHash, size), + "Unexpected value\n"); + else if (size == sizeof(PKCSSignerWithHashNoNull)) + ok(!memcmp(buf, PKCSSignerWithHashNoNull, size), + "Unexpected value\n"); + else + ok(0, "Unexpected value\n"); + LocalFree(buf); + } + } +} + +static void test_decodePKCSSignerInfo(DWORD dwEncoding) +{ + BOOL ret; + LPBYTE buf = NULL; + DWORD size = 0; + CMSG_SIGNER_INFO *info; + + /* A PKCS signer can't be decoded without a serial number. */ + SetLastError(0xdeadbeef); + ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, + minimalPKCSSigner, sizeof(minimalPKCSSigner), + CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT, + "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError()); + ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, + PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial), + CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); + if (buf) + { + info = (CMSG_SIGNER_INFO *)buf; + ok(info->dwVersion == 0, "Expected version 0, got %d\n", + info->dwVersion); + ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull), + "Unexpected size %d\n", info->Issuer.cbData); + ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull, + info->Issuer.cbData), "Unexpected value\n"); + ok(info->SerialNumber.cbData == sizeof(serialNum), + "Unexpected size %d\n", info->SerialNumber.cbData); + ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)), + "Unexpected value\n"); + LocalFree(buf); + } + ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, + PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo), + CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + if (buf) + { + info = (CMSG_SIGNER_INFO *)buf; + ok(info->dwVersion == 0, "Expected version 0, got %d\n", + info->dwVersion); + ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull), + "Unexpected size %d\n", info->Issuer.cbData); + ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull, + info->Issuer.cbData), "Unexpected value\n"); + ok(info->SerialNumber.cbData == sizeof(serialNum), + "Unexpected size %d\n", info->SerialNumber.cbData); + ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)), + "Unexpected value\n"); + ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"), + "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId); + LocalFree(buf); + } + ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, + PKCSSignerWithHashAndEncryptionAlgo, + sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG, + NULL, (BYTE *)&buf, &size); + if (buf) + { + info = (CMSG_SIGNER_INFO *)buf; + ok(info->dwVersion == 0, "Expected version 0, got %d\n", + info->dwVersion); + ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull), + "Unexpected size %d\n", info->Issuer.cbData); + ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull, + info->Issuer.cbData), "Unexpected value\n"); + ok(info->SerialNumber.cbData == sizeof(serialNum), + "Unexpected size %d\n", info->SerialNumber.cbData); + ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)), + "Unexpected value\n"); + ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"), + "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId); + ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"), + "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId); + LocalFree(buf); + } + ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, + PKCSSignerWithHash, sizeof(PKCSSignerWithHash), + CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + if (buf) + { + info = (CMSG_SIGNER_INFO *)buf; + ok(info->dwVersion == 0, "Expected version 0, got %d\n", + info->dwVersion); + ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull), + "Unexpected size %d\n", info->Issuer.cbData); + ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull, + info->Issuer.cbData), "Unexpected value\n"); + ok(info->SerialNumber.cbData == sizeof(serialNum), + "Unexpected size %d\n", info->SerialNumber.cbData); + ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)), + "Unexpected value\n"); + ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"), + "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId); + ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"), + "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId); + ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n", + info->EncryptedHash.cbData); + ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)), + "Unexpected value\n"); + LocalFree(buf); + } +} + /* Free *pInfo with HeapFree */ static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo) { @@ -5070,6 +5380,8 @@ START_TEST(encode) test_decodePKCSAttribute(encodings[i]); test_encodePKCSAttributes(encodings[i]); test_decodePKCSAttributes(encodings[i]); + test_encodePKCSSignerInfo(encodings[i]); + test_decodePKCSSignerInfo(encodings[i]); } testPortPublicKeyInfo(); }