From 8cdf146317ae4c54986010a21ed879ca98d04c15 Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Thu, 16 Sep 2010 18:44:53 +0400 Subject: [PATCH] crypt32: Implement CryptSignMessage. --- dlls/crypt32/message.c | 111 ++++++++++++++++++++++++++++++++++++++++++- dlls/crypt32/tests/message.c | 22 +++------ 2 files changed, 115 insertions(+), 18 deletions(-) diff --git a/dlls/crypt32/message.c b/dlls/crypt32/message.c index 81eb913a7ad..2d67e4c3ad6 100644 --- a/dlls/crypt32/message.c +++ b/dlls/crypt32/message.c @@ -420,7 +420,114 @@ BOOL WINAPI CryptSignMessage(PCRYPT_SIGN_MESSAGE_PARA pSignPara, BOOL fDetachedSignature, DWORD cToBeSigned, const BYTE *rgpbToBeSigned[], DWORD rgcbToBeSigned[], BYTE *pbSignedBlob, DWORD *pcbSignedBlob) { - FIXME("(%p, %d, %d, %p, %p, %p, %p): stub\n", pSignPara, fDetachedSignature, + HCRYPTPROV hCryptProv; + BOOL ret, freeProv = FALSE; + DWORD i, keySpec; + PCERT_BLOB certBlob = NULL; + PCRL_BLOB crlBlob = NULL; + CMSG_SIGNED_ENCODE_INFO signInfo; + CMSG_SIGNER_ENCODE_INFO signer; + HCRYPTMSG msg = 0; + + TRACE("(%p, %d, %d, %p, %p, %p, %p)\n", pSignPara, fDetachedSignature, cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, pbSignedBlob, pcbSignedBlob); - return FALSE; + + if (pSignPara->cbSize != sizeof(CRYPT_SIGN_MESSAGE_PARA) || + GET_CMSG_ENCODING_TYPE(pSignPara->dwMsgEncodingType) != + PKCS_7_ASN_ENCODING) + { + *pcbSignedBlob = 0; + SetLastError(E_INVALIDARG); + return FALSE; + } + if (!pSignPara->pSigningCert) + return TRUE; + + ret = CryptAcquireCertificatePrivateKey(pSignPara->pSigningCert, + CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hCryptProv, &keySpec, &freeProv); + if (!ret) + return FALSE; + + memset(&signer, 0, sizeof(signer)); + signer.cbSize = sizeof(signer); + signer.pCertInfo = pSignPara->pSigningCert->pCertInfo; + signer.hCryptProv = hCryptProv; + signer.dwKeySpec = keySpec; + signer.HashAlgorithm = pSignPara->HashAlgorithm; + signer.pvHashAuxInfo = pSignPara->pvHashAuxInfo; + signer.cAuthAttr = pSignPara->cAuthAttr; + signer.rgAuthAttr = pSignPara->rgAuthAttr; + signer.cUnauthAttr = pSignPara->cUnauthAttr; + signer.rgUnauthAttr = pSignPara->rgUnauthAttr; + + memset(&signInfo, 0, sizeof(signInfo)); + signInfo.cbSize = sizeof(signInfo); + signInfo.cSigners = 1; + signInfo.rgSigners = &signer; + + if (pSignPara->cMsgCert) + { + certBlob = CryptMemAlloc(sizeof(CERT_BLOB) * pSignPara->cMsgCert); + if (certBlob) + { + for (i = 0; i < pSignPara->cMsgCert; ++i) + { + certBlob[i].cbData = pSignPara->rgpMsgCert[i]->cbCertEncoded; + certBlob[i].pbData = pSignPara->rgpMsgCert[i]->pbCertEncoded; + } + signInfo.cCertEncoded = pSignPara->cMsgCert; + signInfo.rgCertEncoded = certBlob; + } + else + ret = FALSE; + } + if (pSignPara->cMsgCrl) + { + crlBlob = CryptMemAlloc(sizeof(CRL_BLOB) * pSignPara->cMsgCrl); + if (crlBlob) + { + for (i = 0; i < pSignPara->cMsgCrl; ++i) + { + crlBlob[i].cbData = pSignPara->rgpMsgCrl[i]->cbCrlEncoded; + crlBlob[i].pbData = pSignPara->rgpMsgCrl[i]->pbCrlEncoded; + } + signInfo.cCrlEncoded = pSignPara->cMsgCrl; + signInfo.rgCrlEncoded = crlBlob; + } + else + ret = FALSE; + } + if (pSignPara->dwFlags || pSignPara->dwInnerContentType) + FIXME("unimplemented feature\n"); + + if (ret) + msg = CryptMsgOpenToEncode(pSignPara->dwMsgEncodingType, + fDetachedSignature ? CMSG_DETACHED_FLAG : 0, CMSG_SIGNED, &signInfo, + NULL, NULL); + if (msg) + { + if (cToBeSigned) + { + for (i = 0; ret && i < cToBeSigned; ++i) + { + ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i], + i == cToBeSigned - 1 ? TRUE : FALSE); + } + } + else + ret = CryptMsgUpdate(msg, NULL, 0, TRUE); + if (ret) + ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbSignedBlob, + pcbSignedBlob); + CryptMsgClose(msg); + } + else + ret = FALSE; + if (crlBlob) + CryptMemFree(crlBlob); + if (certBlob) + CryptMemFree(certBlob); + if (freeProv) + CryptReleaseContext(hCryptProv, 0); + return ret; } diff --git a/dlls/crypt32/tests/message.c b/dlls/crypt32/tests/message.c index a2706fe7516..8e214e7802d 100644 --- a/dlls/crypt32/tests/message.c +++ b/dlls/crypt32/tests/message.c @@ -959,7 +959,6 @@ static void test_sign_message(void) memset(¶, 0, sizeof(para)); SetLastError(0xdeadbeef); ret = CryptSignMessage(¶, FALSE, 0, NULL, NULL, NULL, &signedBlobSize); - todo_wine ok(!ret && (GetLastError() == E_INVALIDARG || GetLastError() == ERROR_ARITHMETIC_OVERFLOW), /* Win7 */ @@ -970,16 +969,13 @@ static void test_sign_message(void) SetLastError(0xdeadbeef); signedBlobSize = 255; ret = CryptSignMessage(¶, FALSE, 0, NULL, NULL, NULL, &signedBlobSize); - todo_wine ok(!ret && GetLastError() == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", GetLastError()); - todo_wine ok(!signedBlobSize, "unexpected size %d\n", signedBlobSize); para.dwMsgEncodingType = PKCS_7_ASN_ENCODING; SetLastError(0xdeadbeef); signedBlobSize = 0; ret = CryptSignMessage(¶, FALSE, 0, NULL, NULL, NULL, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); todo_wine ok(signedBlobSize, "bad size\n"); @@ -1020,7 +1016,6 @@ static void test_sign_message(void) SetLastError(0xdeadbeef); signedBlobSize = 0; ret = CryptSignMessage(¶, TRUE, 0, NULL, NULL, NULL, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); signedBlob = CryptMemAlloc(signedBlobSize); if (signedBlob) @@ -1028,11 +1023,11 @@ static void test_sign_message(void) SetLastError(0xdeadbeef); ret = CryptSignMessage(¶, TRUE, 0, NULL, NULL, signedBlob, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); todo_wine ok(signedBlobSize == sizeof(signedHashForEmptyMessage), "unexpected size %d\n", signedBlobSize); + todo_wine ok(!memcmp(signedBlob, signedHashForEmptyMessage, signedBlobSize), "unexpected value\n"); CryptMemFree(signedBlob); @@ -1041,7 +1036,6 @@ static void test_sign_message(void) SetLastError(0xdeadbeef); signedBlobSize = 0; ret = CryptSignMessage(¶, FALSE, 0, NULL, NULL, NULL, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); signedBlob = CryptMemAlloc(signedBlobSize); if (signedBlob) @@ -1049,11 +1043,11 @@ static void test_sign_message(void) SetLastError(0xdeadbeef); ret = CryptSignMessage(¶, FALSE, 0, NULL, NULL, signedBlob, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); todo_wine ok(signedBlobSize == sizeof(signedEmptyMessage), "unexpected size %d\n", signedBlobSize); + todo_wine ok(!memcmp(signedBlob, signedEmptyMessage, signedBlobSize), "unexpected value\n"); CryptMemFree(signedBlob); @@ -1063,7 +1057,6 @@ static void test_sign_message(void) signedBlobSize = 0; ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, NULL, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); signedBlob = CryptMemAlloc(signedBlobSize); if (signedBlob) @@ -1071,11 +1064,11 @@ static void test_sign_message(void) SetLastError(0xdeadbeef); ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, signedBlob, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); todo_wine ok(signedBlobSize == sizeof(signedHash), "unexpected size of signed blob %d\n", signedBlobSize); + todo_wine ok(!memcmp(signedBlob, signedHash, signedBlobSize), "unexpected value\n"); CryptMemFree(signedBlob); @@ -1088,7 +1081,6 @@ static void test_sign_message(void) signedBlobSize = 0; ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, NULL, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); signedBlob = CryptMemAlloc(signedBlobSize); if (signedBlob) @@ -1096,11 +1088,11 @@ static void test_sign_message(void) SetLastError(0xdeadbeef); ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, signedBlob, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); todo_wine ok(signedBlobSize == sizeof(signedHashWithCert), "unexpected size of signed blob %d\n", signedBlobSize); + todo_wine ok(!memcmp(signedBlob, signedHashWithCert, signedBlobSize), "unexpected value\n"); CryptMemFree(signedBlob); @@ -1120,7 +1112,6 @@ static void test_sign_message(void) signedBlobSize = 0; ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, NULL, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); signedBlob = CryptMemAlloc(signedBlobSize); if (signedBlob) @@ -1128,11 +1119,11 @@ static void test_sign_message(void) SetLastError(0xdeadbeef); ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, signedBlob, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); todo_wine ok(signedBlobSize == sizeof(signedHashWithCRL), "unexpected size of signed blob %d\n", signedBlobSize); + todo_wine ok(!memcmp(signedBlob, signedHashWithCRL, signedBlobSize), "unexpected value\n"); CryptMemFree(signedBlob); @@ -1146,7 +1137,6 @@ static void test_sign_message(void) signedBlobSize = 0; ret = CryptSignMessage(¶, FALSE, 1, toSign, signSize, NULL, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); signedBlob = CryptMemAlloc(signedBlobSize); if (signedBlob) @@ -1154,11 +1144,11 @@ static void test_sign_message(void) SetLastError(0xdeadbeef); ret = CryptSignMessage(¶, FALSE, 1, toSign, signSize, signedBlob, &signedBlobSize); - todo_wine ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); todo_wine ok(signedBlobSize == sizeof(signedData), "unexpected size of signed blob %d\n", signedBlobSize); + todo_wine ok(!memcmp(signedBlob, signedData, signedBlobSize), "unexpected value\n"); CryptMemFree(signedBlob); -- 2.11.4.GIT