diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index 67a40245a91..08b3ce8499e 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -535,6 +535,119 @@ static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo, return (HCRYPTMSG)msg; } +typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS +{ + DWORD cbSize; + PCERT_INFO pCertInfo; + HCRYPTPROV hCryptProv; + DWORD dwKeySpec; + CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; + void *pvHashAuxInfo; + DWORD cAuthAttr; + PCRYPT_ATTRIBUTE rgAuthAttr; + DWORD cUnauthAttr; + PCRYPT_ATTRIBUTE rgUnauthAttr; + CERT_ID SignerId; + CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; + void *pvHashEncryptionAuxInfo; +} CMSG_SIGNER_ENCODE_INFO_WITH_CMS, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS; + +typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS +{ + DWORD cbSize; + DWORD cSigners; + PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners; + DWORD cCertEncoded; + PCERT_BLOB rgCertEncoded; + DWORD cCrlEncoded; + PCRL_BLOB rgCrlEncoded; + DWORD cAttrCertEncoded; + PCERT_BLOB rgAttrCertEncoded; +} CMSG_SIGNED_ENCODE_INFO_WITH_CMS, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS; + +static BOOL CRYPT_IsValidSigner(CMSG_SIGNER_ENCODE_INFO_WITH_CMS *signer) +{ + if (!signer->pCertInfo->SerialNumber.cbData) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + if (!signer->pCertInfo->Issuer.cbData) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + if (!signer->hCryptProv) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + if (!CertOIDToAlgId(signer->HashAlgorithm.pszObjId)) + { + SetLastError(CRYPT_E_UNKNOWN_ALGO); + return FALSE; + } + return TRUE; +} + +typedef struct _CSignedEncodeMsg +{ + CryptMsgBase base; +} CSignedEncodeMsg; + +static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg) +{ + FIXME("(%p)\n", hCryptMsg); +} + +static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, + DWORD dwIndex, void *pvData, DWORD *pcbData) +{ + FIXME("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex, pvData, + pcbData); + return FALSE; +} + +static BOOL CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, + DWORD cbData, BOOL fFinal) +{ + FIXME("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal); + return FALSE; +} + +static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags, + const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID, + PCMSG_STREAM_INFO pStreamInfo) +{ + const CMSG_SIGNED_ENCODE_INFO_WITH_CMS *info = + (const CMSG_SIGNED_ENCODE_INFO_WITH_CMS *)pvMsgEncodeInfo; + DWORD i; + CSignedEncodeMsg *msg; + + if (info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO) && + info->cbSize != sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS)) + { + SetLastError(E_INVALIDARG); + return NULL; + } + if (info->cbSize == sizeof(CMSG_SIGNED_ENCODE_INFO_WITH_CMS)) + { + FIXME("CMSG_SIGNED_ENCODE_INFO with CMS fields unsupported\n"); + return NULL; + } + for (i = 0; i < info->cSigners; i++) + if (!CRYPT_IsValidSigner(&info->rgSigners[i])) + return NULL; + msg = CryptMemAlloc(sizeof(CSignedEncodeMsg)); + if (msg) + { + CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo, + CSignedEncodeMsg_Close, CSignedEncodeMsg_GetParam, + CSignedEncodeMsg_Update); + } + return msg; +} + static inline const char *MSG_TYPE_STR(DWORD type) { switch (type) @@ -577,6 +690,9 @@ HCRYPTMSG WINAPI CryptMsgOpenToEncode(DWORD dwMsgEncodingType, DWORD dwFlags, pszInnerContentObjID, pStreamInfo); break; case CMSG_SIGNED: + msg = CSignedEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, + pszInnerContentObjID, pStreamInfo); + break; case CMSG_ENVELOPED: FIXME("unimplemented for type %s\n", MSG_TYPE_STR(dwMsgType)); break; diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c index 893f49d6663..d2d94888b97 100644 --- a/dlls/crypt32/tests/msg.c +++ b/dlls/crypt32/tests/msg.c @@ -989,13 +989,11 @@ static void test_signed_msg_open(void) SetLastError(0xdeadbeef); msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, NULL, NULL); - todo_wine ok(!msg && GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", GetLastError()); signInfo.cbSize = sizeof(signInfo); msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, NULL, NULL); - todo_wine ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError()); CryptMsgClose(msg); @@ -1009,7 +1007,6 @@ static void test_signed_msg_open(void) SetLastError(0xdeadbeef); msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, NULL, NULL); - todo_wine ok(!msg && GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", GetLastError()); certInfo.SerialNumber.cbData = sizeof(serialNum); @@ -1017,7 +1014,6 @@ static void test_signed_msg_open(void) SetLastError(0xdeadbeef); msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, NULL, NULL); - todo_wine ok(!msg && GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", GetLastError()); certInfo.Issuer.cbData = sizeof(encodedCommonName); @@ -1025,7 +1021,6 @@ static void test_signed_msg_open(void) SetLastError(0xdeadbeef); msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, NULL, NULL); - todo_wine ok(!msg && GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", GetLastError()); @@ -1037,17 +1032,18 @@ static void test_signed_msg_open(void) SetLastError(0xdeadbeef); msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, NULL, NULL); - todo_wine ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO, "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError()); /* The signer's hash algorithm must also be set. */ signer.HashAlgorithm.pszObjId = oid_rsa_md5; SetLastError(0xdeadbeef); - msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, - NULL, NULL); - todo_wine - ok(!msg && GetLastError() == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError()); + /* Crashes in advapi32 in wine, don't do it */ + if (0) { + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, + &signInfo, NULL, NULL); + ok(!msg && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError()); + } /* The signer's hCryptProv must also be valid. */ ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET); @@ -1057,7 +1053,6 @@ static void test_signed_msg_open(void) ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError()); msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, NULL, NULL); - todo_wine ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError()); CryptMsgClose(msg);