crypt32: Change finalized from a boolean to a state and use it to simplify message...
[wine] / dlls / crypt32 / tests / msg.c
1 /*
2  * Unit test suite for crypt32.dll's CryptMsg functions
3  *
4  * Copyright 2007 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 void test_msg_open_to_encode(void)
31 {
32     HCRYPTMSG msg;
33
34     /* Crash
35     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, NULL,
36      NULL, NULL);
37     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, NULL, NULL,
38      NULL);
39     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, NULL, NULL,
40      NULL);
41      */
42
43     /* Bad encodings */
44     SetLastError(0xdeadbeef);
45     msg = CryptMsgOpenToEncode(0, 0, 0, NULL, NULL, NULL);
46     ok(!msg && GetLastError() == E_INVALIDARG,
47      "Expected E_INVALIDARG, got %x\n", GetLastError());
48     SetLastError(0xdeadbeef);
49     msg = CryptMsgOpenToEncode(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
50     ok(!msg && GetLastError() == E_INVALIDARG,
51      "Expected E_INVALIDARG, got %x\n", GetLastError());
52
53     /* Bad message types */
54     SetLastError(0xdeadbeef);
55     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
56     ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
57      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
58     SetLastError(0xdeadbeef);
59     msg = CryptMsgOpenToEncode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0,
60      NULL, NULL, NULL);
61     ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
62      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
63     SetLastError(0xdeadbeef);
64     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0,
65      CMSG_SIGNED_AND_ENVELOPED, NULL, NULL, NULL);
66     ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
67      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
68     SetLastError(0xdeadbeef);
69     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, NULL,
70      NULL, NULL);
71     ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
72      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
73 }
74
75 static void test_msg_open_to_decode(void)
76 {
77     HCRYPTMSG msg;
78     CMSG_STREAM_INFO streamInfo = { 0 };
79
80     SetLastError(0xdeadbeef);
81     msg = CryptMsgOpenToDecode(0, 0, 0, 0, NULL, NULL);
82     ok(!msg && GetLastError() == E_INVALIDARG,
83      "Expected E_INVALIDARG, got %x\n", GetLastError());
84
85     /* Bad encodings */
86     SetLastError(0xdeadbeef);
87     msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, 0, 0, NULL, NULL);
88     ok(!msg && GetLastError() == E_INVALIDARG,
89      "Expected E_INVALIDARG, got %x\n", GetLastError());
90     SetLastError(0xdeadbeef);
91     msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, CMSG_DATA, 0, NULL, NULL);
92     ok(!msg && GetLastError() == E_INVALIDARG,
93      "Expected E_INVALIDARG, got %x\n", GetLastError());
94
95     /* The message type can be explicit... */
96     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
97      NULL);
98     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
99     CryptMsgClose(msg);
100     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
101      NULL);
102     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
103     CryptMsgClose(msg);
104     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
105      NULL);
106     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
107     CryptMsgClose(msg);
108     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
109      NULL);
110     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
111     CryptMsgClose(msg);
112     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0,
113      CMSG_SIGNED_AND_ENVELOPED, 0, NULL, NULL);
114     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
115     CryptMsgClose(msg);
116     /* or implicit.. */
117     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
118     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
119     CryptMsgClose(msg);
120     /* or even invalid. */
121     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
122      NULL);
123     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
124     CryptMsgClose(msg);
125     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
126     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
127     CryptMsgClose(msg);
128
129     /* And even though the stream info parameter "must be set to NULL" for
130      * CMSG_HASHED, it's still accepted.
131      */
132     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
133      &streamInfo);
134     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
135     CryptMsgClose(msg);
136 }
137
138 static void test_msg_get_param(void)
139 {
140     BOOL ret;
141     HCRYPTMSG msg;
142     DWORD size, i, value;
143     CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
144     CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
145
146     /* Crash
147     ret = CryptMsgGetParam(NULL, 0, 0, NULL, NULL);
148     ret = CryptMsgGetParam(NULL, 0, 0, NULL, &size);
149     ret = CryptMsgGetParam(msg, 0, 0, NULL, NULL);
150      */
151
152     /* Decoded messages */
153     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
154     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
155     /* For decoded messages, the type is always available */
156     size = 0;
157     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
158     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
159     size = sizeof(value);
160     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
161     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
162     /* For this (empty) message, the type isn't set */
163     ok(value == 0, "Expected type 0, got %d\n", value);
164     CryptMsgClose(msg);
165
166     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
167      NULL);
168     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
169     /* For explicitly typed messages, the type is known. */
170     size = sizeof(value);
171     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
172     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
173     ok(value == CMSG_DATA, "Expected CMSG_DATA, got %d\n", value);
174     for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
175     {
176         size = 0;
177         ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
178         ok(!ret, "Parameter %d: expected failure\n", i);
179     }
180     CryptMsgClose(msg);
181
182     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
183      NULL);
184     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
185     size = sizeof(value);
186     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
187     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
188     ok(value == CMSG_ENVELOPED, "Expected CMSG_ENVELOPED, got %d\n", value);
189     for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
190     {
191         size = 0;
192         ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
193         ok(!ret, "Parameter %d: expected failure\n", i);
194     }
195     CryptMsgClose(msg);
196
197     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
198      NULL);
199     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
200     size = sizeof(value);
201     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
202     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
203     ok(value == CMSG_HASHED, "Expected CMSG_HASHED, got %d\n", value);
204     for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
205     {
206         size = 0;
207         ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
208         ok(!ret, "Parameter %d: expected failure\n", i);
209     }
210     CryptMsgClose(msg);
211
212     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
213      NULL);
214     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
215     size = sizeof(value);
216     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
217     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
218     ok(value == CMSG_SIGNED, "Expected CMSG_SIGNED, got %d\n", value);
219     for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
220     {
221         size = 0;
222         ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
223         ok(!ret, "Parameter %d: expected failure\n", i);
224     }
225     CryptMsgClose(msg);
226
227     /* Explicitly typed messages get their types set, even if they're invalid */
228     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
229      NULL);
230     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
231     size = sizeof(value);
232     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
233     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
234     ok(value == CMSG_ENCRYPTED, "Expected CMSG_ENCRYPTED, got %d\n", value);
235     CryptMsgClose(msg);
236
237     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
238     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
239     size = sizeof(value);
240     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
241     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
242     ok(value == 1000, "Expected 1000, got %d\n", value);
243     CryptMsgClose(msg);
244 }
245
246 static void test_msg_close(void)
247 {
248     BOOL ret;
249     HCRYPTMSG msg;
250
251     /* NULL succeeds.. */
252     ret = CryptMsgClose(NULL);
253     ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
254     /* but an arbitrary pointer crashes. */
255     if (0)
256         ret = CryptMsgClose((HCRYPTMSG)1);
257     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
258      NULL);
259     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
260     ret = CryptMsgClose(msg);
261     ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
262 }
263
264 static void check_param(LPCSTR test, HCRYPTMSG msg, DWORD param,
265  const BYTE *expected, DWORD expectedSize)
266 {
267     DWORD size;
268     LPBYTE buf;
269     BOOL ret;
270
271     size = 0;
272     ret = CryptMsgGetParam(msg, param, 0, NULL, &size);
273     ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
274     buf = HeapAlloc(GetProcessHeap(), 0, size);
275     ret = CryptMsgGetParam(msg, param, 0, buf, &size);
276     ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
277     ok(size == expectedSize, "%s: expected size %d, got %d\n", test,
278      expectedSize, size);
279     if (size)
280         ok(!memcmp(buf, expected, size), "%s: unexpected data\n", test);
281     HeapFree(GetProcessHeap(), 0, buf);
282 }
283
284 static void test_data_msg_open(void)
285 {
286     HCRYPTMSG msg;
287     CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
288     CMSG_STREAM_INFO streamInfo = { 0 };
289     char oid[] = "1.2.3";
290
291     /* The data message type takes no additional info */
292     SetLastError(0xdeadbeef);
293     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, &hashInfo,
294      NULL, NULL);
295     ok(!msg && GetLastError() == E_INVALIDARG,
296      "Expected E_INVALIDARG, got %x\n", GetLastError());
297     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
298      NULL);
299     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
300     CryptMsgClose(msg);
301
302     /* An empty stream info is allowed. */
303     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
304      &streamInfo);
305     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
306     CryptMsgClose(msg);
307
308     /* Passing a bogus inner OID succeeds for a non-streamed message.. */
309     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
310      NULL);
311     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
312     CryptMsgClose(msg);
313     /* and still succeeds when CMSG_DETACHED_FLAG is passed.. */
314     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
315      CMSG_DATA, NULL, oid, NULL);
316     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
317     CryptMsgClose(msg);
318     /* and when a stream info is given, even though you're not supposed to be
319      * able to use anything but szOID_RSA_data when streaming is being used.
320      */
321     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
322      CMSG_DATA, NULL, oid, &streamInfo);
323     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
324     CryptMsgClose(msg);
325 }
326
327 static const BYTE msgData[] = { 1, 2, 3, 4 };
328
329 static BOOL WINAPI nop_stream_output(const void *pvArg, BYTE *pb, DWORD cb,
330  BOOL final)
331 {
332     return TRUE;
333 }
334
335 static void test_data_msg_update(void)
336 {
337     HCRYPTMSG msg;
338     BOOL ret;
339     CMSG_STREAM_INFO streamInfo = { 0 };
340
341     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
342      NULL);
343     /* Can't update a message that wasn't opened detached with final = FALSE */
344     SetLastError(0xdeadbeef);
345     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
346     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
347      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
348     /* Updating it with final = TRUE succeeds */
349     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
350     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
351     /* Any subsequent update will fail, as the last was final */
352     SetLastError(0xdeadbeef);
353     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
354     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
355      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
356     CryptMsgClose(msg);
357
358     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
359      NULL);
360     /* Can't update a message with no data */
361     SetLastError(0xdeadbeef);
362     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
363     ok(!ret && GetLastError() == E_INVALIDARG,
364      "Expected E_INVALIDARG, got %x\n", GetLastError());
365     /* Curiously, a valid update will now fail as well, presumably because of
366      * the last (invalid, but final) update.
367      */
368     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
369     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
370      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
371     CryptMsgClose(msg);
372
373     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
374      CMSG_DATA, NULL, NULL, NULL);
375     /* Doesn't appear to be able to update CMSG-DATA with non-final updates */
376     SetLastError(0xdeadbeef);
377     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
378     ok(!ret && GetLastError() == E_INVALIDARG,
379      "Expected E_INVALIDARG, got %x\n", GetLastError());
380     SetLastError(0xdeadbeef);
381     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
382     ok(!ret && GetLastError() == E_INVALIDARG,
383      "Expected E_INVALIDARG, got %x\n", GetLastError());
384     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
385     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
386     CryptMsgClose(msg);
387
388     /* Calling update after opening with an empty stream info (with a bogus
389      * output function) yields an error:
390      */
391     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
392      &streamInfo);
393     SetLastError(0xdeadbeef);
394     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
395     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
396      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
397     CryptMsgClose(msg);
398     /* Calling update with a valid output function succeeds, even if the data
399      * exceeds the size specified in the stream info.
400      */
401     streamInfo.pfnStreamOutput = nop_stream_output;
402     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
403      &streamInfo);
404     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
405     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
406     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
407     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
408     CryptMsgClose(msg);
409 }
410
411 static void test_data_msg_get_param(void)
412 {
413     HCRYPTMSG msg;
414     DWORD size;
415     BOOL ret;
416     CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
417
418     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
419      NULL);
420
421     /* Content and bare content are always gettable when not streaming */
422     size = 0;
423     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
424     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
425     size = 0;
426     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
427     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
428     /* But for this type of message, the signer and hash aren't applicable,
429      * and the type isn't available.
430      */
431     size = 0;
432     SetLastError(0xdeadbeef);
433     ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
434     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
435      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
436     SetLastError(0xdeadbeef);
437     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
438     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
439      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
440     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
441     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
442      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
443     CryptMsgClose(msg);
444
445     /* Can't get content or bare content when streaming */
446     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
447      NULL, &streamInfo);
448     SetLastError(0xdeadbeef);
449     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
450     ok(!ret && GetLastError() == E_INVALIDARG,
451      "Expected E_INVALIDARG, got %x\n", GetLastError());
452     SetLastError(0xdeadbeef);
453     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
454     ok(!ret && GetLastError() == E_INVALIDARG,
455      "Expected E_INVALIDARG, got %x\n", GetLastError());
456     CryptMsgClose(msg);
457 }
458
459 static const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
460 static const BYTE dataEmptyContent[] = {
461 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
462 0x04,0x00 };
463 static const BYTE dataBareContent[] = { 0x04,0x04,0x01,0x02,0x03,0x04 };
464 static const BYTE dataContent[] = {
465 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,
466 0x04,0x04,0x01,0x02,0x03,0x04 };
467
468 struct update_accum
469 {
470     DWORD cUpdates;
471     CRYPT_DATA_BLOB *updates;
472 };
473
474 static BOOL WINAPI accumulating_stream_output(const void *pvArg, BYTE *pb,
475  DWORD cb, BOOL final)
476 {
477     struct update_accum *accum = (struct update_accum *)pvArg;
478     BOOL ret = FALSE;
479
480     if (accum->cUpdates)
481         accum->updates = CryptMemRealloc(accum->updates,
482          (accum->cUpdates + 1) * sizeof(CRYPT_DATA_BLOB));
483     else
484         accum->updates = CryptMemAlloc(sizeof(CRYPT_DATA_BLOB));
485     if (accum->updates)
486     {
487         CRYPT_DATA_BLOB *blob = &accum->updates[accum->cUpdates];
488
489         blob->pbData = CryptMemAlloc(cb);
490         if (blob->pbData)
491         {
492             memcpy(blob->pbData, pb, cb);
493             blob->cbData = cb;
494             ret = TRUE;
495         }
496         accum->cUpdates++;
497     }
498     return ret;
499 }
500
501 /* The updates of a (bogus) definite-length encoded message */
502 static BYTE u1[] = { 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
503  0x07,0x01,0xa0,0x02,0x04,0x00 };
504 static BYTE u2[] = { 0x01,0x02,0x03,0x04 };
505 static CRYPT_DATA_BLOB b1[] = {
506     { sizeof(u1), u1 },
507     { sizeof(u2), u2 },
508     { sizeof(u2), u2 },
509 };
510 static const struct update_accum a1 = { sizeof(b1) / sizeof(b1[0]), b1 };
511 /* The updates of a definite-length encoded message */
512 static BYTE u3[] = { 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
513  0x07,0x01,0xa0,0x06,0x04,0x04 };
514 static CRYPT_DATA_BLOB b2[] = {
515     { sizeof(u3), u3 },
516     { sizeof(u2), u2 },
517 };
518 static const struct update_accum a2 = { sizeof(b2) / sizeof(b2[0]), b2 };
519 /* The updates of an indefinite-length encoded message */
520 static BYTE u4[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
521  0x07,0x01,0xa0,0x80,0x24,0x80 };
522 static BYTE u5[] = { 0x04,0x04 };
523 static BYTE u6[] = { 0x00,0x00,0x00,0x00,0x00,0x00 };
524 static CRYPT_DATA_BLOB b3[] = {
525     { sizeof(u4), u4 },
526     { sizeof(u5), u5 },
527     { sizeof(u2), u2 },
528     { sizeof(u5), u5 },
529     { sizeof(u2), u2 },
530     { sizeof(u6), u6 },
531 };
532 static const struct update_accum a3 = { sizeof(b3) / sizeof(b3[0]), b3 };
533
534 static void check_updates(LPCSTR header, const struct update_accum *expected,
535  const struct update_accum *got)
536 {
537     DWORD i;
538
539     ok(expected->cUpdates == got->cUpdates,
540      "%s: expected %d updates, got %d\n", header, expected->cUpdates,
541      got->cUpdates);
542     if (expected->cUpdates == got->cUpdates)
543         for (i = 0; i < min(expected->cUpdates, got->cUpdates); i++)
544         {
545             ok(expected->updates[i].cbData == got->updates[i].cbData,
546              "%s, update %d: expected %d bytes, got %d\n", header, i,
547              expected->updates[i].cbData, got->updates[i].cbData);
548             if (expected->updates[i].cbData && expected->updates[i].cbData ==
549              got->updates[i].cbData)
550                 ok(!memcmp(expected->updates[i].pbData, got->updates[i].pbData,
551                  got->updates[i].cbData), "%s, update %d: unexpected value\n",
552                  header, i);
553         }
554 }
555
556 /* Frees the updates stored in accum */
557 static void free_updates(struct update_accum *accum)
558 {
559     DWORD i;
560
561     for (i = 0; i < accum->cUpdates; i++)
562         CryptMemFree(accum->updates[i].pbData);
563     CryptMemFree(accum->updates);
564     accum->updates = NULL;
565     accum->cUpdates = 0;
566 }
567
568 static void test_data_msg_encoding(void)
569 {
570     HCRYPTMSG msg;
571     BOOL ret;
572     static char oid[] = "1.2.3";
573     struct update_accum accum = { 0, NULL };
574     CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
575
576     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
577      NULL);
578     check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
579      dataEmptyBareContent, sizeof(dataEmptyBareContent));
580     check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
581      sizeof(dataEmptyContent));
582     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
583     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
584     check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
585      dataBareContent, sizeof(dataBareContent));
586     check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
587      sizeof(dataContent));
588     CryptMsgClose(msg);
589     /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
590     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
591      CMSG_DATA, NULL, NULL, NULL);
592     check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
593      dataEmptyBareContent, sizeof(dataEmptyBareContent));
594     check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
595      sizeof(dataEmptyContent));
596     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
597     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
598     check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
599      dataBareContent, sizeof(dataBareContent));
600     check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
601      sizeof(dataContent));
602     CryptMsgClose(msg);
603     /* The inner OID is apparently ignored */
604     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
605      NULL);
606     check_param("data bogus oid bare content", msg, CMSG_BARE_CONTENT_PARAM,
607      dataEmptyBareContent, sizeof(dataEmptyBareContent));
608     check_param("data bogus oid content", msg, CMSG_CONTENT_PARAM,
609      dataEmptyContent, sizeof(dataEmptyContent));
610     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
611     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
612     check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
613      dataBareContent, sizeof(dataBareContent));
614     check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
615      sizeof(dataContent));
616     CryptMsgClose(msg);
617     /* A streaming message is DER encoded if the length is not 0xffffffff, but
618      * curiously, updates aren't validated to make sure they don't exceed the
619      * stated length.  (The resulting output will of course fail to decode.)
620      */
621     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
622      NULL, &streamInfo);
623     CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
624     CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
625     CryptMsgClose(msg);
626     check_updates("bogus data message with definite length", &a1, &accum);
627     free_updates(&accum);
628     /* A valid definite-length encoding: */
629     streamInfo.cbContent = sizeof(msgData);
630     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
631      NULL, &streamInfo);
632     CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
633     CryptMsgClose(msg);
634     check_updates("data message with definite length", &a2, &accum);
635     free_updates(&accum);
636     /* An indefinite-length encoding: */
637     streamInfo.cbContent = 0xffffffff;
638     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
639      NULL, &streamInfo);
640     CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
641     CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
642     CryptMsgClose(msg);
643     todo_wine
644     check_updates("data message with indefinite length", &a3, &accum);
645     free_updates(&accum);
646 }
647
648 static void test_data_msg(void)
649 {
650     test_data_msg_open();
651     test_data_msg_update();
652     test_data_msg_get_param();
653     test_data_msg_encoding();
654 }
655
656 static void test_hash_msg_open(void)
657 {
658     HCRYPTMSG msg;
659     CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
660     static char oid_rsa_md5[] = szOID_RSA_MD5;
661     CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
662
663     SetLastError(0xdeadbeef);
664     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
665      NULL, NULL);
666     ok(!msg && GetLastError() == E_INVALIDARG,
667      "Expected E_INVALIDARG, got %x\n", GetLastError());
668     hashInfo.cbSize = sizeof(hashInfo);
669     SetLastError(0xdeadbeef);
670     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
671      NULL, NULL);
672     ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
673      "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
674     hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
675     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
676      NULL, NULL);
677     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
678     CryptMsgClose(msg);
679     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
680      CMSG_HASHED, &hashInfo, NULL, NULL);
681     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
682     CryptMsgClose(msg);
683     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
684      CMSG_HASHED, &hashInfo, NULL, &streamInfo);
685     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
686     CryptMsgClose(msg);
687 }
688
689 static void test_hash_msg_update(void)
690 {
691     HCRYPTMSG msg;
692     BOOL ret;
693     static char oid_rsa_md5[] = szOID_RSA_MD5;
694     CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
695      { oid_rsa_md5, { 0, NULL } }, NULL };
696     CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
697
698     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
699      CMSG_HASHED, &hashInfo, NULL, NULL);
700     /* Detached hashed messages opened in non-streaming mode allow non-final
701      * updates..
702      */
703     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
704     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
705     /* including non-final updates with no data.. */
706     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
707     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
708     /* and final updates with no data. */
709     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
710     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
711     /* But no updates are allowed after the final update. */
712     SetLastError(0xdeadbeef);
713     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
714     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
715      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
716     SetLastError(0xdeadbeef);
717     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
718     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
719      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
720     CryptMsgClose(msg);
721     /* Non-detached messages, in contrast, don't allow non-final updates in
722      * non-streaming mode.
723      */
724     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
725      NULL, NULL);
726     SetLastError(0xdeadbeef);
727     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
728     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
729      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
730     /* Final updates (including empty ones) are allowed. */
731     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
732     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
733     CryptMsgClose(msg);
734     /* And, of course, streaming mode allows non-final updates */
735     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
736      NULL, &streamInfo);
737     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
738     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
739     CryptMsgClose(msg);
740     /* Setting pfnStreamOutput to NULL results in no error.  (In what appears
741      * to be a bug, it isn't actually used - see encoding tests.)
742      */
743     streamInfo.pfnStreamOutput = NULL;
744     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
745      NULL, &streamInfo);
746     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
747     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
748     CryptMsgClose(msg);
749 }
750
751 static const BYTE emptyHashParam[] = {
752 0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,
753 0x7e };
754
755 static void test_hash_msg_get_param(void)
756 {
757     HCRYPTMSG msg;
758     BOOL ret;
759     static char oid_rsa_md5[] = szOID_RSA_MD5;
760     CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
761      { oid_rsa_md5, { 0, NULL } }, NULL };
762     DWORD size, value;
763     CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
764     BYTE buf[16];
765
766     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
767      NULL, NULL);
768     /* Content and bare content are always gettable for non-streamed messages */
769     size = 0;
770     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
771     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
772     size = 0;
773     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
774     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
775     /* The hash is also available. */
776     size = 0;
777     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
778     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
779     ok(size == sizeof(buf), "Unexpected size %d\n", size);
780     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
781     if (size == sizeof(buf))
782         ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
783     /* By getting the hash, further updates are not allowed */
784     SetLastError(0xdeadbeef);
785     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
786     ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
787      "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
788     /* The version is also available, and should be zero for this message. */
789     size = 0;
790     ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
791     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
792     size = sizeof(value);
793     ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, (LPBYTE)&value, &size);
794     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
795     ok(value == 0, "Expected version 0, got %d\n", value);
796     /* As usual, the type isn't available. */
797     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
798     ok(!ret, "Expected failure\n");
799     CryptMsgClose(msg);
800
801     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
802      NULL, &streamInfo);
803     /* Streamed messages don't allow you to get the content or bare content. */
804     SetLastError(0xdeadbeef);
805     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
806     ok(!ret && GetLastError() == E_INVALIDARG,
807      "Expected E_INVALIDARG, got %x\n", GetLastError());
808     SetLastError(0xdeadbeef);
809     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
810     ok(!ret && GetLastError() == E_INVALIDARG,
811      "Expected E_INVALIDARG, got %x\n", GetLastError());
812     /* The hash is still available. */
813     size = 0;
814     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
815     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
816     ok(size == sizeof(buf), "Unexpected size %d\n", size);
817     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
818     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
819     if (size == sizeof(buf))
820         ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
821     /* After updating the hash, further updates aren't allowed on streamed
822      * messages either.
823      */
824     SetLastError(0xdeadbeef);
825     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
826     ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
827      "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
828     CryptMsgClose(msg);
829 }
830
831 static const BYTE hashEmptyBareContent[] = {
832 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
833 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
834 static const BYTE hashEmptyContent[] = {
835 0x30,0x26,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x19,
836 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
837 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
838 static const BYTE hashBareContent[] = {
839 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
840 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
841 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
842 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
843 static const BYTE hashContent[] = {
844 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
845 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
846 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
847 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
848 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
849
850 static const BYTE detachedHashNonFinalBareContent[] = {
851 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
852 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
853 0x07,0x01,0x04,0x00 };
854 static const BYTE detachedHashNonFinalContent[] = {
855 0x30,0x2f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x22,
856 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
857 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
858 0x07,0x01,0x04,0x00 };
859 static const BYTE detachedHashBareContent[] = {
860 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
861 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
862 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
863 0x9d,0x2a,0x8f,0x26,0x2f };
864 static const BYTE detachedHashContent[] = {
865 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
866 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
867 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
868 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
869 0x9d,0x2a,0x8f,0x26,0x2f };
870
871 static void test_hash_msg_encoding(void)
872 {
873     HCRYPTMSG msg;
874     CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0 };
875     BOOL ret;
876     struct update_accum accum = { 0, NULL }, empty_accum = { 0, NULL };
877     CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
878     static char oid_rsa_md5[] = szOID_RSA_MD5;
879
880     hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
881     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
882      NULL, NULL);
883     check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
884      hashEmptyBareContent, sizeof(hashEmptyBareContent));
885     check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
886      hashEmptyContent, sizeof(hashEmptyContent));
887     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
888     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
889     check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
890      hashBareContent, sizeof(hashBareContent));
891     check_param("hash content", msg, CMSG_CONTENT_PARAM,
892      hashContent, sizeof(hashContent));
893     CryptMsgClose(msg);
894     /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
895     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
896      CMSG_HASHED, &hashInfo, NULL, NULL);
897     check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
898      hashEmptyBareContent, sizeof(hashEmptyBareContent));
899     check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
900      hashEmptyContent, sizeof(hashEmptyContent));
901     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
902     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
903     check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
904      hashBareContent, sizeof(hashBareContent));
905     check_param("hash content", msg, CMSG_CONTENT_PARAM,
906      hashContent, sizeof(hashContent));
907     CryptMsgClose(msg);
908     /* Same test, but with CMSG_DETACHED_FLAG set */
909     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
910      CMSG_HASHED, &hashInfo, NULL, NULL);
911     check_param("detached hash empty bare content", msg,
912      CMSG_BARE_CONTENT_PARAM, hashEmptyBareContent,
913      sizeof(hashEmptyBareContent));
914     check_param("detached hash empty content", msg, CMSG_CONTENT_PARAM,
915      hashEmptyContent, sizeof(hashEmptyContent));
916     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
917     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
918     check_param("detached hash not final bare content", msg,
919      CMSG_BARE_CONTENT_PARAM, detachedHashNonFinalBareContent,
920      sizeof(detachedHashNonFinalBareContent));
921     check_param("detached hash not final content", msg, CMSG_CONTENT_PARAM,
922      detachedHashNonFinalContent, sizeof(detachedHashNonFinalContent));
923     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
924     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
925     check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
926      detachedHashBareContent, sizeof(detachedHashBareContent));
927     check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
928      detachedHashContent, sizeof(detachedHashContent));
929     check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
930      detachedHashBareContent, sizeof(detachedHashBareContent));
931     check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
932      detachedHashContent, sizeof(detachedHashContent));
933     CryptMsgClose(msg);
934     /* In what appears to be a bug, streamed updates to hash messages don't
935      * call the output function.
936      */
937     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
938      NULL, &streamInfo);
939     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
940     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
941     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
942     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
943     CryptMsgClose(msg);
944     check_updates("empty hash message", &empty_accum, &accum);
945     free_updates(&accum);
946
947     streamInfo.cbContent = sizeof(msgData);
948     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
949      NULL, &streamInfo);
950     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
951     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
952     CryptMsgClose(msg);
953     check_updates("hash message", &empty_accum, &accum);
954     free_updates(&accum);
955
956     streamInfo.cbContent = sizeof(msgData);
957     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
958      CMSG_HASHED, &hashInfo, NULL, &streamInfo);
959     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
960     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
961     CryptMsgClose(msg);
962     check_updates("detached hash message", &empty_accum, &accum);
963     free_updates(&accum);
964 }
965
966 static void test_hash_msg(void)
967 {
968     test_hash_msg_open();
969     test_hash_msg_update();
970     test_hash_msg_get_param();
971     test_hash_msg_encoding();
972 }
973
974 static CRYPT_DATA_BLOB b4 = { 0, NULL };
975 static const struct update_accum a4 = { 1, &b4 };
976
977 static const BYTE bogusOIDContent[] = {
978 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
979 0x04,0x00 };
980
981 static void test_decode_msg_update(void)
982 {
983     HCRYPTMSG msg;
984     BOOL ret;
985     CMSG_STREAM_INFO streamInfo = { 0 };
986     DWORD i;
987     struct update_accum accum = { 0, NULL };
988
989     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
990     /* Update with a full message in a final update */
991     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
992     todo_wine
993     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
994     /* Can't update after a final update */
995     SetLastError(0xdeadbeef);
996     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
997     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
998      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
999     CryptMsgClose(msg);
1000
1001     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1002     /* Can't send a non-final update without streaming */
1003     SetLastError(0xdeadbeef);
1004     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1005      FALSE);
1006     todo_wine
1007     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1008      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1009     /* A subsequent final update succeeds */
1010     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1011     todo_wine
1012     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1013     CryptMsgClose(msg);
1014
1015     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1016     /* Updating a message that has a NULL stream callback fails */
1017     SetLastError(0xdeadbeef);
1018     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1019      FALSE);
1020     todo_wine
1021     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1022      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1023     /* Changing the callback pointer after the fact yields the same error (so
1024      * the message must copy the stream info, not just store a pointer to it)
1025      */
1026     streamInfo.pfnStreamOutput = nop_stream_output;
1027     SetLastError(0xdeadbeef);
1028     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1029      FALSE);
1030     todo_wine
1031     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1032      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1033     CryptMsgClose(msg);
1034
1035     /* Empty non-final updates are allowed when streaming.. */
1036     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1037     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1038     todo_wine
1039     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1040     /* but final updates aren't when not enough data has been received. */
1041     SetLastError(0xdeadbeef);
1042     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1043     todo_wine
1044     ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
1045      "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
1046     CryptMsgClose(msg);
1047
1048     /* Updating the message byte by byte is legal */
1049     streamInfo.pfnStreamOutput = accumulating_stream_output;
1050     streamInfo.pvArg = &accum;
1051     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1052     for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
1053         ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
1054     todo_wine {
1055     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1056     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1057     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1058     }
1059     CryptMsgClose(msg);
1060     todo_wine
1061     check_updates("byte-by-byte empty content", &a4, &accum);
1062     free_updates(&accum);
1063
1064     /* Decoding bogus content fails in non-streaming mode.. */
1065     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1066     SetLastError(0xdeadbeef);
1067     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1068     todo_wine
1069     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1070      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1071     CryptMsgClose(msg);
1072     /* and as the final update in streaming mode.. */
1073     streamInfo.pfnStreamOutput = nop_stream_output;
1074     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1075     SetLastError(0xdeadbeef);
1076     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1077     todo_wine
1078     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1079      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1080     CryptMsgClose(msg);
1081     /* and even as a non-final update in streaming mode. */
1082     streamInfo.pfnStreamOutput = nop_stream_output;
1083     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1084     SetLastError(0xdeadbeef);
1085     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1086     todo_wine
1087     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1088      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1089     CryptMsgClose(msg);
1090
1091     /* An empty message can be opened with indetermined type.. */
1092     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1093     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1094      TRUE);
1095     todo_wine
1096     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1097     /* but decoding it as an explicitly typed message fails. */
1098     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1099      NULL);
1100     SetLastError(0xdeadbeef);
1101     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1102      TRUE);
1103     todo_wine
1104     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1105      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1106     CryptMsgClose(msg);
1107     /* On the other hand, decoding the bare content of an empty message fails
1108      * with unspecified type..
1109      */
1110     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1111     SetLastError(0xdeadbeef);
1112     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1113      sizeof(dataEmptyBareContent), TRUE);
1114     todo_wine
1115     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1116      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1117     CryptMsgClose(msg);
1118     /* but succeeds with explicit type. */
1119     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1120      NULL);
1121     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1122      sizeof(dataEmptyBareContent), TRUE);
1123     todo_wine
1124     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1125     CryptMsgClose(msg);
1126
1127     /* Decoding valid content with an unsupported OID fails */
1128     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1129     SetLastError(0xdeadbeef);
1130     ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
1131     todo_wine
1132     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1133      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1134     CryptMsgClose(msg);
1135 }
1136
1137 static void test_decode_msg(void)
1138 {
1139     test_decode_msg_update();
1140 }
1141
1142 START_TEST(msg)
1143 {
1144     /* Basic parameter checking tests */
1145     test_msg_open_to_encode();
1146     test_msg_open_to_decode();
1147     test_msg_get_param();
1148     test_msg_close();
1149
1150     /* Message-type specific tests */
1151     test_data_msg();
1152     test_hash_msg();
1153     test_decode_msg();
1154 }