crypt32: Add test showing only file header is checked for cabinet files.
[wine] / dlls / crypt32 / tests / message.c
1 /*
2  * Unit test suite for crypt32.dll's Crypt*Message functions
3  *
4  * Copyright 2007-2008 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winerror.h>
26 #include <wincrypt.h>
27
28 #include "wine/test.h"
29
30 static const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
31 static const BYTE dataEmptyContent[] = {
32 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
33 0x04,0x00 };
34 static const BYTE signedEmptyBareContent[] = {
35 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
36 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
37 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
38 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
39 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
40 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
41 static const BYTE signedEmptyContent[] = {
42 0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52,
43 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
44 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
45 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
46 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
47 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
48 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
49
50 static void test_msg_get_signer_count(void)
51 {
52     LONG count;
53
54     SetLastError(0xdeadbeef);
55     count = CryptGetMessageSignerCount(0, NULL, 0);
56     ok(count == -1, "Expected -1, got %d\n", count);
57     ok(GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n",
58      GetLastError());
59     SetLastError(0xdeadbeef);
60     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, NULL, 0);
61     ok(count == -1, "Expected -1, got %d\n", count);
62     ok(GetLastError() == CRYPT_E_ASN1_EOD,
63      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
64     SetLastError(0xdeadbeef);
65     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
66      dataEmptyBareContent, sizeof(dataEmptyBareContent));
67     ok(count == -1, "Expected -1, got %d\n", count);
68     ok(GetLastError() == CRYPT_E_ASN1_BADTAG,
69      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
70     SetLastError(0xdeadbeef);
71     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
72      dataEmptyContent, sizeof(dataEmptyContent));
73     ok(count == -1, "Expected -1, got %d\n", count);
74     ok(GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
75      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
76     SetLastError(0xdeadbeef);
77     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
78      signedEmptyBareContent, sizeof(signedEmptyBareContent));
79     ok(count == -1, "Expected -1, got %d\n", count);
80     ok(GetLastError() == CRYPT_E_ASN1_BADTAG,
81      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
82     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
83      signedEmptyContent, sizeof(signedEmptyContent));
84     ok(count == 1, "Expected 1, got %d\n", count);
85 }
86
87 static const BYTE signedContent[] = {
88 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
89 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
90 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
91 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
92 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
93 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
94 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
95 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
96 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
97 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
98 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
99 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
100 0x0d };
101 static const BYTE signedWithCertEmptyContent[] = {
102 0x30,0x81,0xdf,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
103 0x81,0xd1,0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
104 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,
105 0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
106 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
107 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
108 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
109 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
110 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
111 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,
112 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
113 0xff,0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,
114 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
115 0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,
116 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
117 0x00 };
118 static const BYTE signedWithCertContent[] = {
119 0x30,0x82,0x01,0x32,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
120 0xa0,0x82,0x01,0x23,0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
121 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
122 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
123 0x02,0x03,0x04,0xa0,0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
124 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
125 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
126 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
127 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
128 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
129 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
130 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
131 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,
132 0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,
133 0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,
134 0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,
135 0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,
136 0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,
137 0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,
138 0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,
139 0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
140 static const BYTE signedWithCertWithPubKeyContent[] = {
141 0x30,0x81,0xfc,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
142 0x81,0xee,0x30,0x81,0xeb,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
143 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x81,
144 0x98,0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,
145 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,
146 0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
147 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
148 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,
149 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
150 0x6e,0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
151 0x01,0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
152 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,
153 0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,
154 0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
155 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
156 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
157 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
158
159 static void test_verify_message_signature(void)
160 {
161     BOOL ret;
162     CRYPT_VERIFY_MESSAGE_PARA para = { 0 };
163     PCCERT_CONTEXT cert;
164     DWORD cbDecoded;
165
166     SetLastError(0xdeadbeef);
167     ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL);
168     ok(!ret && GetLastError() == E_INVALIDARG,
169      "Expected E_INVALIDARG, got %08x\n", GetLastError());
170     SetLastError(0xdeadbeef);
171     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
172     ok(!ret && GetLastError() == E_INVALIDARG,
173      "Expected E_INVALIDARG, got %08x\n", GetLastError());
174     para.cbSize = sizeof(para);
175     SetLastError(0xdeadbeef);
176     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
177     ok(!ret && GetLastError() == E_INVALIDARG,
178      "Expected E_INVALIDARG, got %08x\n", GetLastError());
179     para.cbSize = 0;
180     para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
181     SetLastError(0xdeadbeef);
182     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
183     ok(!ret && GetLastError() == E_INVALIDARG,
184      "Expected E_INVALIDARG, got %08x\n", GetLastError());
185     para.cbSize = sizeof(para);
186     SetLastError(0xdeadbeef);
187     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
188     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
189      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
190     /* Check whether cert is set on error */
191     cert = (PCCERT_CONTEXT)0xdeadbeef;
192     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, &cert);
193     ok(cert == NULL, "Expected NULL cert\n");
194     /* Check whether cbDecoded is set on error */
195     cbDecoded = 0xdeadbeef;
196     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, &cbDecoded,
197      NULL);
198     ok(!cbDecoded, "Expected 0\n");
199     SetLastError(0xdeadbeef);
200     ret = CryptVerifyMessageSignature(&para, 0, dataEmptyBareContent,
201      sizeof(dataEmptyBareContent), NULL, 0, NULL);
202     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
203      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
204     SetLastError(0xdeadbeef);
205     ret = CryptVerifyMessageSignature(&para, 0, dataEmptyContent,
206      sizeof(dataEmptyContent), NULL, 0, NULL);
207     ok(!ret && GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE,
208      "Expected CRYPT_E_UNEXPECTED_MSG_TYPE, got %08x\n", GetLastError());
209     SetLastError(0xdeadbeef);
210     ret = CryptVerifyMessageSignature(&para, 0, signedEmptyBareContent,
211      sizeof(signedEmptyBareContent), NULL, 0, NULL);
212     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
213      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
214     SetLastError(0xdeadbeef);
215     ret = CryptVerifyMessageSignature(&para, 0, signedEmptyContent,
216      sizeof(signedEmptyContent), NULL, 0, NULL);
217     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
218      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
219     SetLastError(0xdeadbeef);
220     ret = CryptVerifyMessageSignature(&para, 0, signedContent,
221      sizeof(signedContent), NULL, 0, NULL);
222     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
223      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
224     /* FIXME: Windows fails with CRYPT_E_NOT_FOUND for these messages, but
225      * their signer certs have invalid public keys that fail to decode.  In
226      * Wine therefore the failure is an ASN error.  Need some messages with
227      * valid public keys and invalid signatures to check against.
228      */
229     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertEmptyContent,
230      sizeof(signedWithCertEmptyContent), NULL, 0, NULL);
231     ok(!ret, "Expected failure\n");
232     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertContent,
233      sizeof(signedWithCertContent), NULL, 0, NULL);
234     ok(!ret, "Expected failure\n");
235     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertWithPubKeyContent,
236      sizeof(signedWithCertWithPubKeyContent), NULL, 0, NULL);
237     ok(!ret, "Expected failure\n");
238 }
239
240 static const BYTE detachedHashBlob[] = {
241 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
242 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
243 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
244 0x07,0x01,0x04,0x10,0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,
245 0x24,0xb9,0x66,0x7c,0x21 };
246 static const BYTE hashBlob[] = {
247 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
248 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
249 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
250 0x07,0x01,0xa0,0x06,0x04,0x04,0xde,0xad,0xbe,0xef,0x04,0x10,0x2f,0x24,0x92,
251 0x30,0xa8,0xe7,0xc2,0xbf,0x60,0x05,0xcc,0xd2,0x67,0x92,0x59,0xec };
252 static const BYTE hashVal[] = {
253 0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,0x24,0xb9,0x66,0x7c,
254 0x21 };
255
256 static void test_hash_message(void)
257 {
258     BOOL ret;
259     CRYPT_HASH_MESSAGE_PARA para;
260     static const BYTE blob1[] = { 0xde, 0xad, 0xbe, 0xef };
261     static const BYTE blob2[] = { 0xba, 0xad, 0xf0, 0x0d };
262     const BYTE *toHash[] = { blob1, blob2 };
263     DWORD hashSize[] = { sizeof(blob1), sizeof(blob2) };
264     DWORD hashedBlobSize, computedHashSize;
265     static char oid_rsa_md5[] = szOID_RSA_MD5;
266     LPBYTE hashedBlob, computedHash;
267
268     /* Crash
269     ret = CryptHashMessage(NULL, FALSE, 0, NULL, 0, NULL, NULL, NULL, NULL);
270      */
271     memset(&para, 0, sizeof(para));
272     SetLastError(0xdeadbeef);
273     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
274     ok(!ret && GetLastError() == E_INVALIDARG,
275      "expected E_INVALIDARG, got 0x%08x\n", GetLastError());
276     para.cbSize = sizeof(para);
277     /* Not quite sure what "success" means in this case, but it does succeed */
278     SetLastError(0xdeadbeef);
279     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
280     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
281     /* With a bogus encoding type it "succeeds" */
282     para.dwMsgEncodingType = 0xdeadbeef;
283     SetLastError(0xdeadbeef);
284     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
285     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
286     /* According to MSDN, the third parameter (cToBeHashed) must be 1 if the
287      * second parameter (fDetached) is FALSE, but again it "succeeds."
288      */
289     SetLastError(0xdeadbeef);
290     ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
291     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
292     /* Even passing parameters to hash results in "success." */
293     SetLastError(0xdeadbeef);
294     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
295      NULL);
296     /* Try again with a valid encoding type */
297     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
298     SetLastError(0xdeadbeef);
299     ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
300     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
301     /* And with valid data to hash */
302     SetLastError(0xdeadbeef);
303     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
304      NULL);
305     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
306     /* But requesting the size of the hashed blob and indicating there's data
307      * to hash results in a crash
308      */
309     if (0)
310     {
311         ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL,
312          &hashedBlobSize, NULL, NULL);
313     }
314     /* Passing a valid pointer for the data to hash fails, as the hash
315      * algorithm is finally checked.
316      */
317     SetLastError(0xdeadbeef);
318     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
319      &hashedBlobSize, NULL, NULL);
320     ok(!ret && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
321      "expected CRYPT_E_UNKNOWN_ALGO, got 0x%08x (%d)\n", GetLastError(),
322      GetLastError());
323     para.HashAlgorithm.pszObjId = oid_rsa_md5;
324     /* With a valid hash algorithm, this succeeds, even though fDetached is
325      * FALSE.
326      */
327     SetLastError(0xdeadbeef);
328     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
329      &hashedBlobSize, NULL, NULL);
330     todo_wine
331     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
332     if (ret)
333     {
334         /* Actually attempting to get the hashed data fails, perhaps because
335          * detached is FALSE.
336          */
337         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
338         SetLastError(0xdeadbeef);
339         ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, hashedBlob,
340          &hashedBlobSize, NULL, NULL);
341         ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
342          "expected CRYPT_E_MSG_ERROR, got 0x%08x (%d)\n", GetLastError(),
343          GetLastError());
344         HeapFree(GetProcessHeap(), 0, hashedBlob);
345     }
346     /* Repeating tests with fDetached = TRUE results in success */
347     SetLastError(0xdeadbeef);
348     ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
349      &hashedBlobSize, NULL, NULL);
350     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
351     if (ret)
352     {
353         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
354         SetLastError(0xdeadbeef);
355         ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, hashedBlob,
356          &hashedBlobSize, NULL, NULL);
357         ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
358         ok(hashedBlobSize == sizeof(detachedHashBlob),
359          "unexpected size of detached blob %d\n", hashedBlobSize);
360         ok(!memcmp(hashedBlob, detachedHashBlob, hashedBlobSize),
361          "unexpected detached blob value\n");
362         HeapFree(GetProcessHeap(), 0, hashedBlob);
363     }
364     /* Hashing a single item with fDetached = FALSE also succeeds */
365     SetLastError(0xdeadbeef);
366     ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, NULL,
367      &hashedBlobSize, NULL, NULL);
368     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
369     if (ret)
370     {
371         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
372         ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, hashedBlob,
373          &hashedBlobSize, NULL, NULL);
374         ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
375         ok(hashedBlobSize == sizeof(hashBlob),
376          "unexpected size of detached blob %d\n", hashedBlobSize);
377         ok(!memcmp(hashedBlob, hashBlob, hashedBlobSize),
378          "unexpected detached blob value\n");
379         HeapFree(GetProcessHeap(), 0, hashedBlob);
380     }
381     /* Check the computed hash value too.  You don't need to get the encoded
382      * blob to get it.
383      */
384     computedHashSize = 0xdeadbeef;
385     ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
386      &hashedBlobSize, NULL, &computedHashSize);
387     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
388     ok(computedHashSize == 16, "expected hash size of 16, got %d\n",
389      computedHashSize);
390     if (ret)
391     {
392         computedHash = HeapAlloc(GetProcessHeap(), 0, computedHashSize);
393         SetLastError(0xdeadbeef);
394         ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
395          &hashedBlobSize, computedHash, &computedHashSize);
396         ok(computedHashSize == sizeof(hashVal),
397          "unexpected size of hash value %d\n", computedHashSize);
398         ok(!memcmp(computedHash, hashVal, computedHashSize),
399          "unexpected value\n");
400         HeapFree(GetProcessHeap(), 0, computedHash);
401     }
402 }
403
404 START_TEST(message)
405 {
406     test_msg_get_signer_count();
407     test_verify_message_signature();
408     test_hash_message();
409 }