crypt32: Simplify hash value tests.
[wine/wine-kai.git] / dlls / crypt32 / tests / msg.c
blob8874d8ec26faf41967b9a61333ad7242a735d583
1 /*
2 * Unit test suite for crypt32.dll's CryptMsg functions
4 * Copyright 2007 Juan Lang
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.
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.
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
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winerror.h>
26 #include <wincrypt.h>
28 #include "wine/test.h"
30 static void test_msg_open_to_encode(void)
32 HCRYPTMSG msg;
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);
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());
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());
75 static void test_msg_open_to_decode(void)
77 HCRYPTMSG msg;
78 CMSG_STREAM_INFO streamInfo = { 0 };
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());
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());
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);
129 /* And even though the stream info parameter "must be set to NULL" for
130 * CMSG_HASHED, it's still accepted.
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);
138 static void test_msg_get_param(void)
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 };
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);
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);
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++)
176 size = 0;
177 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
178 ok(!ret, "Parameter %d: expected failure\n", i);
180 CryptMsgClose(msg);
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++)
191 size = 0;
192 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
193 ok(!ret, "Parameter %d: expected failure\n", i);
195 CryptMsgClose(msg);
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++)
206 size = 0;
207 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
208 ok(!ret, "Parameter %d: expected failure\n", i);
210 CryptMsgClose(msg);
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++)
221 size = 0;
222 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
223 ok(!ret, "Parameter %d: expected failure\n", i);
225 CryptMsgClose(msg);
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);
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);
246 static void test_msg_close(void)
248 BOOL ret;
249 HCRYPTMSG msg;
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());
264 static void check_param(LPCSTR test, HCRYPTMSG msg, DWORD param,
265 const BYTE *expected, DWORD expectedSize)
267 DWORD size;
268 LPBYTE buf;
269 BOOL ret;
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);
284 static void test_data_msg_open(void)
286 HCRYPTMSG msg;
287 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
288 CMSG_STREAM_INFO streamInfo = { 0 };
289 char oid[] = "1.2.3";
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);
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);
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.
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);
327 static const BYTE msgData[] = { 1, 2, 3, 4 };
329 static BOOL WINAPI nop_stream_output(const void *pvArg, BYTE *pb, DWORD cb,
330 BOOL final)
332 return TRUE;
335 static void test_data_msg_update(void)
337 HCRYPTMSG msg;
338 BOOL ret;
339 CMSG_STREAM_INFO streamInfo = { 0 };
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);
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.
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);
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);
388 /* Calling update after opening with an empty stream info (with a bogus
389 * output function) yields an error:
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.
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);
411 static void test_data_msg_get_param(void)
413 HCRYPTMSG msg;
414 DWORD size;
415 BOOL ret;
416 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
418 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
419 NULL);
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.
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);
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);
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 };
468 struct update_accum
470 DWORD cUpdates;
471 CRYPT_DATA_BLOB *updates;
474 static BOOL WINAPI accumulating_stream_output(const void *pvArg, BYTE *pb,
475 DWORD cb, BOOL final)
477 struct update_accum *accum = (struct update_accum *)pvArg;
478 BOOL ret = FALSE;
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)
487 CRYPT_DATA_BLOB *blob = &accum->updates[accum->cUpdates];
489 blob->pbData = CryptMemAlloc(cb);
490 if (blob->pbData)
492 memcpy(blob->pbData, pb, cb);
493 blob->cbData = cb;
494 ret = TRUE;
496 accum->cUpdates++;
498 return ret;
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 },
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 },
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 },
532 static const struct update_accum a3 = { sizeof(b3) / sizeof(b3[0]), b3 };
534 static void check_updates(LPCSTR header, const struct update_accum *expected,
535 const struct update_accum *got)
537 DWORD i;
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++)
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);
556 /* Frees the updates stored in accum */
557 static void free_updates(struct update_accum *accum)
559 DWORD i;
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;
568 static void test_data_msg_encoding(void)
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 };
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.)
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);
648 static void test_data_msg(void)
650 test_data_msg_open();
651 test_data_msg_update();
652 test_data_msg_get_param();
653 test_data_msg_encoding();
656 static void test_hash_msg_open(void)
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 };
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);
689 static void test_hash_msg_update(void)
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 };
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..
703 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
704 todo_wine
705 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
706 /* including non-final updates with no data.. */
707 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
708 todo_wine
709 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
710 /* and final updates with no data. */
711 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
712 todo_wine
713 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
714 /* But no updates are allowed after the final update. */
715 SetLastError(0xdeadbeef);
716 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
717 todo_wine
718 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
719 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
720 SetLastError(0xdeadbeef);
721 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
722 todo_wine
723 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
724 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
725 CryptMsgClose(msg);
726 /* Non-detached messages, in contrast, don't allow non-final updates in
727 * non-streaming mode.
729 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
730 NULL, NULL);
731 SetLastError(0xdeadbeef);
732 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
733 todo_wine
734 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
735 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
736 /* Final updates (including empty ones) are allowed. */
737 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
738 todo_wine
739 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
740 CryptMsgClose(msg);
741 /* And, of course, streaming mode allows non-final updates */
742 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
743 NULL, &streamInfo);
744 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
745 todo_wine
746 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
747 CryptMsgClose(msg);
750 static const BYTE emptyHashParam[] = {
751 0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,
752 0x7e };
754 static void test_hash_msg_get_param(void)
756 HCRYPTMSG msg;
757 BOOL ret;
758 static char oid_rsa_md5[] = szOID_RSA_MD5;
759 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
760 { oid_rsa_md5, { 0, NULL } }, NULL };
761 DWORD size, value;
762 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
763 BYTE buf[16];
765 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
766 NULL, NULL);
767 /* Content and bare content are always gettable for non-streamed messages */
768 size = 0;
769 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
770 todo_wine {
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());
776 /* The hash is also available. */
777 size = 0;
778 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
779 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
780 ok(size == sizeof(buf), "Unexpected size %d\n", size);
781 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
782 if (size == sizeof(buf))
783 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
784 /* By getting the hash, further updates are not allowed */
785 SetLastError(0xdeadbeef);
786 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
787 todo_wine
788 ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
789 "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
790 /* The version is also available, and should be zero for this message. */
791 size = 0;
792 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
793 todo_wine
794 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
795 size = sizeof(value);
796 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, (LPBYTE)&value, &size);
797 todo_wine {
798 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
799 ok(value == 0, "Expected version 0, got %d\n", value);
801 /* As usual, the type isn't available. */
802 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
803 todo_wine
804 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
805 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
806 CryptMsgClose(msg);
808 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
809 NULL, &streamInfo);
810 /* Streamed messages don't allow you to get the content or bare content. */
811 SetLastError(0xdeadbeef);
812 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
813 todo_wine {
814 ok(!ret && GetLastError() == E_INVALIDARG,
815 "Expected E_INVALIDARG, got %x\n", GetLastError());
816 SetLastError(0xdeadbeef);
817 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
818 ok(!ret && GetLastError() == E_INVALIDARG,
819 "Expected E_INVALIDARG, got %x\n", GetLastError());
821 /* The hash is still available. */
822 size = 0;
823 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
824 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
825 ok(size == sizeof(buf), "Unexpected size %d\n", size);
826 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
827 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
828 if (size == sizeof(buf))
829 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
830 CryptMsgClose(msg);
833 static void test_hash_msg(void)
835 test_hash_msg_open();
836 test_hash_msg_update();
837 test_hash_msg_get_param();
840 static CRYPT_DATA_BLOB b4 = { 0, NULL };
841 static const struct update_accum a4 = { 1, &b4 };
843 static const BYTE bogusOIDContent[] = {
844 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
845 0x04,0x00 };
847 static void test_decode_msg_update(void)
849 HCRYPTMSG msg;
850 BOOL ret;
851 CMSG_STREAM_INFO streamInfo = { 0 };
852 DWORD i;
853 struct update_accum accum = { 0, NULL };
855 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
856 /* Update with a full message in a final update */
857 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
858 todo_wine
859 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
860 /* Can't update after a final update */
861 SetLastError(0xdeadbeef);
862 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
863 todo_wine
864 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
865 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
866 CryptMsgClose(msg);
868 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
869 /* Can't send a non-final update without streaming */
870 SetLastError(0xdeadbeef);
871 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
872 FALSE);
873 todo_wine
874 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
875 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
876 /* A subsequent final update succeeds */
877 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
878 todo_wine
879 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
880 CryptMsgClose(msg);
882 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
883 /* Updating a message that has a NULL stream callback fails */
884 SetLastError(0xdeadbeef);
885 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
886 FALSE);
887 todo_wine
888 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
889 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
890 /* Changing the callback pointer after the fact yields the same error (so
891 * the message must copy the stream info, not just store a pointer to it)
893 streamInfo.pfnStreamOutput = nop_stream_output;
894 SetLastError(0xdeadbeef);
895 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
896 FALSE);
897 todo_wine
898 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
899 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
900 CryptMsgClose(msg);
902 /* Empty non-final updates are allowed when streaming.. */
903 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
904 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
905 todo_wine
906 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
907 /* but final updates aren't when not enough data has been received. */
908 SetLastError(0xdeadbeef);
909 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
910 todo_wine
911 ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
912 "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
913 CryptMsgClose(msg);
915 /* Updating the message byte by byte is legal */
916 streamInfo.pfnStreamOutput = accumulating_stream_output;
917 streamInfo.pvArg = &accum;
918 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
919 for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
920 ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
921 todo_wine {
922 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
923 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
924 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
926 CryptMsgClose(msg);
927 todo_wine
928 check_updates("byte-by-byte empty content", &a4, &accum);
929 free_updates(&accum);
931 /* Decoding bogus content fails in non-streaming mode.. */
932 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
933 SetLastError(0xdeadbeef);
934 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
935 todo_wine
936 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
937 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
938 CryptMsgClose(msg);
939 /* and as the final update in streaming mode.. */
940 streamInfo.pfnStreamOutput = nop_stream_output;
941 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
942 SetLastError(0xdeadbeef);
943 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
944 todo_wine
945 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
946 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
947 CryptMsgClose(msg);
948 /* and even as a non-final update in streaming mode. */
949 streamInfo.pfnStreamOutput = nop_stream_output;
950 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
951 SetLastError(0xdeadbeef);
952 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
953 todo_wine
954 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
955 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
956 CryptMsgClose(msg);
958 /* An empty message can be opened with indetermined type.. */
959 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
960 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
961 TRUE);
962 todo_wine
963 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
964 /* but decoding it as an explicitly typed message fails. */
965 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
966 NULL);
967 SetLastError(0xdeadbeef);
968 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
969 TRUE);
970 todo_wine
971 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
972 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
973 CryptMsgClose(msg);
974 /* On the other hand, decoding the bare content of an empty message fails
975 * with unspecified type..
977 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
978 SetLastError(0xdeadbeef);
979 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
980 sizeof(dataEmptyBareContent), TRUE);
981 todo_wine
982 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
983 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
984 CryptMsgClose(msg);
985 /* but succeeds with explicit type. */
986 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
987 NULL);
988 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
989 sizeof(dataEmptyBareContent), TRUE);
990 todo_wine
991 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
992 CryptMsgClose(msg);
994 /* Decoding valid content with an unsupported OID fails */
995 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
996 SetLastError(0xdeadbeef);
997 ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
998 todo_wine
999 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1000 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1001 CryptMsgClose(msg);
1004 static void test_decode_msg(void)
1006 test_decode_msg_update();
1009 START_TEST(msg)
1011 /* Basic parameter checking tests */
1012 test_msg_open_to_encode();
1013 test_msg_open_to_decode();
1014 test_msg_get_param();
1015 test_msg_close();
1017 /* Message-type specific tests */
1018 test_data_msg();
1019 test_hash_msg();
1020 test_decode_msg();