crypt32: Implement verifying a decoded signed message's signature.

This commit is contained in:
Juan Lang 2007-08-21 07:34:47 -07:00 committed by Alexandre Julliard
parent d3431271fa
commit b7e420429d
2 changed files with 46 additions and 6 deletions

View File

@ -2084,6 +2084,47 @@ static BOOL CDecodeHashMsg_VerifyHash(CDecodeMsg *msg)
return ret; return ret;
} }
static BOOL CDecodeSignedMsg_VerifySignature(CDecodeMsg *msg, PCERT_INFO info)
{
BOOL ret = FALSE;
DWORD i;
for (i = 0; !ret && i < msg->u.signed_data.info->cSignerInfo; i++)
{
ret = CertCompareCertificateName(X509_ASN_ENCODING,
&msg->u.signed_data.info->rgSignerInfo[i].Issuer, &info->Issuer);
if (ret)
ret = CertCompareIntegerBlob(
&msg->u.signed_data.info->rgSignerInfo[i].SerialNumber,
&info->SerialNumber);
}
if (ret)
{
HCRYPTKEY key;
ret = CryptImportPublicKeyInfo(msg->crypt_prov, X509_ASN_ENCODING,
&info->SubjectPublicKeyInfo, &key);
if (ret)
{
HCRYPTHASH hash;
if (msg->u.signed_data.info->rgSignerInfo[i].AuthAttrs.cAttr)
hash = msg->u.signed_data.signerHandles[i].authAttrHash;
else
hash = msg->u.signed_data.signerHandles[i].contentHash;
ret = CryptVerifySignatureW(hash,
msg->u.signed_data.info->rgSignerInfo[i].EncryptedHash.pbData,
msg->u.signed_data.info->rgSignerInfo[i].EncryptedHash.cbData,
key, NULL, 0);
CryptDestroyKey(key);
}
}
else
SetLastError(CRYPT_E_SIGNER_NOT_FOUND);
return ret;
}
static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags, static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags,
DWORD dwCtrlType, const void *pvCtrlPara) DWORD dwCtrlType, const void *pvCtrlPara)
{ {
@ -2096,7 +2137,7 @@ static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags,
switch (msg->type) switch (msg->type)
{ {
case CMSG_SIGNED: case CMSG_SIGNED:
FIXME("CMSG_CTRL_VERIFY_SIGNATURE: stub\n"); ret = CDecodeSignedMsg_VerifySignature(msg, (PCERT_INFO)pvCtrlPara);
break; break;
default: default:
SetLastError(CRYPT_E_INVALID_MSG_TYPE); SetLastError(CRYPT_E_INVALID_MSG_TYPE);

View File

@ -2291,7 +2291,6 @@ static void test_msg_control(void)
*/ */
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
todo_wine
ok(!ret && GetLastError() == CRYPT_E_SIGNER_NOT_FOUND, ok(!ret && GetLastError() == CRYPT_E_SIGNER_NOT_FOUND,
"Expected CRYPT_E_SIGNER_NOT_FOUND, got %08x\n", GetLastError()); "Expected CRYPT_E_SIGNER_NOT_FOUND, got %08x\n", GetLastError());
/* The cert info is expected to have an issuer, serial number, and public /* The cert info is expected to have an issuer, serial number, and public
@ -2303,7 +2302,6 @@ static void test_msg_control(void)
certInfo.Issuer.pbData = encodedCommonName; certInfo.Issuer.pbData = encodedCommonName;
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
todo_wine
ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD, ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
"Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
CryptMsgClose(msg); CryptMsgClose(msg);
@ -2315,7 +2313,6 @@ static void test_msg_control(void)
/* Again, cert info needs to have a public key set */ /* Again, cert info needs to have a public key set */
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
todo_wine
ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD, ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
"Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
/* The public key is supposed to be in encoded form.. */ /* The public key is supposed to be in encoded form.. */
@ -2324,7 +2321,6 @@ static void test_msg_control(void)
certInfo.SubjectPublicKeyInfo.PublicKey.pbData = aKey; certInfo.SubjectPublicKeyInfo.PublicKey.pbData = aKey;
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
todo_wine
ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG, ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
/* but not as a X509_PUBLIC_KEY_INFO.. */ /* but not as a X509_PUBLIC_KEY_INFO.. */
@ -2333,7 +2329,6 @@ static void test_msg_control(void)
certInfo.SubjectPublicKeyInfo.PublicKey.pbData = encodedPubKey; certInfo.SubjectPublicKeyInfo.PublicKey.pbData = encodedPubKey;
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
todo_wine
ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG, ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
/* This decodes successfully, but it doesn't match any key in the message */ /* This decodes successfully, but it doesn't match any key in the message */
@ -2341,6 +2336,10 @@ static void test_msg_control(void)
certInfo.SubjectPublicKeyInfo.PublicKey.pbData = mod_encoded; certInfo.SubjectPublicKeyInfo.PublicKey.pbData = mod_encoded;
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
/* In Wine's rsaenh, this fails to decode because the key length is too
* small. Not sure if that's a bug in rsaenh, so leaving todo_wine for
* now.
*/
todo_wine todo_wine
ok(!ret && GetLastError() == NTE_BAD_SIGNATURE, ok(!ret && GetLastError() == NTE_BAD_SIGNATURE,
"Expected NTE_BAD_SIGNATURE, got %08x\n", GetLastError()); "Expected NTE_BAD_SIGNATURE, got %08x\n", GetLastError());