|  | /* | 
|  | * 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 BOOL (WINAPI * pCryptAcquireContextA) | 
|  | (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD); | 
|  |  | 
|  | static void init_function_pointers(void) | 
|  | { | 
|  | HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll"); | 
|  |  | 
|  | #define GET_PROC(dll, func) \ | 
|  | p ## func = (void *)GetProcAddress(dll, #func); \ | 
|  | if(!p ## func) \ | 
|  | trace("GetProcAddress(%s) failed\n", #func); | 
|  |  | 
|  | GET_PROC(hAdvapi32, CryptAcquireContextA) | 
|  |  | 
|  | #undef GET_PROC | 
|  | } | 
|  |  | 
|  | 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) | 
|  | { | 
|  | 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 const BYTE signedWithCertWithValidPubKeyContent[] = { | 
|  | 0x30,0x82,0x01,0x89,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02, | 
|  | 0xa0,0x82,0x01,0x7a,0x30,0x82,0x01,0x76,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,0x81,0xd2,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,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 void test_verify_message_signature(void) | 
|  | { | 
|  | BOOL ret; | 
|  | CRYPT_VERIFY_MESSAGE_PARA para = { 0 }; | 
|  | PCCERT_CONTEXT cert; | 
|  | DWORD cbDecoded; | 
|  | BYTE decoded[sizeof(msgData)]; | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL); | 
|  | ok(!ret && GetLastError() == E_INVALIDARG, | 
|  | "Expected E_INVALIDARG, got %08x\n", GetLastError()); | 
|  | /* Is cbDecoded set when invalid parameters are passed? */ | 
|  | cbDecoded = 0xdeadbeef; | 
|  | ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, &cbDecoded, | 
|  | NULL); | 
|  | ok(!ret && GetLastError() == E_INVALIDARG, | 
|  | "Expected E_INVALIDARG, got %08x\n", GetLastError()); | 
|  | ok(cbDecoded == 0, "expected 0, got %08x\n", cbDecoded); | 
|  | 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(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || | 
|  | GetLastError() == OSS_BAD_ARG /* NT40 */), | 
|  | "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); | 
|  | 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(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || | 
|  | GetLastError() == OSS_BAD_ARG /* NT40 */), | 
|  | "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); | 
|  | ok(!cbDecoded, "Expected 0\n"); | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptVerifyMessageSignature(¶, 0, dataEmptyBareContent, | 
|  | sizeof(dataEmptyBareContent), NULL, 0, NULL); | 
|  | ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || | 
|  | GetLastError() == OSS_PDU_MISMATCH /* NT40 */), | 
|  | "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); | 
|  | 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"); | 
|  | /* Apparently, an output pcbDecoded parameter is expected. */ | 
|  | ret = CryptVerifyMessageSignature(¶, 0, | 
|  | signedWithCertWithValidPubKeyContent, | 
|  | sizeof(signedWithCertWithValidPubKeyContent), NULL, 0, NULL); | 
|  | ok(!ret, "Expected failure\n"); | 
|  | /* Finally, a message signed with a valid public key verifies successfully | 
|  | */ | 
|  | cbDecoded = 0xdeadbeef; | 
|  | ret = CryptVerifyMessageSignature(¶, 0, | 
|  | signedWithCertWithValidPubKeyContent, | 
|  | sizeof(signedWithCertWithValidPubKeyContent), NULL, &cbDecoded, NULL); | 
|  | ok(ret, "CryptVerifyMessageSignature failed: %08x\n", GetLastError()); | 
|  | ok(cbDecoded == sizeof(msgData), "expected 4, got %d\n", cbDecoded); | 
|  | cbDecoded = 0; | 
|  | ret = CryptVerifyMessageSignature(¶, 0, | 
|  | signedWithCertWithValidPubKeyContent, | 
|  | sizeof(signedWithCertWithValidPubKeyContent), NULL, &cbDecoded, NULL); | 
|  | /* Setting cbDecoded to 0 succeeds when a NULL buffer is provided */ | 
|  | ok(ret, "CryptVerifyMessageSignature failed: %08x\n", GetLastError()); | 
|  | ok(cbDecoded == sizeof(msgData), "expected 4, got %d\n", cbDecoded); | 
|  | cbDecoded = 0; | 
|  | ret = CryptVerifyMessageSignature(¶, 0, | 
|  | signedWithCertWithValidPubKeyContent, | 
|  | sizeof(signedWithCertWithValidPubKeyContent), decoded, &cbDecoded, NULL); | 
|  | /* When a non-NULL buffer is provided, cbDecoded must not be too small */ | 
|  | ok(!ret && GetLastError() == ERROR_MORE_DATA, | 
|  | "expected ERROR_MORE_DATA, got %d (%08x)\n", GetLastError(), | 
|  | GetLastError()); | 
|  | } | 
|  |  | 
|  | 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); | 
|  | ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); | 
|  | /* 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) | 
|  | { | 
|  | 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(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); | 
|  | ok(computedHashSize == sizeof(hashVal), | 
|  | "unexpected size of hash value %d\n", computedHashSize); | 
|  | ok(!memcmp(computedHash, hashVal, computedHashSize), | 
|  | "unexpected value\n"); | 
|  | HeapFree(GetProcessHeap(), 0, computedHash); | 
|  | } | 
|  | } | 
|  |  | 
|  | static const BYTE publicPrivateKeyPair[] = { | 
|  | 0x07,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x32,0x00,0x02,0x00, | 
|  | 0x00,0x01,0x00,0x01,0x00,0x9b,0xd9,0x60,0xd9,0x5b,0x09,0x50,0x9e,0x09,0x94, | 
|  | 0x1e,0x6a,0x06,0x1d,0xdd,0x39,0xc5,0x96,0x17,0xe3,0xb9,0x0c,0x71,0x9c,0xf7, | 
|  | 0xc1,0x07,0x7b,0xd7,0x4a,0xaa,0x8a,0x3e,0xcd,0x78,0x3c,0x4c,0x95,0x98,0x28, | 
|  | 0x29,0x2d,0xe0,0xfc,0xe6,0x4f,0x95,0xca,0x87,0x92,0xdd,0xa3,0x8d,0xf0,0x39, | 
|  | 0xf3,0x1b,0x87,0x64,0x82,0x99,0xc0,0xa9,0xe8,0x87,0x86,0x2e,0x72,0x07,0x07, | 
|  | 0x8f,0x45,0x54,0x51,0x2f,0x51,0xd0,0x60,0x97,0x48,0x54,0x0e,0x78,0xb5,0x7e, | 
|  | 0x2b,0x9d,0xca,0x81,0xa8,0xa8,0x00,0x57,0x69,0xa6,0xf7,0x4d,0x45,0xe0,0xf7, | 
|  | 0xfa,0xd2,0xeb,0xaa,0xb8,0x06,0x34,0xce,0xf0,0x9d,0x2b,0x76,0x8a,0x4f,0x70, | 
|  | 0x51,0x90,0x33,0x72,0xcb,0x81,0x85,0x7e,0x35,0x2e,0xfb,0x81,0xf0,0xc7,0x85, | 
|  | 0xa5,0x75,0xf9,0x2d,0x00,0x71,0x66,0x36,0xfe,0x22,0xd6,0xc9,0x36,0x61,0x9b, | 
|  | 0x64,0x92,0xe8,0x25,0x38,0x35,0xeb,0x0c,0x84,0x83,0x76,0x42,0x90,0xf7,0x73, | 
|  | 0x91,0xdc,0x43,0x83,0x07,0x77,0xc9,0x1b,0x3f,0x74,0xc0,0xbe,0x18,0x97,0xd6, | 
|  | 0x86,0xe5,0xfa,0x28,0x7c,0xf7,0x8d,0x89,0xb1,0x93,0xac,0x48,0x3c,0xa1,0x02, | 
|  | 0xfa,0xc6,0x1c,0xa0,0xb5,0xe8,0x4f,0xd7,0xd1,0x33,0x63,0x8b,0x7e,0xf1,0x94, | 
|  | 0x56,0x07,0xbc,0x6e,0x0c,0xbd,0xa0,0x15,0xba,0x99,0x5d,0xb7,0x5e,0x09,0xf2, | 
|  | 0x1b,0x46,0x85,0x61,0x91,0x6a,0x78,0x31,0xb5,0xf0,0xba,0x20,0xf5,0x7a,0xb4, | 
|  | 0x8e,0xd3,0x50,0x87,0xf8,0xf3,0xe4,0xd9,0xab,0x6f,0x0e,0x59,0x42,0xac,0x7d, | 
|  | 0xb1,0x8c,0xea,0x33,0x54,0x08,0x38,0xc9,0xcd,0xac,0x10,0x19,0x4a,0xba,0x89, | 
|  | 0xdc,0xb6,0x73,0xef,0xec,0x56,0x93,0xd6,0xf2,0x4b,0xba,0x50,0x2d,0x8f,0x15, | 
|  | 0xed,0x8b,0xb5,0x67,0xc8,0xfc,0x51,0x5f }; | 
|  | static const BYTE cert1[] = { | 
|  | 0x30,0x81,0xd0,0x30,0x81,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x20,0x42, | 
|  | 0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30, | 
|  | 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,0x0a,0x30, | 
|  | 0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x20,0x17,0x0d,0x31,0x30, | 
|  | 0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x18,0x0f,0x33,0x30, | 
|  | 0x31,0x30,0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x30,0x0c, | 
|  | 0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,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,0xe8,0xa9,0xc0,0x99,0x82,0x64,0x87,0x1b, | 
|  | 0xf3,0x39,0xf0,0x8d,0xa3,0xdd,0x92,0x87,0xca,0x95,0x4f,0xe6,0xfc,0xe0,0x2d, | 
|  | 0x29,0x28,0x98,0x95,0x4c,0x3c,0x78,0xcd,0x3e,0x8a,0xaa,0x4a,0xd7,0x7b,0x07, | 
|  | 0xc1,0xf7,0x9c,0x71,0x0c,0xb9,0xe3,0x17,0x96,0xc5,0x39,0xdd,0x1d,0x06,0x6a, | 
|  | 0x1e,0x94,0x09,0x9e,0x50,0x09,0x5b,0xd9,0x60,0xd9,0x9b,0x02,0x03,0x01,0x00, | 
|  | 0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00, | 
|  | 0xc1 }; | 
|  | static const BYTE cert2[] = { | 
|  | 0x30,0x82,0x01,0x15,0x30,0x82,0x01,0x02,0xa0,0x03,0x02,0x01,0x02,0x02,0x10, | 
|  | 0x1c,0xf2,0x1f,0xec,0x6b,0xdc,0x36,0xbf,0x4a,0xd7,0xe1,0x6c,0x84,0x85,0xcd, | 
|  | 0x2e,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31, | 
|  | 0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x58,0x30,0x20,0x17,0x0d, | 
|  | 0x31,0x30,0x30,0x37,0x31,0x32,0x31,0x31,0x33,0x37,0x35,0x36,0x5a,0x18,0x0f, | 
|  | 0x33,0x30,0x31,0x30,0x30,0x37,0x31,0x32,0x31,0x31,0x33,0x37,0x35,0x36,0x5a, | 
|  | 0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x58,0x30, | 
|  | 0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, | 
|  | 0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xab,0xed, | 
|  | 0x6e,0xe0,0x00,0x3c,0xcf,0x2d,0x2b,0xda,0x05,0x88,0x6a,0x7e,0xed,0x60,0x30, | 
|  | 0x24,0xef,0x6c,0x6b,0xad,0x28,0x9b,0x14,0x90,0xf6,0xd0,0x96,0x79,0x6d,0xad, | 
|  | 0xac,0x46,0x14,0x7b,0x0e,0xfe,0xa9,0x8a,0x05,0x5a,0xc8,0x84,0x38,0x44,0xf9, | 
|  | 0xce,0xb2,0xe6,0xde,0x5b,0x80,0x0b,0x15,0xff,0x1b,0x60,0x3f,0xba,0xb2,0xfe, | 
|  | 0x6e,0xf5,0xdc,0x54,0x33,0xfc,0xfc,0x79,0x0a,0x10,0xa4,0x23,0x6d,0x67,0xeb, | 
|  | 0x16,0xb2,0x92,0xbf,0x63,0x42,0x17,0x0a,0xde,0xe6,0xab,0x8e,0xf7,0x8e,0x41, | 
|  | 0x8c,0x04,0xe8,0xe2,0x38,0x73,0xd3,0x82,0xd7,0xd1,0xee,0xd3,0xa6,0x54,0x8c, | 
|  | 0xcd,0x0b,0x93,0xda,0x63,0x55,0x0d,0x1f,0x68,0x5c,0x30,0xee,0xad,0x2d,0xd5, | 
|  | 0x40,0x56,0xe0,0xd8,0xc7,0xef,0x02,0x03,0x01,0x00,0x01,0x30,0x09,0x06,0x05, | 
|  | 0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,0x06 }; | 
|  | static const BYTE crl[] = { | 
|  | 0x30,0x81,0xc2,0x30,0x7e,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48, | 
|  | 0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x3c,0x31,0x0b,0x30,0x09,0x06, | 
|  | 0x03,0x55,0x04,0x06,0x13,0x02,0x52,0x55,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55, | 
|  | 0x04,0x08,0x13,0x03,0x53,0x50,0x62,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04, | 
|  | 0x07,0x13,0x03,0x53,0x50,0x62,0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x0a, | 
|  | 0x13,0x08,0x45,0x74,0x65,0x72,0x73,0x6f,0x66,0x74,0x17,0x0d,0x31,0x30,0x30, | 
|  | 0x36,0x32,0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0x17,0x0d,0x31,0x30,0x30, | 
|  | 0x37,0x32,0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0xa0,0x0e,0x30,0x0c,0x30, | 
|  | 0x0a,0x06,0x03,0x55,0x1d,0x14,0x04,0x03,0x02,0x01,0x00,0x30,0x0d,0x06,0x09, | 
|  | 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x31,0x00,0x83, | 
|  | 0x35,0x9c,0xf5,0x35,0x5c,0xc1,0x20,0x81,0x80,0x5c,0x35,0x56,0xaf,0xb3,0x27, | 
|  | 0x15,0xc6,0xdd,0x24,0xe1,0xff,0xb9,0xf9,0x19,0x21,0xed,0x5e,0x1b,0xff,0x72, | 
|  | 0xc3,0x33,0xf6,0x9f,0xcb,0xde,0x84,0x0b,0x12,0x84,0xad,0x48,0x90,0x9d,0xdd, | 
|  | 0x89,0xbb }; | 
|  | static const BYTE signedHashForEmptyMessage[] = { | 
|  | 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, | 
|  | 0x81,0xad,0x30,0x81,0xaa,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,0x81,0x87,0x30,0x81,0x84,0x02,0x01, | 
|  | 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13, | 
|  | 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0, | 
|  | 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, | 
|  | 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, | 
|  | 0x01,0x01,0x05,0x00,0x04,0x40,0xe1,0xee,0xca,0x98,0x16,0x23,0x5a,0x34,0xfd, | 
|  | 0x91,0x69,0x97,0x1e,0x16,0xe4,0x57,0x45,0xad,0xc9,0x5d,0x2e,0xda,0x92,0xbf, | 
|  | 0xee,0x2f,0xb1,0xaa,0x32,0xfa,0x07,0x4e,0x63,0xfd,0xe1,0x52,0x17,0xd0,0xa4, | 
|  | 0x49,0x30,0x54,0x4d,0x12,0xa0,0x6a,0x1c,0x64,0xea,0xc7,0x50,0x49,0xa5,0xca, | 
|  | 0xc3,0x71,0xa4,0xf7,0x8c,0x25,0xe4,0x1a,0xca,0x89 }; | 
|  | static const BYTE signedEmptyMessage[] = { | 
|  | 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, | 
|  | 0x81,0xad,0x30,0x81,0xaa,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,0x81,0x87,0x30,0x81,0x84,0x02,0x01, | 
|  | 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13, | 
|  | 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0, | 
|  | 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, | 
|  | 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, | 
|  | 0x01,0x01,0x05,0x00,0x04,0x40,0xe1,0xee,0xca,0x98,0x16,0x23,0x5a,0x34,0xfd, | 
|  | 0x91,0x69,0x97,0x1e,0x16,0xe4,0x57,0x45,0xad,0xc9,0x5d,0x2e,0xda,0x92,0xbf, | 
|  | 0xee,0x2f,0xb1,0xaa,0x32,0xfa,0x07,0x4e,0x63,0xfd,0xe1,0x52,0x17,0xd0,0xa4, | 
|  | 0x49,0x30,0x54,0x4d,0x12,0xa0,0x6a,0x1c,0x64,0xea,0xc7,0x50,0x49,0xa5,0xca, | 
|  | 0xc3,0x71,0xa4,0xf7,0x8c,0x25,0xe4,0x1a,0xca,0x89 }; | 
|  | static const BYTE signedHash[] = { | 
|  | 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, | 
|  | 0x81,0xad,0x30,0x81,0xaa,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,0x81,0x87,0x30,0x81,0x84,0x02,0x01, | 
|  | 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13, | 
|  | 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0, | 
|  | 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, | 
|  | 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, | 
|  | 0x01,0x01,0x05,0x00,0x04,0x40,0x1e,0x04,0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94, | 
|  | 0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,0x82,0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd, | 
|  | 0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,0xb1,0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1, | 
|  | 0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,0x59,0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7, | 
|  | 0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,0xa6,0x43,0xdf }; | 
|  | static const BYTE signedHashWithCert[] = { | 
|  | 0x30,0x82,0x01,0x93,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02, | 
|  | 0xa0,0x82,0x01,0x84,0x30,0x82,0x01,0x80,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,0xa0,0x81,0xd3,0x30,0x81, | 
|  | 0xd0,0x30,0x81,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x20,0x42,0x68,0x69, | 
|  | 0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x09,0x06, | 
|  | 0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06, | 
|  | 0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x20,0x17,0x0d,0x31,0x30,0x30,0x39, | 
|  | 0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x18,0x0f,0x33,0x30,0x31,0x30, | 
|  | 0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x30,0x0c,0x31,0x0a, | 
|  | 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,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,0xe8,0xa9,0xc0,0x99,0x82,0x64,0x87,0x1b,0xf3,0x39, | 
|  | 0xf0,0x8d,0xa3,0xdd,0x92,0x87,0xca,0x95,0x4f,0xe6,0xfc,0xe0,0x2d,0x29,0x28, | 
|  | 0x98,0x95,0x4c,0x3c,0x78,0xcd,0x3e,0x8a,0xaa,0x4a,0xd7,0x7b,0x07,0xc1,0xf7, | 
|  | 0x9c,0x71,0x0c,0xb9,0xe3,0x17,0x96,0xc5,0x39,0xdd,0x1d,0x06,0x6a,0x1e,0x94, | 
|  | 0x09,0x9e,0x50,0x09,0x5b,0xd9,0x60,0xd9,0x9b,0x02,0x03,0x01,0x00,0x01,0x30, | 
|  | 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,0xc1,0x31, | 
|  | 0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30, | 
|  | 0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69, | 
|  | 0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06, | 
|  | 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09, | 
|  | 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0x1e,0x04, | 
|  | 0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,0x82, | 
|  | 0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,0xb1, | 
|  | 0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,0x59, | 
|  | 0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,0xa6, | 
|  | 0x43,0xdf }; | 
|  | static const BYTE signedHashWithCRL[] = { | 
|  | 0x30,0x82,0x01,0x85,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02, | 
|  | 0xa0,0x82,0x01,0x76,0x30,0x82,0x01,0x72,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,0xa1,0x81,0xc5,0x30,0x81, | 
|  | 0xc2,0x30,0x7e,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, | 
|  | 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x3c,0x31,0x0b,0x30,0x09,0x06,0x03,0x55, | 
|  | 0x04,0x06,0x13,0x02,0x52,0x55,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x08, | 
|  | 0x13,0x03,0x53,0x50,0x62,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x07,0x13, | 
|  | 0x03,0x53,0x50,0x62,0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x0a,0x13,0x08, | 
|  | 0x45,0x74,0x65,0x72,0x73,0x6f,0x66,0x74,0x17,0x0d,0x31,0x30,0x30,0x36,0x32, | 
|  | 0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0x17,0x0d,0x31,0x30,0x30,0x37,0x32, | 
|  | 0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0xa0,0x0e,0x30,0x0c,0x30,0x0a,0x06, | 
|  | 0x03,0x55,0x1d,0x14,0x04,0x03,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86, | 
|  | 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x31,0x00,0x83,0x35,0x9c, | 
|  | 0xf5,0x35,0x5c,0xc1,0x20,0x81,0x80,0x5c,0x35,0x56,0xaf,0xb3,0x27,0x15,0xc6, | 
|  | 0xdd,0x24,0xe1,0xff,0xb9,0xf9,0x19,0x21,0xed,0x5e,0x1b,0xff,0x72,0xc3,0x33, | 
|  | 0xf6,0x9f,0xcb,0xde,0x84,0x0b,0x12,0x84,0xad,0x48,0x90,0x9d,0xdd,0x89,0xbb, | 
|  | 0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a, | 
|  | 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68, | 
|  | 0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c, | 
|  | 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06, | 
|  | 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0x1e, | 
|  | 0x04,0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2, | 
|  | 0x82,0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c, | 
|  | 0xb1,0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69, | 
|  | 0x59,0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c, | 
|  | 0xa6,0x43,0xdf }; | 
|  | static const BYTE signedData[] = { | 
|  | 0x30,0x81,0xc3,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, | 
|  | 0x81,0xb5,0x30,0x81,0xb2,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,0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a, | 
|  | 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68, | 
|  | 0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c, | 
|  | 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06, | 
|  | 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0xe4, | 
|  | 0x69,0xf5,0x62,0xfb,0x3a,0x7d,0x1c,0x7b,0x8b,0xcc,0xfc,0x6e,0x8e,0x91,0x85, | 
|  | 0xcf,0x3c,0xb8,0xfd,0x8a,0xac,0x81,0x96,0xa0,0x42,0xac,0x88,0xc4,0x48,0xe8, | 
|  | 0x43,0x64,0xd1,0x38,0xd2,0x6c,0xc4,0xd4,0x9b,0x9a,0xd4,0x33,0x02,0xef,0x88, | 
|  | 0xef,0x98,0x2d,0xac,0xad,0xc1,0x93,0x60,0xc4,0x3a,0xdc,0xa7,0xd6,0x97,0x70, | 
|  | 0x01,0xc1,0x84 }; | 
|  |  | 
|  | static void test_sign_message(void) | 
|  | { | 
|  | BOOL ret; | 
|  | CRYPT_SIGN_MESSAGE_PARA para; | 
|  | static char oid_rsa_md5[] = szOID_RSA_MD5; | 
|  | static const BYTE blob1[] = { 0x01, 0x02, 0x03, 0x04 }; | 
|  | static const BYTE blob2[] = { 0x11, 0x12, 0x13, 0x14 }; | 
|  | const BYTE *toSign[] = { blob1, blob2 }; | 
|  | DWORD signSize[] = { sizeof(blob1), sizeof(blob2) }; | 
|  | LPBYTE signedBlob; | 
|  | DWORD signedBlobSize; | 
|  | PCCRL_CONTEXT crlContext; | 
|  | CERT_KEY_CONTEXT keyContext; | 
|  | HCRYPTPROV hCryptProv = 0; | 
|  | HCRYPTKEY hKey = 0; | 
|  |  | 
|  | memset(¶, 0, sizeof(para)); | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptSignMessage(¶, FALSE, 0, NULL, NULL, NULL, &signedBlobSize); | 
|  | ok(!ret && | 
|  | (GetLastError() == E_INVALIDARG || | 
|  | GetLastError() == ERROR_ARITHMETIC_OVERFLOW), /* Win7 */ | 
|  | "expected E_INVALIDARG or ERROR_ARITHMETIC_OVERFLOW, got %08x\n", | 
|  | GetLastError()); | 
|  | para.cbSize = sizeof(para); | 
|  | para.dwMsgEncodingType = X509_ASN_ENCODING; | 
|  | SetLastError(0xdeadbeef); | 
|  | signedBlobSize = 255; | 
|  | ret = CryptSignMessage(¶, FALSE, 0, NULL, NULL, NULL, &signedBlobSize); | 
|  | ok(!ret && GetLastError() == E_INVALIDARG, | 
|  | "expected E_INVALIDARG, got %08x\n", GetLastError()); | 
|  | 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); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | todo_wine | 
|  | ok(signedBlobSize, "bad size\n"); | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = pCryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL, | 
|  | CRYPT_VERIFYCONTEXT); | 
|  | ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError()); | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptImportKey(hCryptProv, publicPrivateKeyPair, | 
|  | sizeof(publicPrivateKeyPair), 0, 0, &hKey); | 
|  | if (!ret && GetLastError() == NTE_PERM) /* Win9x */ | 
|  | { | 
|  | skip("Failed to import a key\n"); | 
|  | if (hCryptProv) | 
|  | CryptReleaseContext(hCryptProv, 0); | 
|  | return; | 
|  | } | 
|  | ok(ret, "CryptImportKey failed: %08x\n", GetLastError()); | 
|  |  | 
|  | para.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; | 
|  | SetLastError(0xdeadbeef); | 
|  | para.pSigningCert = CertCreateCertificateContext(X509_ASN_ENCODING | | 
|  | PKCS_7_ASN_ENCODING, cert1, sizeof(cert1)); | 
|  | ok(para.pSigningCert != NULL, "CertCreateCertificateContext failed: %08x\n", | 
|  | GetLastError()); | 
|  | para.HashAlgorithm.pszObjId = oid_rsa_md5; | 
|  |  | 
|  | memset(&keyContext, 0, sizeof(keyContext)); | 
|  | keyContext.cbSize = sizeof(keyContext); | 
|  | keyContext.hCryptProv = hCryptProv; | 
|  | keyContext.dwKeySpec = AT_SIGNATURE; | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CertSetCertificateContextProperty(para.pSigningCert, | 
|  | CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext); | 
|  | ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError()); | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | signedBlobSize = 0; | 
|  | ret = CryptSignMessage(¶, TRUE, 0, NULL, NULL, NULL, &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | signedBlob = CryptMemAlloc(signedBlobSize); | 
|  | if (signedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptSignMessage(¶, TRUE, 0, NULL, NULL, signedBlob, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | ok(signedBlobSize == sizeof(signedHashForEmptyMessage), | 
|  | "unexpected size %d\n", signedBlobSize); | 
|  | ok(!memcmp(signedBlob, signedHashForEmptyMessage, signedBlobSize), | 
|  | "unexpected value\n"); | 
|  | CryptMemFree(signedBlob); | 
|  | } | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | signedBlobSize = 0; | 
|  | ret = CryptSignMessage(¶, FALSE, 0, NULL, NULL, NULL, &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | signedBlob = CryptMemAlloc(signedBlobSize); | 
|  | if (signedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptSignMessage(¶, FALSE, 0, NULL, NULL, signedBlob, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | ok(signedBlobSize == sizeof(signedEmptyMessage), "unexpected size %d\n", | 
|  | signedBlobSize); | 
|  | ok(!memcmp(signedBlob, signedEmptyMessage, signedBlobSize), | 
|  | "unexpected value\n"); | 
|  | CryptMemFree(signedBlob); | 
|  | } | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | signedBlobSize = 0; | 
|  | ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, NULL, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | signedBlob = CryptMemAlloc(signedBlobSize); | 
|  | if (signedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, signedBlob, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | ok(signedBlobSize == sizeof(signedHash), | 
|  | "unexpected size of signed blob %d\n", signedBlobSize); | 
|  | ok(!memcmp(signedBlob, signedHash, signedBlobSize), | 
|  | "unexpected value\n"); | 
|  | CryptMemFree(signedBlob); | 
|  | } | 
|  |  | 
|  | para.cMsgCert = 1; | 
|  | para.rgpMsgCert = ¶.pSigningCert; | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | signedBlobSize = 0; | 
|  | ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, NULL, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | signedBlob = CryptMemAlloc(signedBlobSize); | 
|  | if (signedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, signedBlob, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | ok(signedBlobSize == sizeof(signedHashWithCert), | 
|  | "unexpected size of signed blob %d\n", signedBlobSize); | 
|  | ok(!memcmp(signedBlob, signedHashWithCert, signedBlobSize), | 
|  | "unexpected value\n"); | 
|  | CryptMemFree(signedBlob); | 
|  | } | 
|  |  | 
|  | para.cMsgCert = 0; | 
|  | para.rgpMsgCert = NULL; | 
|  | para.cMsgCrl = 1; | 
|  | SetLastError(0xdeadbeef); | 
|  | crlContext = CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | 
|  | crl, sizeof(crl)); | 
|  | ok(crlContext != NULL, "CertCreateCRLContext failed: %08x\n", | 
|  | GetLastError()); | 
|  | para.rgpMsgCrl = &crlContext; | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | signedBlobSize = 0; | 
|  | ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, NULL, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | signedBlob = CryptMemAlloc(signedBlobSize); | 
|  | if (signedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptSignMessage(¶, TRUE, 2, toSign, signSize, signedBlob, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | ok(signedBlobSize == sizeof(signedHashWithCRL), | 
|  | "unexpected size of signed blob %d\n", signedBlobSize); | 
|  | ok(!memcmp(signedBlob, signedHashWithCRL, signedBlobSize), | 
|  | "unexpected value\n"); | 
|  | CryptMemFree(signedBlob); | 
|  | } | 
|  |  | 
|  | CertFreeCRLContext(crlContext); | 
|  | para.cMsgCrl = 0; | 
|  | para.rgpMsgCrl = NULL; | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | signedBlobSize = 0; | 
|  | ret = CryptSignMessage(¶, FALSE, 1, toSign, signSize, NULL, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | signedBlob = CryptMemAlloc(signedBlobSize); | 
|  | if (signedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptSignMessage(¶, FALSE, 1, toSign, signSize, signedBlob, | 
|  | &signedBlobSize); | 
|  | ok(ret, "CryptSignMessage failed: %08x\n", GetLastError()); | 
|  | ok(signedBlobSize == sizeof(signedData), | 
|  | "unexpected size of signed blob %d\n", signedBlobSize); | 
|  | ok(!memcmp(signedBlob, signedData, signedBlobSize), | 
|  | "unexpected value\n"); | 
|  | CryptMemFree(signedBlob); | 
|  | } | 
|  |  | 
|  | if (para.pSigningCert) | 
|  | CertFreeCertificateContext(para.pSigningCert); | 
|  | if (hKey) | 
|  | CryptDestroyKey(hKey); | 
|  | if (hCryptProv) | 
|  | CryptReleaseContext(hCryptProv, 0); | 
|  | } | 
|  |  | 
|  | static const BYTE encryptedMessage[] = { | 
|  | 0x30,0x31,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x03,0xa0,0x24, | 
|  | 0x30,0x22,0x02,0x01,0x00,0x31,0x00,0x30,0x1b,0x06,0x09,0x2a,0x86,0x48,0x86, | 
|  | 0xf7,0x0d,0x01,0x07,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, | 
|  | 0x03,0x04,0x05,0x00,0x80,0x00 }; | 
|  |  | 
|  | static void test_encrypt_message(void) | 
|  | { | 
|  | BOOL ret; | 
|  | CRYPT_ENCRYPT_MESSAGE_PARA para; | 
|  | static char oid_rsa_rc4[] = szOID_RSA_RC4; | 
|  | static const BYTE blob[] = { 0x01, 0x02, 0x03, 0x04 }; | 
|  | PCCERT_CONTEXT certs[2]; | 
|  | HCRYPTPROV hCryptProv = 0; | 
|  | LPBYTE encryptedBlob; | 
|  | DWORD encryptedBlobSize; | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = pCryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL, | 
|  | CRYPT_VERIFYCONTEXT); | 
|  | ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError()); | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING | | 
|  | PKCS_7_ASN_ENCODING, cert1, sizeof(cert1)); | 
|  | ok(certs[0] != NULL, "CertCreateCertificateContext failed: %08x\n", | 
|  | GetLastError()); | 
|  | SetLastError(0xdeadbeef); | 
|  | certs[1] = CertCreateCertificateContext(X509_ASN_ENCODING | | 
|  | PKCS_7_ASN_ENCODING, cert2, sizeof(cert2)); | 
|  | ok(certs[1] != NULL, "CertCreateCertificateContext failed: %08x\n", | 
|  | GetLastError()); | 
|  |  | 
|  | memset(¶, 0, sizeof(para)); | 
|  | SetLastError(0xdeadbeef); | 
|  | encryptedBlobSize = 255; | 
|  | ret = CryptEncryptMessage(¶, 0, NULL, NULL, 0, NULL, | 
|  | &encryptedBlobSize); | 
|  | ok(!ret && GetLastError() == E_INVALIDARG, | 
|  | "expected E_INVALIDARG, got %08x\n", GetLastError()); | 
|  | ok(!encryptedBlobSize, "unexpected size %d\n", encryptedBlobSize); | 
|  | para.cbSize = sizeof(para); | 
|  | para.dwMsgEncodingType = X509_ASN_ENCODING; | 
|  | SetLastError(0xdeadbeef); | 
|  | encryptedBlobSize = 255; | 
|  | ret = CryptEncryptMessage(¶, 0, NULL, NULL, 0, NULL, | 
|  | &encryptedBlobSize); | 
|  | ok(!ret && GetLastError() == E_INVALIDARG, | 
|  | "expected E_INVALIDARG, got %08x\n", GetLastError()); | 
|  | ok(!encryptedBlobSize, "unexpected size %d\n", encryptedBlobSize); | 
|  | para.dwMsgEncodingType = PKCS_7_ASN_ENCODING; | 
|  | SetLastError(0xdeadbeef); | 
|  | encryptedBlobSize = 255; | 
|  | ret = CryptEncryptMessage(¶, 0, NULL, NULL, 0, NULL, | 
|  | &encryptedBlobSize); | 
|  | ok(!ret && | 
|  | (GetLastError() == CRYPT_E_UNKNOWN_ALGO || | 
|  | GetLastError() == E_INVALIDARG), /* Win9x */ | 
|  | "expected CRYPT_E_UNKNOWN_ALGO or E_INVALIDARG, got %08x\n", | 
|  | GetLastError()); | 
|  | ok(!encryptedBlobSize, "unexpected size %d\n", encryptedBlobSize); | 
|  |  | 
|  | para.hCryptProv = hCryptProv; | 
|  | para.ContentEncryptionAlgorithm.pszObjId = oid_rsa_rc4; | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | encryptedBlobSize = 0; | 
|  | ret = CryptEncryptMessage(¶, 0, NULL, NULL, 0, NULL, | 
|  | &encryptedBlobSize); | 
|  | ok(ret || | 
|  | broken(!ret) /* Win9x */, | 
|  | "CryptEncryptMessage failed: %08x\n", GetLastError()); | 
|  | if (ret) | 
|  | { | 
|  | encryptedBlob = CryptMemAlloc(encryptedBlobSize); | 
|  | if (encryptedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptEncryptMessage(¶, 0, NULL, NULL, 0, encryptedBlob, | 
|  | &encryptedBlobSize); | 
|  | ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError()); | 
|  | ok(encryptedBlobSize == sizeof(encryptedMessage), | 
|  | "unexpected size of encrypted blob %d\n", encryptedBlobSize); | 
|  | ok(!memcmp(encryptedBlob, encryptedMessage, encryptedBlobSize), | 
|  | "unexpected value\n"); | 
|  | CryptMemFree(encryptedBlob); | 
|  | } | 
|  | } | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | encryptedBlobSize = 0; | 
|  | ret = CryptEncryptMessage(¶, 2, certs, NULL, 0, NULL, | 
|  | &encryptedBlobSize); | 
|  | ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError()); | 
|  | if (ret) | 
|  | { | 
|  | encryptedBlob = CryptMemAlloc(encryptedBlobSize); | 
|  | if (encryptedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptEncryptMessage(¶, 2, certs, NULL, 0, encryptedBlob, | 
|  | &encryptedBlobSize); | 
|  | ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError()); | 
|  | CryptMemFree(encryptedBlob); | 
|  | } | 
|  | } | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | encryptedBlobSize = 0; | 
|  | ret = CryptEncryptMessage(¶, 0, NULL, blob, sizeof(blob), NULL, | 
|  | &encryptedBlobSize); | 
|  | ok(ret || | 
|  | broken(!ret) /* Win9x */, | 
|  | "CryptEncryptMessage failed: %08x\n", GetLastError()); | 
|  | if (ret) | 
|  | { | 
|  | encryptedBlob = CryptMemAlloc(encryptedBlobSize); | 
|  | if (encryptedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptEncryptMessage(¶, 0, NULL, blob, sizeof(blob), | 
|  | encryptedBlob, &encryptedBlobSize); | 
|  | ok(ret || | 
|  | broken(!ret && GetLastError() == NTE_PERM), /* some NT4 */ | 
|  | "CryptEncryptMessage failed: %08x\n", GetLastError()); | 
|  | if (ret) | 
|  | { | 
|  | ok(encryptedBlobSize == 55, | 
|  | "unexpected size of encrypted blob %d\n", encryptedBlobSize); | 
|  | } | 
|  | CryptMemFree(encryptedBlob); | 
|  | } | 
|  | } | 
|  |  | 
|  | SetLastError(0xdeadbeef); | 
|  | encryptedBlobSize = 0; | 
|  | ret = CryptEncryptMessage(¶, 2, certs, blob, sizeof(blob), NULL, | 
|  | &encryptedBlobSize); | 
|  | ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError()); | 
|  | if (ret) | 
|  | { | 
|  | encryptedBlob = CryptMemAlloc(encryptedBlobSize); | 
|  | if (encryptedBlob) | 
|  | { | 
|  | SetLastError(0xdeadbeef); | 
|  | ret = CryptEncryptMessage(¶, 2, certs, blob, sizeof(blob), | 
|  | encryptedBlob, &encryptedBlobSize); | 
|  | ok(ret || | 
|  | broken(!ret), /* some Win95 and some NT4 */ | 
|  | "CryptEncryptMessage failed: %08x\n", GetLastError()); | 
|  | CryptMemFree(encryptedBlob); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (certs[0]) | 
|  | CertFreeCertificateContext(certs[0]); | 
|  | if (certs[1]) | 
|  | CertFreeCertificateContext(certs[1]); | 
|  | if (hCryptProv) | 
|  | CryptReleaseContext(hCryptProv, 0); | 
|  | } | 
|  |  | 
|  | START_TEST(message) | 
|  | { | 
|  | init_function_pointers(); | 
|  |  | 
|  | 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(); | 
|  | test_sign_message(); | 
|  | test_encrypt_message(); | 
|  | } |