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
28 #include "wine/test.h"
30 static void test_msg_open_to_encode(void)
35 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, NULL,
37 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, NULL, NULL,
39 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, NULL, NULL,
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,
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,
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)
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());
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,
98 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
100 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
102 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
104 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
106 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
108 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
110 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
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());
117 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
118 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
120 /* or even invalid. */
121 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
123 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
125 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
126 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
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,
134 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
138 static void test_msg_get_param(void)
142 DWORD size, i, value;
143 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
144 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
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 */
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);
166 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, 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++)
177 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
178 ok(!ret, "Parameter %d: expected failure\n", i);
182 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, 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++)
192 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
193 ok(!ret, "Parameter %d: expected failure\n", i);
197 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, 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++)
207 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
208 ok(!ret, "Parameter %d: expected failure\n", i);
212 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, 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++)
222 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
223 ok(!ret, "Parameter %d: expected failure\n", i);
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,
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);
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);
246 static void test_msg_close(void)
251 /* NULL succeeds.. */
252 ret = CryptMsgClose(NULL);
253 ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
254 /* but an arbitrary pointer crashes. */
256 ret = CryptMsgClose((HCRYPTMSG)1);
257 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, 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)
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,
279 if (size == expectedSize && 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)
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,
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,
299 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
302 /* An empty stream info is allowed. */
303 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
305 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
308 /* Passing a bogus inner OID succeeds for a non-streamed message.. */
309 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
311 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
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());
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());
327 static const BYTE msgData[] = { 1, 2, 3, 4 };
329 static BOOL WINAPI nop_stream_output(const void *pvArg, BYTE *pb, DWORD cb,
335 static void test_data_msg_update(void)
339 CMSG_STREAM_INFO streamInfo = { 0 };
341 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, 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());
358 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, 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());
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());
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,
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());
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,
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());
411 static void test_data_msg_get_param(void)
416 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
418 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
421 /* Content and bare content are always gettable when not streaming */
423 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
424 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
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.
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());
445 /* Can't get content or bare content when streaming */
446 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
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());
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,
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 };
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;
481 accum->updates = CryptMemRealloc(accum->updates,
482 (accum->cUpdates + 1) * sizeof(CRYPT_DATA_BLOB));
484 accum->updates = CryptMemAlloc(sizeof(CRYPT_DATA_BLOB));
487 CRYPT_DATA_BLOB *blob = &accum->updates[accum->cUpdates];
489 blob->pbData = CryptMemAlloc(cb);
492 memcpy(blob->pbData, pb, cb);
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[] = {
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[] = {
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[] = {
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)
539 ok(expected->cUpdates == got->cUpdates,
540 "%s: expected %d updates, got %d\n", header, expected->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",
556 /* Frees the updates stored in accum */
557 static void free_updates(struct update_accum *accum)
561 for (i = 0; i < accum->cUpdates; i++)
562 CryptMemFree(accum->updates[i].pbData);
563 CryptMemFree(accum->updates);
564 accum->updates = NULL;
568 static void test_data_msg_encoding(void)
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,
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));
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));
603 /* The inner OID is apparently ignored */
604 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
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));
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,
623 CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
624 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
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,
632 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
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,
640 CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
641 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
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)
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,
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,
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,
677 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
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());
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());
689 static void test_hash_msg_update(void)
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
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());
721 /* Non-detached messages, in contrast, don't allow non-final updates in
722 * non-streaming mode.
724 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
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());
734 /* And, of course, streaming mode allows non-final updates */
735 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
737 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
738 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
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.)
743 streamInfo.pfnStreamOutput = NULL;
744 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
746 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
747 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
751 static const BYTE emptyHashParam[] = {
752 0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,
755 static void test_hash_msg_get_param(void)
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 };
763 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
766 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
768 /* Content and bare content are always gettable for non-streamed messages */
770 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
771 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
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. */
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. */
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");
801 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
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. */
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
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());
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 };
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 };
871 static void test_hash_msg_encoding(void)
874 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0 };
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;
880 hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
881 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
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));
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));
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));
934 /* In what appears to be a bug, streamed updates to hash messages don't
935 * call the output function.
937 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
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());
944 check_updates("empty hash message", &empty_accum, &accum);
945 free_updates(&accum);
947 streamInfo.cbContent = sizeof(msgData);
948 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
950 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
951 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
953 check_updates("hash message", &empty_accum, &accum);
954 free_updates(&accum);
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());
962 check_updates("detached hash message", &empty_accum, &accum);
963 free_updates(&accum);
966 static void test_hash_msg(void)
968 test_hash_msg_open();
969 test_hash_msg_update();
970 test_hash_msg_get_param();
971 test_hash_msg_encoding();
974 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
976 static BYTE serialNum[] = { 1 };
977 static BYTE encodedCommonName[] = { 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
978 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
980 static void test_signed_msg_open(void)
984 CMSG_SIGNED_ENCODE_INFO signInfo = { 0 };
985 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
986 CERT_INFO certInfo = { 0 };
987 static char oid_rsa_md5[] = szOID_RSA_MD5;
989 SetLastError(0xdeadbeef);
990 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
992 ok(!msg && GetLastError() == E_INVALIDARG,
993 "Expected E_INVALIDARG, got %x\n", GetLastError());
994 signInfo.cbSize = sizeof(signInfo);
995 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
997 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1000 signInfo.cSigners = 1;
1001 signInfo.rgSigners = &signer;
1002 /* With signer.pCertInfo unset, attempting to open this message this
1005 signer.pCertInfo = &certInfo;
1006 /* The cert info must contain a serial number and an issuer. */
1007 SetLastError(0xdeadbeef);
1008 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1010 ok(!msg && GetLastError() == E_INVALIDARG,
1011 "Expected E_INVALIDARG, got %x\n", GetLastError());
1012 certInfo.SerialNumber.cbData = sizeof(serialNum);
1013 certInfo.SerialNumber.pbData = serialNum;
1014 SetLastError(0xdeadbeef);
1015 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1017 ok(!msg && GetLastError() == E_INVALIDARG,
1018 "Expected E_INVALIDARG, got %x\n", GetLastError());
1019 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1020 certInfo.Issuer.pbData = encodedCommonName;
1021 SetLastError(0xdeadbeef);
1022 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1024 ok(!msg && GetLastError() == E_INVALIDARG,
1025 "Expected E_INVALIDARG, got %x\n", GetLastError());
1027 /* The signer's hCryptProv must be set to something. Whether it's usable
1028 * or not will be checked after the hash algorithm is checked (see next
1031 signer.hCryptProv = 1;
1032 SetLastError(0xdeadbeef);
1033 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1035 ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
1036 "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
1037 /* The signer's hash algorithm must also be set. */
1038 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1039 SetLastError(0xdeadbeef);
1040 /* Crashes in advapi32 in wine, don't do it */
1042 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED,
1043 &signInfo, NULL, NULL);
1044 ok(!msg && GetLastError() == ERROR_INVALID_PARAMETER,
1045 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1047 /* The signer's hCryptProv must also be valid. */
1048 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1049 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1050 if (!ret && GetLastError() == NTE_EXISTS)
1051 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1053 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1054 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1056 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1059 CryptReleaseContext(signer.hCryptProv, 0);
1060 CryptAcquireContextW(&signer.hCryptProv, cspNameW, MS_DEF_PROV_W,
1061 PROV_RSA_FULL, CRYPT_DELETEKEYSET);
1064 static const BYTE privKey[] = {
1065 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1066 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1067 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1068 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1069 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1070 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1071 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1072 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1073 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1074 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1075 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1076 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1077 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1078 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1079 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1080 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1081 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1082 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1083 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1084 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1085 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1086 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1087 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1088 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1090 static void test_signed_msg_update(void)
1094 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1095 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1096 CERT_INFO certInfo = { 0 };
1098 char oid_rsa_md5[] = szOID_RSA_MD5;
1100 certInfo.SerialNumber.cbData = sizeof(serialNum);
1101 certInfo.SerialNumber.pbData = serialNum;
1102 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1103 certInfo.Issuer.pbData = encodedCommonName;
1104 signer.pCertInfo = &certInfo;
1105 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1106 signInfo.cSigners = 1;
1107 signInfo.rgSigners = &signer;
1108 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1109 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1110 if (!ret && GetLastError() == NTE_EXISTS)
1111 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1113 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1114 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1115 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1116 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1117 /* CMSG_SIGNED allows non-final updates. */
1118 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1120 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1121 /* CMSG_SIGNED also allows non-final updates with no data. */
1122 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1124 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1125 /* The final update requires a private key in the hCryptProv, in order to
1126 * generate the signature.
1128 SetLastError(0xdeadbeef);
1129 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1131 ok(!ret && GetLastError() == NTE_BAD_KEYSET,
1132 "Expected NTE_BAD_KEYSET, got %x\n", GetLastError());
1133 ret = CryptImportKey(signer.hCryptProv, (LPBYTE)privKey, sizeof(privKey),
1135 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1136 /* The final update should be able to succeed now that a key exists, but
1137 * the previous (invalid) final update prevents it.
1139 SetLastError(0xdeadbeef);
1140 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1141 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1142 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1145 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1146 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1147 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1148 /* CMSG_SIGNED allows non-final updates. */
1149 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1151 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1152 /* CMSG_SIGNED also allows non-final updates with no data. */
1153 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1155 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1156 /* Now that the private key exists, the final update can succeed (even
1159 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1161 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1162 /* But no updates are allowed after the final update. */
1163 SetLastError(0xdeadbeef);
1164 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1165 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1166 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1167 SetLastError(0xdeadbeef);
1168 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1169 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1170 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1173 CryptDestroyKey(key);
1174 CryptReleaseContext(signer.hCryptProv, 0);
1175 CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL, PROV_RSA_FULL,
1176 CRYPT_DELETEKEYSET);
1179 static void test_signed_msg(void)
1181 test_signed_msg_open();
1182 test_signed_msg_update();
1185 static CRYPT_DATA_BLOB b4 = { 0, NULL };
1186 static const struct update_accum a4 = { 1, &b4 };
1188 static const BYTE bogusOIDContent[] = {
1189 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
1191 static const BYTE bogusHashContent[] = {
1192 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1193 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1194 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1195 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x00,0xd6,0xc0,
1196 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1198 static void test_decode_msg_update(void)
1202 CMSG_STREAM_INFO streamInfo = { 0 };
1204 struct update_accum accum = { 0, NULL };
1206 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1207 /* Update with a full message in a final update */
1208 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1209 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1210 /* Can't update after a final update */
1211 SetLastError(0xdeadbeef);
1212 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1213 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1214 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1217 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1218 /* Can't send a non-final update without streaming */
1219 SetLastError(0xdeadbeef);
1220 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1222 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1223 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1224 /* A subsequent final update succeeds */
1225 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1226 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1229 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1230 /* Updating a message that has a NULL stream callback fails */
1231 SetLastError(0xdeadbeef);
1232 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1235 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1236 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1237 /* Changing the callback pointer after the fact yields the same error (so
1238 * the message must copy the stream info, not just store a pointer to it)
1240 streamInfo.pfnStreamOutput = nop_stream_output;
1241 SetLastError(0xdeadbeef);
1242 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1245 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1246 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1249 /* Empty non-final updates are allowed when streaming.. */
1250 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1251 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1252 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1253 /* but final updates aren't when not enough data has been received. */
1254 SetLastError(0xdeadbeef);
1255 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1257 ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
1258 "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
1261 /* Updating the message byte by byte is legal */
1262 streamInfo.pfnStreamOutput = accumulating_stream_output;
1263 streamInfo.pvArg = &accum;
1264 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1265 for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
1266 ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
1267 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1268 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1269 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1272 check_updates("byte-by-byte empty content", &a4, &accum);
1273 free_updates(&accum);
1275 /* Decoding bogus content fails in non-streaming mode.. */
1276 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1277 SetLastError(0xdeadbeef);
1278 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1279 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1280 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1282 /* and as the final update in streaming mode.. */
1283 streamInfo.pfnStreamOutput = nop_stream_output;
1284 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1285 SetLastError(0xdeadbeef);
1286 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1288 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1289 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1291 /* and even as a non-final update in streaming mode. */
1292 streamInfo.pfnStreamOutput = nop_stream_output;
1293 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1294 SetLastError(0xdeadbeef);
1295 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1297 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1298 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1301 /* An empty message can be opened with indetermined type.. */
1302 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1303 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1305 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1306 /* but decoding it as an explicitly typed message fails. */
1307 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1309 SetLastError(0xdeadbeef);
1310 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1312 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1313 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1315 /* On the other hand, decoding the bare content of an empty message fails
1316 * with unspecified type..
1318 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1319 SetLastError(0xdeadbeef);
1320 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1321 sizeof(dataEmptyBareContent), TRUE);
1322 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1323 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1325 /* but succeeds with explicit type. */
1326 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1328 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1329 sizeof(dataEmptyBareContent), TRUE);
1330 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1333 /* Decoding valid content with an unsupported OID fails */
1334 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1335 SetLastError(0xdeadbeef);
1336 ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
1337 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1338 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1341 /* Similarly, opening an empty hash with unspecified type succeeds.. */
1342 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1343 SetLastError(0xdeadbeef);
1344 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1345 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1347 /* while with specified type it fails. */
1348 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1350 SetLastError(0xdeadbeef);
1351 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1352 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1353 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1355 /* On the other hand, decoding the bare content of an empty hash message
1356 * fails with unspecified type..
1358 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1359 SetLastError(0xdeadbeef);
1360 ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1361 sizeof(hashEmptyBareContent), TRUE);
1362 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1363 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1365 /* but succeeds with explicit type. */
1366 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1368 ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1369 sizeof(hashEmptyBareContent), TRUE);
1370 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1373 /* And again, opening a (non-empty) hash message with unspecified type
1376 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1377 SetLastError(0xdeadbeef);
1378 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1379 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1381 /* while with specified type it fails.. */
1382 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1384 SetLastError(0xdeadbeef);
1385 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1386 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1387 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1389 /* and decoding the bare content of a non-empty hash message fails with
1390 * unspecified type..
1392 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1393 SetLastError(0xdeadbeef);
1394 ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1395 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1396 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1398 /* but succeeds with explicit type. */
1399 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1401 ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1402 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1405 /* Opening a (non-empty) hash message with unspecified type and a bogus
1406 * hash value succeeds..
1408 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1409 SetLastError(0xdeadbeef);
1410 ret = CryptMsgUpdate(msg, bogusHashContent, sizeof(bogusHashContent), TRUE);
1411 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1415 static const BYTE hashParam[] = { 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,
1416 0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1418 static void test_decode_msg_get_param(void)
1422 DWORD size = 0, version;
1424 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1425 SetLastError(0xdeadbeef);
1426 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
1427 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1428 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1429 ret = CryptMsgUpdate(msg, dataContent, sizeof(dataContent), TRUE);
1430 check_param("data content", msg, CMSG_CONTENT_PARAM, msgData,
1434 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1435 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1436 check_param("empty hash content", msg, CMSG_CONTENT_PARAM, NULL, 0);
1437 check_param("empty hash hash data", msg, CMSG_HASH_DATA_PARAM, NULL, 0);
1438 check_param("empty hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1439 emptyHashParam, sizeof(emptyHashParam));
1441 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1442 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1443 check_param("hash content", msg, CMSG_CONTENT_PARAM, msgData,
1445 check_param("hash hash data", msg, CMSG_HASH_DATA_PARAM, hashParam,
1447 check_param("hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1448 hashParam, sizeof(hashParam));
1449 size = strlen(szOID_RSA_data) + 1;
1450 check_param("hash inner OID", msg, CMSG_INNER_CONTENT_TYPE_PARAM,
1451 (const BYTE *)szOID_RSA_data, strlen(szOID_RSA_data) + 1);
1452 version = CMSG_HASHED_DATA_V0;
1453 check_param("hash version", msg, CMSG_VERSION_PARAM, (const BYTE *)&version,
1458 static void test_decode_msg(void)
1460 test_decode_msg_update();
1461 test_decode_msg_get_param();
1466 /* Basic parameter checking tests */
1467 test_msg_open_to_encode();
1468 test_msg_open_to_decode();
1469 test_msg_get_param();
1472 /* Message-type specific tests */