722 lines
34 KiB
C
722 lines
34 KiB
C
/*
|
|
* Unit test suite for crypt32.dll's Crypt*Message functions
|
|
*
|
|
* Copyright 2007-2008 Juan Lang
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <windef.h>
|
|
#include <winbase.h>
|
|
#include <winerror.h>
|
|
#include <wincrypt.h>
|
|
|
|
#include "wine/test.h"
|
|
|
|
static const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
|
|
static const BYTE dataEmptyContent[] = {
|
|
0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
|
|
0x04,0x00 };
|
|
static const BYTE signedEmptyBareContent[] = {
|
|
0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
|
|
0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
|
|
0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
|
|
0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
|
|
0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
|
|
0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
|
|
static const BYTE signedEmptyContent[] = {
|
|
0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52,
|
|
0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
|
|
0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
|
|
0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
|
|
0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
|
|
0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
|
|
0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
|
|
|
|
static void test_msg_get_signer_count(void)
|
|
{
|
|
LONG count;
|
|
|
|
SetLastError(0xdeadbeef);
|
|
count = CryptGetMessageSignerCount(0, NULL, 0);
|
|
ok(count == -1, "Expected -1, got %d\n", count);
|
|
ok(GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n",
|
|
GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, NULL, 0);
|
|
ok(count == -1, "Expected -1, got %d\n", count);
|
|
ok(GetLastError() == CRYPT_E_ASN1_EOD ||
|
|
GetLastError() == OSS_BAD_ARG, /* win9x */
|
|
"Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
|
|
dataEmptyBareContent, sizeof(dataEmptyBareContent));
|
|
ok(count == -1, "Expected -1, got %d\n", count);
|
|
ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
|
|
GetLastError() == OSS_PDU_MISMATCH, /* win9x */
|
|
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
|
|
dataEmptyContent, sizeof(dataEmptyContent));
|
|
ok(count == -1, "Expected -1, got %d\n", count);
|
|
ok(GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
|
|
"Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
|
|
signedEmptyBareContent, sizeof(signedEmptyBareContent));
|
|
ok(count == -1, "Expected -1, got %d\n", count);
|
|
ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
|
|
GetLastError() == OSS_DATA_ERROR, /* win9x */
|
|
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
|
|
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
|
|
signedEmptyContent, sizeof(signedEmptyContent));
|
|
ok(count == 1 ||
|
|
broken(count == -1), /* win9x */
|
|
"Expected 1, got %d\n", count);
|
|
}
|
|
|
|
static BYTE detachedHashContent[] = {
|
|
0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
|
|
0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
|
0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
|
0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
|
|
0x9d,0x2a,0x8f,0x26,0x2f };
|
|
static const BYTE msgData[] = { 1, 2, 3, 4 };
|
|
|
|
static void test_verify_detached_message_hash(void)
|
|
{
|
|
BOOL ret;
|
|
CRYPT_HASH_MESSAGE_PARA para;
|
|
DWORD size, hashSize;
|
|
const BYTE *pMsgData = msgData;
|
|
BYTE hash[16];
|
|
|
|
if (0)
|
|
{
|
|
ret = CryptVerifyDetachedMessageHash(NULL, NULL, 0, 0, NULL, NULL, NULL,
|
|
NULL);
|
|
}
|
|
memset(¶, 0, sizeof(para));
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
|
NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.cbSize = sizeof(para);
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
|
NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
|
NULL);
|
|
ok(!ret &&
|
|
(GetLastError() == CRYPT_E_ASN1_EOD ||
|
|
GetLastError() == OSS_BAD_ARG), /* win9x */
|
|
"expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
|
|
para.dwMsgEncodingType = X509_ASN_ENCODING;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
|
NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
|
NULL);
|
|
ok(!ret &&
|
|
(GetLastError() == CRYPT_E_ASN1_EOD ||
|
|
GetLastError() == OSS_BAD_ARG), /* win9x */
|
|
"expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
|
|
/* Curiously, passing no data to hash succeeds.. */
|
|
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
|
sizeof(detachedHashContent), 0, NULL, NULL, NULL, NULL);
|
|
todo_wine
|
|
ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
|
|
/* as does passing the actual content of the message to hash.. */
|
|
size = sizeof(msgData);
|
|
pMsgData = msgData;
|
|
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
|
sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
|
|
ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
|
|
/* while passing data to hash that isn't the content of the message fails.
|
|
*/
|
|
size = sizeof(detachedHashContent);
|
|
pMsgData = detachedHashContent;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
|
sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
|
|
ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
|
|
"expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
|
|
/* Getting the size of the hash while passing no hash data causes the
|
|
* hash to be checked (and fail.)
|
|
*/
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
|
sizeof(detachedHashContent), 0, NULL, NULL, NULL, &hashSize);
|
|
ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
|
|
"expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
|
|
size = sizeof(msgData);
|
|
pMsgData = msgData;
|
|
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
|
sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, &hashSize);
|
|
ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
|
|
ok(hashSize == sizeof(hash), "unexpected size %d\n", hashSize);
|
|
hashSize = 1;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
|
sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
|
|
ok(!ret && GetLastError() == ERROR_MORE_DATA,
|
|
"expected ERROR_MORE_DATA, got %08x\n", GetLastError());
|
|
hashSize = sizeof(hash);
|
|
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
|
sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
|
|
ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
|
|
}
|
|
|
|
static BYTE hashContent[] = {
|
|
0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
|
|
0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
|
0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
|
0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
|
|
0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
|
|
|
|
static void test_verify_message_hash(void)
|
|
{
|
|
BOOL ret;
|
|
CRYPT_HASH_MESSAGE_PARA para;
|
|
DWORD size;
|
|
BYTE *buf = NULL;
|
|
|
|
memset(¶, 0, sizeof(para));
|
|
/* Crash */
|
|
if (0)
|
|
ret = CryptVerifyMessageHash(NULL, NULL, 0, NULL, NULL, NULL, NULL);
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageHash(¶, NULL, 0, NULL, NULL, NULL, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.cbSize = sizeof(para);
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageHash(¶, NULL, 0, NULL, NULL, NULL, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageHash(¶, NULL, 0, NULL, NULL, NULL, NULL);
|
|
ok(!ret, "Expected 0, got %d\n", ret);
|
|
ok(GetLastError() == CRYPT_E_ASN1_EOD ||
|
|
GetLastError() == OSS_BAD_ARG, /* win98 */
|
|
"Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
|
|
/* Verifying the hash of a detached message succeeds? */
|
|
ret = CryptVerifyMessageHash(¶, detachedHashContent,
|
|
sizeof(detachedHashContent), NULL, NULL, NULL, NULL);
|
|
todo_wine
|
|
ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
|
|
/* As does verifying the hash of a regular message. */
|
|
ret = CryptVerifyMessageHash(¶, hashContent, sizeof(hashContent),
|
|
NULL, NULL, NULL, NULL);
|
|
ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
|
|
ret = CryptVerifyMessageHash(¶, hashContent, sizeof(hashContent),
|
|
NULL, &size, NULL, NULL);
|
|
ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
|
|
if (ret)
|
|
buf = CryptMemAlloc(size);
|
|
if (buf)
|
|
{
|
|
size = 1;
|
|
ret = CryptVerifyMessageHash(¶, hashContent, sizeof(hashContent),
|
|
buf, &size, NULL, NULL);
|
|
ok(!ret && GetLastError() == ERROR_MORE_DATA,
|
|
"expected ERROR_MORE_DATA, got %08x\n", GetLastError());
|
|
ret = CryptVerifyMessageHash(¶, hashContent, sizeof(hashContent),
|
|
buf, &size, NULL, NULL);
|
|
ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
|
|
ok(size == sizeof(msgData), "unexpected size %d\n", size);
|
|
ok(!memcmp(buf, msgData, size), "unexpected value\n");
|
|
CryptMemFree(buf);
|
|
}
|
|
}
|
|
|
|
static const BYTE signedWithCertContent[] = {
|
|
0x30,0x82,0x01,0x32,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
|
|
0xa0,0x82,0x01,0x23,0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
|
|
0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
|
|
0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
|
|
0x02,0x03,0x04,0xa0,0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
|
|
0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
|
|
0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
|
|
0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
|
|
0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
|
|
0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
|
|
0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
|
|
0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
|
|
0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,
|
|
0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,
|
|
0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,
|
|
0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,
|
|
0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,
|
|
0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,
|
|
0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,
|
|
0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,
|
|
0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
|
|
static const BYTE signedContent[] = {
|
|
0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
|
0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
|
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
|
|
0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
|
|
0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
|
|
0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
|
0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
|
0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
|
|
0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
|
|
0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
|
|
0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
|
|
0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
|
|
0x0d };
|
|
static const BYTE detachedSignedContent[] = {
|
|
0x30,0x81,0xaa,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
|
0x81,0x9c,0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
|
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
|
|
0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,
|
|
0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
|
|
0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,
|
|
0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,
|
|
0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,
|
|
0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,
|
|
0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,
|
|
0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,
|
|
0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
|
|
static const BYTE v1CertWithValidPubKey[] = {
|
|
0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
|
|
0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
|
|
0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
|
|
0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
|
|
0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
|
|
0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
|
0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
|
0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,
|
|
0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,
|
|
0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,
|
|
0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,
|
|
0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,
|
|
0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
|
|
0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
|
|
|
|
static PCCERT_CONTEXT WINAPI msg_get_signer_callback(void *pvArg,
|
|
DWORD certEncodingType, PCERT_INFO signerId, HCERTSTORE store)
|
|
{
|
|
return CertCreateCertificateContext(X509_ASN_ENCODING,
|
|
v1CertWithValidPubKey, sizeof(v1CertWithValidPubKey));
|
|
}
|
|
|
|
static void test_verify_detached_message_signature(void)
|
|
{
|
|
CRYPT_VERIFY_MESSAGE_PARA para;
|
|
BOOL ret;
|
|
const BYTE *pContent;
|
|
DWORD cbContent;
|
|
|
|
memset(¶, 0, sizeof(para));
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageSignature(NULL, 0, NULL, 0, 0, NULL,
|
|
NULL, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, NULL, 0, 0, NULL,
|
|
NULL, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.cbSize = sizeof(para);
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, NULL, 0, 0, NULL,
|
|
NULL, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.dwMsgAndCertEncodingType = X509_ASN_ENCODING;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, NULL, 0, 0, NULL,
|
|
NULL, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, NULL, 0, 0, NULL,
|
|
NULL, NULL);
|
|
ok(!ret, "Expected 0, got %d\n", ret);
|
|
ok(GetLastError() == CRYPT_E_ASN1_EOD ||
|
|
GetLastError() == OSS_BAD_ARG, /* win98 */
|
|
"Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
|
|
/* None of these messages contains a cert in the message itself, so the
|
|
* default callback isn't able to verify their signature.
|
|
*/
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, signedWithCertContent,
|
|
sizeof(signedWithCertContent), 0, NULL, NULL, NULL);
|
|
ok(!ret, "Expected 0, got %d\n", ret);
|
|
todo_wine
|
|
ok(GetLastError() == CRYPT_E_NOT_FOUND ||
|
|
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
|
"Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, signedContent,
|
|
sizeof(signedContent), 0, NULL, NULL, NULL);
|
|
ok(!ret, "Expected 0, got %d\n", ret);
|
|
ok(GetLastError() == CRYPT_E_NOT_FOUND ||
|
|
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
|
"Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, detachedSignedContent,
|
|
sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
|
|
ok(!ret, "Expected 0, got %d\n", ret);
|
|
ok(GetLastError() == CRYPT_E_NOT_FOUND ||
|
|
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
|
"Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
pContent = msgData;
|
|
cbContent = sizeof(msgData);
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, detachedSignedContent,
|
|
sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
|
|
ok(!ret, "Expected 0, got %d\n", ret);
|
|
ok(GetLastError() == CRYPT_E_NOT_FOUND ||
|
|
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
|
"Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
|
/* Passing the correct callback results in success */
|
|
para.pfnGetSignerCertificate = msg_get_signer_callback;
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, detachedSignedContent,
|
|
sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
|
|
ok(ret ||
|
|
broken(!ret), /* win98 */
|
|
"CryptVerifyDetachedMessageSignature failed: %08x\n",
|
|
GetLastError());
|
|
/* Not passing the correct data to be signed results in the signature not
|
|
* matching.
|
|
*/
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyDetachedMessageSignature(¶, 0, detachedSignedContent,
|
|
sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
|
|
ok(!ret, "Expected 0, got %d\n", ret);
|
|
ok(GetLastError() == NTE_BAD_SIGNATURE ||
|
|
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
|
"Expected NTE_BAD_SIGNATURE or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
|
}
|
|
|
|
static const BYTE signedWithCertEmptyContent[] = {
|
|
0x30,0x81,0xdf,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
|
0x81,0xd1,0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
|
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,
|
|
0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
|
|
0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
|
0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
|
|
0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
|
|
0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
|
|
0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
|
|
0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,
|
|
0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
|
|
0xff,0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,
|
|
0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
|
|
0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,
|
|
0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
|
|
0x00 };
|
|
static const BYTE signedWithCertWithPubKeyContent[] = {
|
|
0x30,0x81,0xfc,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
|
0x81,0xee,0x30,0x81,0xeb,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
|
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x81,
|
|
0x98,0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,
|
|
0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,
|
|
0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
|
|
0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
|
|
0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,
|
|
0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
|
|
0x6e,0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
|
0x01,0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
|
|
0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,
|
|
0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,
|
|
0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
|
|
0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
|
|
0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
|
|
0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
|
|
|
|
static void test_verify_message_signature(void)
|
|
{
|
|
BOOL ret;
|
|
CRYPT_VERIFY_MESSAGE_PARA para = { 0 };
|
|
PCCERT_CONTEXT cert;
|
|
DWORD cbDecoded;
|
|
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.cbSize = sizeof(para);
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.cbSize = 0;
|
|
para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
para.cbSize = sizeof(para);
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL);
|
|
ok(!ret &&
|
|
(GetLastError() == CRYPT_E_ASN1_EOD ||
|
|
GetLastError() == OSS_BAD_ARG), /* win9x */
|
|
"Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
|
|
/* Check whether cert is set on error */
|
|
cert = (PCCERT_CONTEXT)0xdeadbeef;
|
|
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, &cert);
|
|
ok(cert == NULL, "Expected NULL cert\n");
|
|
/* Check whether cbDecoded is set on error */
|
|
cbDecoded = 0xdeadbeef;
|
|
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, &cbDecoded,
|
|
NULL);
|
|
ok(!cbDecoded, "Expected 0\n");
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(¶, 0, dataEmptyBareContent,
|
|
sizeof(dataEmptyBareContent), NULL, 0, NULL);
|
|
ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
|
|
GetLastError() == OSS_PDU_MISMATCH, /* win9x */
|
|
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(¶, 0, dataEmptyContent,
|
|
sizeof(dataEmptyContent), NULL, 0, NULL);
|
|
ok(!ret && GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE,
|
|
"Expected CRYPT_E_UNEXPECTED_MSG_TYPE, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(¶, 0, signedEmptyBareContent,
|
|
sizeof(signedEmptyBareContent), NULL, 0, NULL);
|
|
ok(!ret &&
|
|
(GetLastError() == CRYPT_E_ASN1_BADTAG ||
|
|
GetLastError() == OSS_DATA_ERROR), /* win9x */
|
|
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(¶, 0, signedEmptyContent,
|
|
sizeof(signedEmptyContent), NULL, 0, NULL);
|
|
ok(!ret &&
|
|
(GetLastError() == CRYPT_E_NOT_FOUND ||
|
|
GetLastError() == OSS_DATA_ERROR), /* win9x */
|
|
"Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptVerifyMessageSignature(¶, 0, signedContent,
|
|
sizeof(signedContent), NULL, 0, NULL);
|
|
ok(!ret &&
|
|
(GetLastError() == CRYPT_E_NOT_FOUND ||
|
|
GetLastError() == OSS_DATA_ERROR), /* win9x */
|
|
"Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
|
/* FIXME: Windows fails with CRYPT_E_NOT_FOUND for these messages, but
|
|
* their signer certs have invalid public keys that fail to decode. In
|
|
* Wine therefore the failure is an ASN error. Need some messages with
|
|
* valid public keys and invalid signatures to check against.
|
|
*/
|
|
ret = CryptVerifyMessageSignature(¶, 0, signedWithCertEmptyContent,
|
|
sizeof(signedWithCertEmptyContent), NULL, 0, NULL);
|
|
ok(!ret, "Expected failure\n");
|
|
ret = CryptVerifyMessageSignature(¶, 0, signedWithCertContent,
|
|
sizeof(signedWithCertContent), NULL, 0, NULL);
|
|
ok(!ret, "Expected failure\n");
|
|
ret = CryptVerifyMessageSignature(¶, 0, signedWithCertWithPubKeyContent,
|
|
sizeof(signedWithCertWithPubKeyContent), NULL, 0, NULL);
|
|
ok(!ret, "Expected failure\n");
|
|
}
|
|
|
|
static const BYTE detachedHashBlob[] = {
|
|
0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
|
|
0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
|
0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
|
0x07,0x01,0x04,0x10,0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,
|
|
0x24,0xb9,0x66,0x7c,0x21 };
|
|
static const BYTE hashBlob[] = {
|
|
0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
|
|
0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
|
0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
|
0x07,0x01,0xa0,0x06,0x04,0x04,0xde,0xad,0xbe,0xef,0x04,0x10,0x2f,0x24,0x92,
|
|
0x30,0xa8,0xe7,0xc2,0xbf,0x60,0x05,0xcc,0xd2,0x67,0x92,0x59,0xec };
|
|
static const BYTE hashVal[] = {
|
|
0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,0x24,0xb9,0x66,0x7c,
|
|
0x21 };
|
|
|
|
static void test_hash_message(void)
|
|
{
|
|
BOOL ret;
|
|
CRYPT_HASH_MESSAGE_PARA para;
|
|
static const BYTE blob1[] = { 0xde, 0xad, 0xbe, 0xef };
|
|
static const BYTE blob2[] = { 0xba, 0xad, 0xf0, 0x0d };
|
|
const BYTE *toHash[] = { blob1, blob2 };
|
|
DWORD hashSize[] = { sizeof(blob1), sizeof(blob2) };
|
|
DWORD hashedBlobSize, computedHashSize;
|
|
static char oid_rsa_md5[] = szOID_RSA_MD5;
|
|
LPBYTE hashedBlob, computedHash;
|
|
|
|
/* Crash
|
|
ret = CryptHashMessage(NULL, FALSE, 0, NULL, 0, NULL, NULL, NULL, NULL);
|
|
*/
|
|
memset(¶, 0, sizeof(para));
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
"expected E_INVALIDARG, got 0x%08x\n", GetLastError());
|
|
para.cbSize = sizeof(para);
|
|
/* Not quite sure what "success" means in this case, but it does succeed */
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
/* With a bogus encoding type it "succeeds" */
|
|
para.dwMsgEncodingType = 0xdeadbeef;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
/* According to MSDN, the third parameter (cToBeHashed) must be 1 if the
|
|
* second parameter (fDetached) is FALSE, but again it "succeeds."
|
|
*/
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
/* Even passing parameters to hash results in "success." */
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
|
|
NULL);
|
|
/* Try again with a valid encoding type */
|
|
para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
/* And with valid data to hash */
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
|
|
NULL);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
/* But requesting the size of the hashed blob and indicating there's data
|
|
* to hash results in a crash
|
|
*/
|
|
if (0)
|
|
{
|
|
ret = CryptHashMessage(¶, FALSE, 2, NULL, NULL, NULL,
|
|
&hashedBlobSize, NULL, NULL);
|
|
}
|
|
/* Passing a valid pointer for the data to hash fails, as the hash
|
|
* algorithm is finally checked.
|
|
*/
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL,
|
|
&hashedBlobSize, NULL, NULL);
|
|
ok(!ret &&
|
|
(GetLastError() == CRYPT_E_UNKNOWN_ALGO ||
|
|
GetLastError() == CRYPT_E_OID_FORMAT), /* Vista */
|
|
"expected CRYPT_E_UNKNOWN_ALGO or CRYPT_E_OID_FORMAT, got 0x%08x (%d)\n",
|
|
GetLastError(), GetLastError());
|
|
para.HashAlgorithm.pszObjId = oid_rsa_md5;
|
|
/* With a valid hash algorithm, this succeeds, even though fDetached is
|
|
* FALSE.
|
|
*/
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL,
|
|
&hashedBlobSize, NULL, NULL);
|
|
todo_wine
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
if (ret)
|
|
{
|
|
/* Actually attempting to get the hashed data fails, perhaps because
|
|
* detached is FALSE.
|
|
*/
|
|
hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, hashedBlob,
|
|
&hashedBlobSize, NULL, NULL);
|
|
ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
|
|
"expected CRYPT_E_MSG_ERROR, got 0x%08x (%d)\n", GetLastError(),
|
|
GetLastError());
|
|
HeapFree(GetProcessHeap(), 0, hashedBlob);
|
|
}
|
|
/* Repeating tests with fDetached = TRUE results in success */
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, NULL,
|
|
&hashedBlobSize, NULL, NULL);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
if (ret)
|
|
{
|
|
hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, hashedBlob,
|
|
&hashedBlobSize, NULL, NULL);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
ok(hashedBlobSize == sizeof(detachedHashBlob),
|
|
"unexpected size of detached blob %d\n", hashedBlobSize);
|
|
ok(!memcmp(hashedBlob, detachedHashBlob, hashedBlobSize),
|
|
"unexpected detached blob value\n");
|
|
HeapFree(GetProcessHeap(), 0, hashedBlob);
|
|
}
|
|
/* Hashing a single item with fDetached = FALSE also succeeds */
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, FALSE, 1, toHash, hashSize, NULL,
|
|
&hashedBlobSize, NULL, NULL);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
if (ret)
|
|
{
|
|
hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
|
|
ret = CryptHashMessage(¶, FALSE, 1, toHash, hashSize, hashedBlob,
|
|
&hashedBlobSize, NULL, NULL);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
ok(hashedBlobSize == sizeof(hashBlob),
|
|
"unexpected size of detached blob %d\n", hashedBlobSize);
|
|
ok(!memcmp(hashedBlob, hashBlob, hashedBlobSize),
|
|
"unexpected detached blob value\n");
|
|
HeapFree(GetProcessHeap(), 0, hashedBlob);
|
|
}
|
|
/* Check the computed hash value too. You don't need to get the encoded
|
|
* blob to get it.
|
|
*/
|
|
computedHashSize = 0xdeadbeef;
|
|
ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, NULL,
|
|
&hashedBlobSize, NULL, &computedHashSize);
|
|
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
|
ok(computedHashSize == 16, "expected hash size of 16, got %d\n",
|
|
computedHashSize);
|
|
if (ret)
|
|
{
|
|
computedHash = HeapAlloc(GetProcessHeap(), 0, computedHashSize);
|
|
SetLastError(0xdeadbeef);
|
|
ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, NULL,
|
|
&hashedBlobSize, computedHash, &computedHashSize);
|
|
ok(computedHashSize == sizeof(hashVal),
|
|
"unexpected size of hash value %d\n", computedHashSize);
|
|
ok(!memcmp(computedHash, hashVal, computedHashSize),
|
|
"unexpected value\n");
|
|
HeapFree(GetProcessHeap(), 0, computedHash);
|
|
}
|
|
}
|
|
|
|
START_TEST(message)
|
|
{
|
|
test_msg_get_signer_count();
|
|
test_verify_detached_message_hash();
|
|
test_verify_message_hash();
|
|
test_verify_detached_message_signature();
|
|
test_verify_message_signature();
|
|
test_hash_message();
|
|
}
|