crypt32: Fix more test failures on Win9x.
[wine/multimedia.git] / dlls / crypt32 / tests / msg.c
blobe296721cca98137606a01cc7408940bcc9cc13cd
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 #define CMSG_SIGNER_ENCODE_INFO_HAS_CMS_FIELDS
27 #define CMSG_SIGNED_ENCODE_INFO_HAS_CMS_FIELDS
28 #include <wincrypt.h>
30 #include "wine/test.h"
32 static BOOL have_nt;
33 static char oid_rsa_md5[] = szOID_RSA_MD5;
35 static BOOL (WINAPI * pCryptAcquireContextA)
36 (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD);
37 static BOOL (WINAPI * pCryptAcquireContextW)
38 (HCRYPTPROV *, LPCWSTR, LPCWSTR, DWORD, DWORD);
40 static void init_function_pointers(void)
42 HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll");
44 #define GET_PROC(dll, func) \
45 p ## func = (void *)GetProcAddress(dll, #func); \
46 if(!p ## func) \
47 trace("GetProcAddress(%s) failed\n", #func);
49 GET_PROC(hAdvapi32, CryptAcquireContextA)
50 GET_PROC(hAdvapi32, CryptAcquireContextW)
52 #undef GET_PROC
55 static void test_msg_open_to_encode(void)
57 HCRYPTMSG msg;
59 /* Crash
60 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, NULL,
61 NULL, NULL);
62 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, NULL, NULL,
63 NULL);
64 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, NULL, NULL,
65 NULL);
68 /* Bad encodings */
69 SetLastError(0xdeadbeef);
70 msg = CryptMsgOpenToEncode(0, 0, 0, NULL, NULL, NULL);
71 ok(!msg && GetLastError() == E_INVALIDARG,
72 "Expected E_INVALIDARG, got %x\n", GetLastError());
73 SetLastError(0xdeadbeef);
74 msg = CryptMsgOpenToEncode(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
75 ok(!msg && GetLastError() == E_INVALIDARG,
76 "Expected E_INVALIDARG, got %x\n", GetLastError());
78 /* Bad message types */
79 SetLastError(0xdeadbeef);
80 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
81 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
82 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
83 SetLastError(0xdeadbeef);
84 msg = CryptMsgOpenToEncode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0,
85 NULL, NULL, NULL);
86 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
87 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
88 SetLastError(0xdeadbeef);
89 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0,
90 CMSG_SIGNED_AND_ENVELOPED, NULL, NULL, NULL);
91 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
92 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
93 SetLastError(0xdeadbeef);
94 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, NULL,
95 NULL, NULL);
96 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
97 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
100 static void test_msg_open_to_decode(void)
102 HCRYPTMSG msg;
103 CMSG_STREAM_INFO streamInfo = { 0 };
105 SetLastError(0xdeadbeef);
106 msg = CryptMsgOpenToDecode(0, 0, 0, 0, NULL, NULL);
107 ok(!msg && GetLastError() == E_INVALIDARG,
108 "Expected E_INVALIDARG, got %x\n", GetLastError());
110 /* Bad encodings */
111 SetLastError(0xdeadbeef);
112 msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, 0, 0, NULL, NULL);
113 ok(!msg && GetLastError() == E_INVALIDARG,
114 "Expected E_INVALIDARG, got %x\n", GetLastError());
115 SetLastError(0xdeadbeef);
116 msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, CMSG_DATA, 0, NULL, NULL);
117 ok(!msg && GetLastError() == E_INVALIDARG,
118 "Expected E_INVALIDARG, got %x\n", GetLastError());
120 /* The message type can be explicit... */
121 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
122 NULL);
123 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
124 CryptMsgClose(msg);
125 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
126 NULL);
127 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
128 CryptMsgClose(msg);
129 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
130 NULL);
131 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
132 CryptMsgClose(msg);
133 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
134 NULL);
135 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
136 CryptMsgClose(msg);
137 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0,
138 CMSG_SIGNED_AND_ENVELOPED, 0, NULL, NULL);
139 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
140 CryptMsgClose(msg);
141 /* or implicit.. */
142 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
143 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
144 CryptMsgClose(msg);
145 /* or even invalid. */
146 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
147 NULL);
148 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
149 CryptMsgClose(msg);
150 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
151 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
152 CryptMsgClose(msg);
154 /* And even though the stream info parameter "must be set to NULL" for
155 * CMSG_HASHED, it's still accepted.
157 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
158 &streamInfo);
159 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
160 CryptMsgClose(msg);
163 static void test_msg_get_param(void)
165 BOOL ret;
166 HCRYPTMSG msg;
167 DWORD size, i, value;
168 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
169 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
171 /* Crash
172 ret = CryptMsgGetParam(NULL, 0, 0, NULL, NULL);
173 ret = CryptMsgGetParam(NULL, 0, 0, NULL, &size);
174 ret = CryptMsgGetParam(msg, 0, 0, NULL, NULL);
177 /* Decoded messages */
178 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
179 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
180 /* For decoded messages, the type is always available */
181 size = 0;
182 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
183 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
184 size = sizeof(value);
185 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &value, &size);
186 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
187 /* For this (empty) message, the type isn't set */
188 ok(value == 0, "Expected type 0, got %d\n", value);
189 CryptMsgClose(msg);
191 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
192 NULL);
193 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
194 /* For explicitly typed messages, the type is known. */
195 size = sizeof(value);
196 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &value, &size);
197 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
198 ok(value == CMSG_DATA, "Expected CMSG_DATA, got %d\n", value);
199 for (i = CMSG_CONTENT_PARAM; have_nt && (i <= CMSG_CMS_SIGNER_INFO_PARAM); i++)
201 size = 0;
202 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
203 ok(!ret, "Parameter %d: expected failure\n", i);
205 CryptMsgClose(msg);
207 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
208 NULL);
209 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
210 size = sizeof(value);
211 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &value, &size);
212 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
213 ok(value == CMSG_ENVELOPED, "Expected CMSG_ENVELOPED, got %d\n", value);
214 for (i = CMSG_CONTENT_PARAM; have_nt && (i <= CMSG_CMS_SIGNER_INFO_PARAM); i++)
216 size = 0;
217 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
218 ok(!ret, "Parameter %d: expected failure\n", i);
220 CryptMsgClose(msg);
222 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
223 NULL);
224 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
225 size = sizeof(value);
226 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &value, &size);
227 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
228 ok(value == CMSG_HASHED, "Expected CMSG_HASHED, got %d\n", value);
229 for (i = CMSG_CONTENT_PARAM; have_nt && (i <= CMSG_CMS_SIGNER_INFO_PARAM); i++)
231 size = 0;
232 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
233 ok(!ret, "Parameter %d: expected failure\n", i);
235 CryptMsgClose(msg);
237 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
238 NULL);
239 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
240 size = sizeof(value);
241 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &value, &size);
242 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
243 ok(value == CMSG_SIGNED, "Expected CMSG_SIGNED, got %d\n", value);
244 for (i = CMSG_CONTENT_PARAM; have_nt && (i <= CMSG_CMS_SIGNER_INFO_PARAM); i++)
246 size = 0;
247 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
248 ok(!ret, "Parameter %d: expected failure\n", i);
250 CryptMsgClose(msg);
252 /* Explicitly typed messages get their types set, even if they're invalid */
253 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
254 NULL);
255 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
256 size = sizeof(value);
257 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &value, &size);
258 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
259 ok(value == CMSG_ENCRYPTED, "Expected CMSG_ENCRYPTED, got %d\n", value);
260 CryptMsgClose(msg);
262 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
263 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
264 size = sizeof(value);
265 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &value, &size);
266 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
267 ok(value == 1000, "Expected 1000, got %d\n", value);
268 CryptMsgClose(msg);
271 static void test_msg_close(void)
273 BOOL ret;
274 HCRYPTMSG msg;
276 /* NULL succeeds.. */
277 ret = CryptMsgClose(NULL);
278 ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
279 /* but an arbitrary pointer crashes. */
280 if (0)
281 ret = CryptMsgClose((HCRYPTMSG)1);
282 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
283 NULL);
284 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
285 ret = CryptMsgClose(msg);
286 ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
289 static void check_param(LPCSTR test, HCRYPTMSG msg, DWORD param,
290 const BYTE *expected, DWORD expectedSize)
292 DWORD size;
293 LPBYTE buf;
294 BOOL ret;
296 size = 0xdeadbeef;
297 ret = CryptMsgGetParam(msg, param, 0, NULL, &size);
298 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
299 "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
300 if (!ret)
302 win_skip("parameter %d not supported, skipping tests\n", param);
303 return;
305 buf = HeapAlloc(GetProcessHeap(), 0, size);
306 ret = CryptMsgGetParam(msg, param, 0, buf, &size);
307 ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
308 ok(size == expectedSize, "%s: expected size %d, got %d\n", test,
309 expectedSize, size);
310 if (size == expectedSize && size)
311 ok(!memcmp(buf, expected, size), "%s: unexpected data\n", test);
312 HeapFree(GetProcessHeap(), 0, buf);
315 static void test_data_msg_open(void)
317 HCRYPTMSG msg;
318 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
319 CMSG_STREAM_INFO streamInfo = { 0 };
320 char oid[] = "1.2.3";
322 /* The data message type takes no additional info */
323 SetLastError(0xdeadbeef);
324 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, &hashInfo,
325 NULL, NULL);
326 ok(!msg && GetLastError() == E_INVALIDARG,
327 "Expected E_INVALIDARG, got %x\n", GetLastError());
328 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
329 NULL);
330 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
331 CryptMsgClose(msg);
333 /* An empty stream info is allowed. */
334 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
335 &streamInfo);
336 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
337 CryptMsgClose(msg);
339 /* Passing a bogus inner OID succeeds for a non-streamed message.. */
340 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
341 NULL);
342 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
343 CryptMsgClose(msg);
344 /* and still succeeds when CMSG_DETACHED_FLAG is passed.. */
345 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
346 CMSG_DATA, NULL, oid, NULL);
347 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
348 CryptMsgClose(msg);
349 /* and when a stream info is given, even though you're not supposed to be
350 * able to use anything but szOID_RSA_data when streaming is being used.
352 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
353 CMSG_DATA, NULL, oid, &streamInfo);
354 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
355 CryptMsgClose(msg);
358 static const BYTE msgData[] = { 1, 2, 3, 4 };
360 static BOOL WINAPI nop_stream_output(const void *pvArg, BYTE *pb, DWORD cb,
361 BOOL final)
363 return TRUE;
366 static void test_data_msg_update(void)
368 HCRYPTMSG msg;
369 BOOL ret;
370 CMSG_STREAM_INFO streamInfo = { 0 };
372 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
373 NULL);
374 /* Can't update a message that wasn't opened detached with final = FALSE */
375 SetLastError(0xdeadbeef);
376 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
377 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
378 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
379 /* Updating it with final = TRUE succeeds */
380 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
381 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
382 /* Any subsequent update will fail, as the last was final */
383 SetLastError(0xdeadbeef);
384 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
385 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
386 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
387 CryptMsgClose(msg);
389 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
390 NULL);
391 /* Can't update a message with no data */
392 SetLastError(0xdeadbeef);
393 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
394 /* This test returns FALSE on XP and earlier but TRUE on Vista, so can't be tested.
395 * GetLastError is either E_INVALIDARG (NT) or unset (9x/Vista), so it doesn't
396 * make sense to test this.
399 /* Curiously, a valid update will now fail as well, presumably because of
400 * the last (invalid, but final) update.
402 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
403 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
404 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
405 CryptMsgClose(msg);
407 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
408 CMSG_DATA, NULL, NULL, NULL);
409 /* Doesn't appear to be able to update CMSG-DATA with non-final updates */
410 SetLastError(0xdeadbeef);
411 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
412 ok((!ret && GetLastError() == E_INVALIDARG) || broken(ret /* Win9x */),
413 "Expected E_INVALIDARG, got %x\n", GetLastError());
414 SetLastError(0xdeadbeef);
415 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
416 ok((!ret && GetLastError() == E_INVALIDARG) || broken(ret /* Win9x */),
417 "Expected E_INVALIDARG, got %x\n", GetLastError());
418 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
419 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
420 CryptMsgClose(msg);
422 if (have_nt)
424 /* Calling update after opening with an empty stream info (with a bogus
425 * output function) yields an error:
427 /* Crashes on some Win9x */
428 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
429 &streamInfo);
430 SetLastError(0xdeadbeef);
431 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
432 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
433 GetLastError() == STATUS_ILLEGAL_INSTRUCTION /* WinME */),
434 "Expected STATUS_ACCESS_VIOLATION or STATUS_ILLEGAL_INSTRUCTION, got %x\n",
435 GetLastError());
436 CryptMsgClose(msg);
438 /* Calling update with a valid output function succeeds, even if the data
439 * exceeds the size specified in the stream info.
441 streamInfo.pfnStreamOutput = nop_stream_output;
442 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
443 &streamInfo);
444 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
445 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
446 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
447 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
448 CryptMsgClose(msg);
451 static void test_data_msg_get_param(void)
453 HCRYPTMSG msg;
454 DWORD size;
455 BOOL ret;
456 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
458 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
459 NULL);
461 /* Content and bare content are always gettable when not streaming */
462 size = 0;
463 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
464 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
465 size = 0;
466 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
467 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
468 /* But for this type of message, the signer and hash aren't applicable,
469 * and the type isn't available.
471 size = 0;
472 SetLastError(0xdeadbeef);
473 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
474 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
475 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
476 SetLastError(0xdeadbeef);
477 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
478 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
479 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
480 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
481 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
482 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
483 CryptMsgClose(msg);
485 /* Can't get content or bare content when streaming */
486 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
487 NULL, &streamInfo);
488 SetLastError(0xdeadbeef);
489 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
490 ok((!ret && GetLastError() == E_INVALIDARG) || broken(ret /* Win9x */),
491 "Expected E_INVALIDARG, got %x\n", GetLastError());
492 SetLastError(0xdeadbeef);
493 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
494 ok((!ret && GetLastError() == E_INVALIDARG) || broken(ret /* Win9x */),
495 "Expected E_INVALIDARG, got %x\n", GetLastError());
496 CryptMsgClose(msg);
499 static const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
500 static const BYTE dataEmptyContent[] = {
501 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
502 0x04,0x00 };
503 static const BYTE dataBareContent[] = { 0x04,0x04,0x01,0x02,0x03,0x04 };
504 static const BYTE dataContent[] = {
505 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,
506 0x04,0x04,0x01,0x02,0x03,0x04 };
508 struct update_accum
510 DWORD cUpdates;
511 CRYPT_DATA_BLOB *updates;
514 static BOOL WINAPI accumulating_stream_output(const void *pvArg, BYTE *pb,
515 DWORD cb, BOOL final)
517 struct update_accum *accum = (struct update_accum *)pvArg;
518 BOOL ret = FALSE;
520 if (accum->cUpdates)
521 accum->updates = CryptMemRealloc(accum->updates,
522 (accum->cUpdates + 1) * sizeof(CRYPT_DATA_BLOB));
523 else
524 accum->updates = CryptMemAlloc(sizeof(CRYPT_DATA_BLOB));
525 if (accum->updates)
527 CRYPT_DATA_BLOB *blob = &accum->updates[accum->cUpdates];
529 blob->pbData = CryptMemAlloc(cb);
530 if (blob->pbData)
532 memcpy(blob->pbData, pb, cb);
533 blob->cbData = cb;
534 ret = TRUE;
536 accum->cUpdates++;
538 return ret;
541 /* The updates of a (bogus) definite-length encoded message */
542 static BYTE u1[] = { 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
543 0x07,0x01,0xa0,0x02,0x04,0x00 };
544 static BYTE u2[] = { 0x01,0x02,0x03,0x04 };
545 static CRYPT_DATA_BLOB b1[] = {
546 { sizeof(u1), u1 },
547 { sizeof(u2), u2 },
548 { sizeof(u2), u2 },
550 static const struct update_accum a1 = { sizeof(b1) / sizeof(b1[0]), b1 };
551 /* The updates of a definite-length encoded message */
552 static BYTE u3[] = { 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
553 0x07,0x01,0xa0,0x06,0x04,0x04 };
554 static CRYPT_DATA_BLOB b2[] = {
555 { sizeof(u3), u3 },
556 { sizeof(u2), u2 },
558 static const struct update_accum a2 = { sizeof(b2) / sizeof(b2[0]), b2 };
559 /* The updates of an indefinite-length encoded message */
560 static BYTE u4[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
561 0x07,0x01,0xa0,0x80,0x24,0x80 };
562 static BYTE u5[] = { 0x04,0x04 };
563 static BYTE u6[] = { 0x00,0x00,0x00,0x00,0x00,0x00 };
564 static CRYPT_DATA_BLOB b3[] = {
565 { sizeof(u4), u4 },
566 { sizeof(u5), u5 },
567 { sizeof(u2), u2 },
568 { sizeof(u5), u5 },
569 { sizeof(u2), u2 },
570 { sizeof(u6), u6 },
572 static const struct update_accum a3 = { sizeof(b3) / sizeof(b3[0]), b3 };
574 static void check_updates(LPCSTR header, const struct update_accum *expected,
575 const struct update_accum *got)
577 DWORD i;
579 ok(expected->cUpdates == got->cUpdates,
580 "%s: expected %d updates, got %d\n", header, expected->cUpdates,
581 got->cUpdates);
582 if (expected->cUpdates == got->cUpdates)
583 for (i = 0; i < min(expected->cUpdates, got->cUpdates); i++)
585 ok(expected->updates[i].cbData == got->updates[i].cbData,
586 "%s, update %d: expected %d bytes, got %d\n", header, i,
587 expected->updates[i].cbData, got->updates[i].cbData);
588 if (expected->updates[i].cbData && expected->updates[i].cbData ==
589 got->updates[i].cbData)
590 ok(!memcmp(expected->updates[i].pbData, got->updates[i].pbData,
591 got->updates[i].cbData), "%s, update %d: unexpected value\n",
592 header, i);
596 /* Frees the updates stored in accum */
597 static void free_updates(struct update_accum *accum)
599 DWORD i;
601 for (i = 0; i < accum->cUpdates; i++)
602 CryptMemFree(accum->updates[i].pbData);
603 CryptMemFree(accum->updates);
604 accum->updates = NULL;
605 accum->cUpdates = 0;
608 static void test_data_msg_encoding(void)
610 HCRYPTMSG msg;
611 BOOL ret;
612 static char oid[] = "1.2.3";
613 struct update_accum accum = { 0, NULL };
614 CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
616 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
617 NULL);
618 check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
619 dataEmptyBareContent, sizeof(dataEmptyBareContent));
620 check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
621 sizeof(dataEmptyContent));
622 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
623 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
624 check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
625 dataBareContent, sizeof(dataBareContent));
626 check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
627 sizeof(dataContent));
628 CryptMsgClose(msg);
629 /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
630 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
631 CMSG_DATA, NULL, NULL, NULL);
632 check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
633 dataEmptyBareContent, sizeof(dataEmptyBareContent));
634 check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
635 sizeof(dataEmptyContent));
636 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
637 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
638 check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
639 dataBareContent, sizeof(dataBareContent));
640 check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
641 sizeof(dataContent));
642 CryptMsgClose(msg);
643 /* The inner OID is apparently ignored */
644 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
645 NULL);
646 check_param("data bogus oid bare content", msg, CMSG_BARE_CONTENT_PARAM,
647 dataEmptyBareContent, sizeof(dataEmptyBareContent));
648 check_param("data bogus oid content", msg, CMSG_CONTENT_PARAM,
649 dataEmptyContent, sizeof(dataEmptyContent));
650 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
651 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
652 check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
653 dataBareContent, sizeof(dataBareContent));
654 check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
655 sizeof(dataContent));
656 CryptMsgClose(msg);
657 /* A streaming message is DER encoded if the length is not 0xffffffff, but
658 * curiously, updates aren't validated to make sure they don't exceed the
659 * stated length. (The resulting output will of course fail to decode.)
661 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
662 NULL, &streamInfo);
663 CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
664 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
665 CryptMsgClose(msg);
666 check_updates("bogus data message with definite length", &a1, &accum);
667 free_updates(&accum);
668 /* A valid definite-length encoding: */
669 streamInfo.cbContent = sizeof(msgData);
670 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
671 NULL, &streamInfo);
672 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
673 CryptMsgClose(msg);
674 check_updates("data message with definite length", &a2, &accum);
675 free_updates(&accum);
676 /* An indefinite-length encoding: */
677 streamInfo.cbContent = 0xffffffff;
678 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
679 NULL, &streamInfo);
680 CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
681 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
682 CryptMsgClose(msg);
683 check_updates("data message with indefinite length", &a3, &accum);
684 free_updates(&accum);
687 static void test_data_msg(void)
689 test_data_msg_open();
690 test_data_msg_update();
691 test_data_msg_get_param();
692 test_data_msg_encoding();
695 static void test_hash_msg_open(void)
697 HCRYPTMSG msg;
698 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
699 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
701 SetLastError(0xdeadbeef);
702 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
703 NULL, NULL);
704 ok(!msg && GetLastError() == E_INVALIDARG,
705 "Expected E_INVALIDARG, got %x\n", GetLastError());
706 hashInfo.cbSize = sizeof(hashInfo);
707 SetLastError(0xdeadbeef);
708 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
709 NULL, NULL);
710 ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
711 "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
712 hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
713 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
714 NULL, NULL);
715 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
716 CryptMsgClose(msg);
717 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
718 CMSG_HASHED, &hashInfo, NULL, NULL);
719 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
720 CryptMsgClose(msg);
721 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
722 CMSG_HASHED, &hashInfo, NULL, &streamInfo);
723 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
724 CryptMsgClose(msg);
727 static void test_hash_msg_update(void)
729 HCRYPTMSG msg;
730 BOOL ret;
731 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
732 { oid_rsa_md5, { 0, NULL } }, NULL };
733 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
735 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
736 CMSG_HASHED, &hashInfo, NULL, NULL);
737 /* Detached hashed messages opened in non-streaming mode allow non-final
738 * updates..
740 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
741 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
742 /* including non-final updates with no data.. */
743 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
744 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
745 /* and final updates with no data. */
746 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
747 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
748 /* But no updates are allowed after the final update. */
749 SetLastError(0xdeadbeef);
750 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
751 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
752 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
753 SetLastError(0xdeadbeef);
754 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
755 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
756 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
757 CryptMsgClose(msg);
758 /* Non-detached messages, in contrast, don't allow non-final updates in
759 * non-streaming mode.
761 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
762 NULL, NULL);
763 SetLastError(0xdeadbeef);
764 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
765 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
766 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
767 /* Final updates (including empty ones) are allowed. */
768 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
769 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
770 CryptMsgClose(msg);
771 /* And, of course, streaming mode allows non-final updates */
772 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
773 NULL, &streamInfo);
774 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
775 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
776 CryptMsgClose(msg);
777 /* Setting pfnStreamOutput to NULL results in no error. (In what appears
778 * to be a bug, it isn't actually used - see encoding tests.)
780 streamInfo.pfnStreamOutput = NULL;
781 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
782 NULL, &streamInfo);
783 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
784 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
785 CryptMsgClose(msg);
788 static const BYTE emptyHashParam[] = {
789 0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,
790 0x7e };
792 static void test_hash_msg_get_param(void)
794 HCRYPTMSG msg;
795 BOOL ret;
796 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
797 { oid_rsa_md5, { 0, NULL } }, NULL };
798 DWORD size, value;
799 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
800 BYTE buf[16];
802 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
803 NULL, NULL);
804 /* Content and bare content are always gettable for non-streamed messages */
805 size = 0;
806 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
807 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
808 "CryptMsgGetParam failed: %08x\n", GetLastError());
809 size = 0;
810 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
811 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
812 "CryptMsgGetParam failed: %08x\n", GetLastError());
813 /* For an encoded hash message, the hash data aren't available */
814 SetLastError(0xdeadbeef);
815 ret = CryptMsgGetParam(msg, CMSG_HASH_DATA_PARAM, 0, NULL, &size);
816 ok(!ret && (GetLastError() == CRYPT_E_INVALID_MSG_TYPE ||
817 GetLastError() == OSS_LIMITED /* Win9x */),
818 "Expected CRYPT_E_INVALID_MSG_TYPE or OSS_LIMITED, got %08x\n",
819 GetLastError());
820 /* The hash is also available. */
821 size = 0;
822 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
823 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
824 ok(size == sizeof(buf), "Unexpected size %d\n", size);
825 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
826 if (size == sizeof(buf))
827 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
828 /* By getting the hash, further updates are not allowed */
829 SetLastError(0xdeadbeef);
830 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
831 ok(!ret &&
832 (GetLastError() == NTE_BAD_HASH_STATE /* NT */ ||
833 GetLastError() == NTE_BAD_ALGID /* 9x */ ||
834 GetLastError() == CRYPT_E_MSG_ERROR /* Vista */),
835 "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID or CRYPT_E_MSG_ERROR, got 0x%x\n", GetLastError());
837 /* Even after a final update, the hash data aren't available */
838 SetLastError(0xdeadbeef);
839 ret = CryptMsgGetParam(msg, CMSG_HASH_DATA_PARAM, 0, NULL, &size);
840 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
841 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
842 /* The version is also available, and should be zero for this message. */
843 size = 0;
844 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
845 ok(ret || broken(GetLastError() == CRYPT_E_INVALID_MSG_TYPE /* Win9x */),
846 "CryptMsgGetParam failed: %08x\n", GetLastError());
847 size = sizeof(value);
848 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, &value, &size);
849 ok(ret || broken(GetLastError() == CRYPT_E_INVALID_MSG_TYPE /* Win9x */),
850 "CryptMsgGetParam failed: %08x\n", GetLastError());
851 if (ret)
852 ok(value == 0, "Expected version 0, got %d\n", value);
853 /* As usual, the type isn't available. */
854 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
855 ok(!ret, "Expected failure\n");
856 CryptMsgClose(msg);
858 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
859 NULL, &streamInfo);
860 /* Streamed messages don't allow you to get the content or bare content. */
861 SetLastError(0xdeadbeef);
862 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
863 ok(!ret && (GetLastError() == E_INVALIDARG ||
864 GetLastError() == OSS_LIMITED /* Win9x */),
865 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
866 SetLastError(0xdeadbeef);
867 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
868 ok(!ret && (GetLastError() == E_INVALIDARG ||
869 GetLastError() == OSS_LIMITED /* Win9x */),
870 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
871 /* The hash is still available. */
872 size = 0;
873 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
874 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
875 ok(size == sizeof(buf), "Unexpected size %d\n", size);
876 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
877 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
878 if (size == sizeof(buf))
879 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
880 /* After updating the hash, further updates aren't allowed on streamed
881 * messages either.
883 SetLastError(0xdeadbeef);
884 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
885 ok(!ret &&
886 (GetLastError() == NTE_BAD_HASH_STATE /* NT */ ||
887 GetLastError() == NTE_BAD_ALGID /* 9x */ ||
888 GetLastError() == CRYPT_E_MSG_ERROR /* Vista */),
889 "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID or CRYPT_E_MSG_ERROR, got 0x%x\n", GetLastError());
891 CryptMsgClose(msg);
894 static const BYTE hashEmptyBareContent[] = {
895 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
896 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
897 static const BYTE hashEmptyContent[] = {
898 0x30,0x26,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x19,
899 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
900 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
901 static const BYTE hashBareContent[] = {
902 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
903 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
904 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
905 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
906 static const BYTE hashContent[] = {
907 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
908 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
909 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
910 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
911 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
913 static const BYTE detachedHashNonFinalBareContent[] = {
914 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
915 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
916 0x07,0x01,0x04,0x00 };
917 static const BYTE detachedHashNonFinalContent[] = {
918 0x30,0x2f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x22,
919 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
920 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
921 0x07,0x01,0x04,0x00 };
922 static const BYTE detachedHashBareContent[] = {
923 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
924 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
925 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
926 0x9d,0x2a,0x8f,0x26,0x2f };
927 static const BYTE detachedHashContent[] = {
928 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
929 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
930 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
931 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
932 0x9d,0x2a,0x8f,0x26,0x2f };
934 static void test_hash_msg_encoding(void)
936 HCRYPTMSG msg;
937 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0 };
938 BOOL ret;
939 struct update_accum accum = { 0, NULL }, empty_accum = { 0, NULL };
940 CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
942 hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
943 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
944 NULL, NULL);
945 check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
946 hashEmptyBareContent, sizeof(hashEmptyBareContent));
947 check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
948 hashEmptyContent, sizeof(hashEmptyContent));
949 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
950 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
951 check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
952 hashBareContent, sizeof(hashBareContent));
953 check_param("hash content", msg, CMSG_CONTENT_PARAM,
954 hashContent, sizeof(hashContent));
955 CryptMsgClose(msg);
956 /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
957 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
958 CMSG_HASHED, &hashInfo, NULL, NULL);
959 check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
960 hashEmptyBareContent, sizeof(hashEmptyBareContent));
961 check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
962 hashEmptyContent, sizeof(hashEmptyContent));
963 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
964 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
965 check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
966 hashBareContent, sizeof(hashBareContent));
967 check_param("hash content", msg, CMSG_CONTENT_PARAM,
968 hashContent, sizeof(hashContent));
969 CryptMsgClose(msg);
970 /* Same test, but with CMSG_DETACHED_FLAG set */
971 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
972 CMSG_HASHED, &hashInfo, NULL, NULL);
973 check_param("detached hash empty bare content", msg,
974 CMSG_BARE_CONTENT_PARAM, hashEmptyBareContent,
975 sizeof(hashEmptyBareContent));
976 check_param("detached hash empty content", msg, CMSG_CONTENT_PARAM,
977 hashEmptyContent, sizeof(hashEmptyContent));
978 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
979 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
980 check_param("detached hash not final bare content", msg,
981 CMSG_BARE_CONTENT_PARAM, detachedHashNonFinalBareContent,
982 sizeof(detachedHashNonFinalBareContent));
983 check_param("detached hash not final content", msg, CMSG_CONTENT_PARAM,
984 detachedHashNonFinalContent, sizeof(detachedHashNonFinalContent));
985 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
986 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
987 check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
988 detachedHashBareContent, sizeof(detachedHashBareContent));
989 check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
990 detachedHashContent, sizeof(detachedHashContent));
991 check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
992 detachedHashBareContent, sizeof(detachedHashBareContent));
993 check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
994 detachedHashContent, sizeof(detachedHashContent));
995 CryptMsgClose(msg);
996 /* In what appears to be a bug, streamed updates to hash messages don't
997 * call the output function.
999 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
1000 NULL, &streamInfo);
1001 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1002 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1003 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1004 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1005 CryptMsgClose(msg);
1006 check_updates("empty hash message", &empty_accum, &accum);
1007 free_updates(&accum);
1009 streamInfo.cbContent = sizeof(msgData);
1010 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
1011 NULL, &streamInfo);
1012 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1013 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1014 CryptMsgClose(msg);
1015 check_updates("hash message", &empty_accum, &accum);
1016 free_updates(&accum);
1018 streamInfo.cbContent = sizeof(msgData);
1019 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
1020 CMSG_HASHED, &hashInfo, NULL, &streamInfo);
1021 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1022 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1023 CryptMsgClose(msg);
1024 check_updates("detached hash message", &empty_accum, &accum);
1025 free_updates(&accum);
1028 static void test_hash_msg(void)
1030 test_hash_msg_open();
1031 test_hash_msg_update();
1032 test_hash_msg_get_param();
1033 test_hash_msg_encoding();
1036 static const CHAR cspNameA[] = { 'W','i','n','e','C','r','y','p','t','T','e',
1037 'm','p',0 };
1038 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
1039 'm','p',0 };
1040 static BYTE serialNum[] = { 1 };
1041 static BYTE encodedCommonName[] = { 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1042 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1044 static void test_signed_msg_open(void)
1046 HCRYPTMSG msg;
1047 BOOL ret;
1048 CMSG_SIGNED_ENCODE_INFO signInfo = { 0 };
1049 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1050 CERT_INFO certInfo = { 0 };
1052 SetLastError(0xdeadbeef);
1053 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1054 NULL, NULL);
1055 ok(!msg && GetLastError() == E_INVALIDARG,
1056 "Expected E_INVALIDARG, got %x\n", GetLastError());
1057 signInfo.cbSize = sizeof(signInfo);
1058 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1059 NULL, NULL);
1060 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1061 CryptMsgClose(msg);
1063 signInfo.cSigners = 1;
1064 signInfo.rgSigners = &signer;
1065 /* With signer.pCertInfo unset, attempting to open this message this
1066 * crashes.
1068 signer.pCertInfo = &certInfo;
1069 /* The cert info must contain a serial number and an issuer. */
1070 SetLastError(0xdeadbeef);
1071 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1072 NULL, NULL);
1073 /* NT: E_INVALIDARG, 9x: unchanged */
1074 ok(!msg && (GetLastError() == E_INVALIDARG || GetLastError() == 0xdeadbeef),
1075 "Expected E_INVALIDARG or 0xdeadbeef, got 0x%x\n", GetLastError());
1077 certInfo.SerialNumber.cbData = sizeof(serialNum);
1078 certInfo.SerialNumber.pbData = serialNum;
1079 SetLastError(0xdeadbeef);
1080 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1081 NULL, NULL);
1082 /* NT: E_INVALIDARG, 9x: unchanged */
1083 ok(!msg && (GetLastError() == E_INVALIDARG || GetLastError() == 0xdeadbeef),
1084 "Expected E_INVALIDARG or 0xdeadbeef, got 0x%x\n", GetLastError());
1086 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1087 certInfo.Issuer.pbData = encodedCommonName;
1088 SetLastError(0xdeadbeef);
1089 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1090 NULL, NULL);
1091 ok(!msg && GetLastError() == E_INVALIDARG,
1092 "Expected E_INVALIDARG, got %x\n", GetLastError());
1094 /* The signer's hCryptProv must be set to something. Whether it's usable
1095 * or not will be checked after the hash algorithm is checked (see next
1096 * test.)
1098 signer.hCryptProv = 1;
1099 SetLastError(0xdeadbeef);
1100 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1101 NULL, NULL);
1102 ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
1103 "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
1104 /* The signer's hash algorithm must also be set. */
1105 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1106 SetLastError(0xdeadbeef);
1107 /* Crashes in advapi32 in wine, don't do it */
1108 if (0) {
1109 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED,
1110 &signInfo, NULL, NULL);
1111 ok(!msg && GetLastError() == ERROR_INVALID_PARAMETER,
1112 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1114 /* The signer's hCryptProv must also be valid. */
1115 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1116 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1117 if (!ret && GetLastError() == NTE_EXISTS) {
1118 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1119 PROV_RSA_FULL, 0);
1121 ok(ret, "CryptAcquireContext failed: 0x%x\n", GetLastError());
1123 if (ret) {
1124 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1125 NULL, NULL);
1126 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1127 CryptMsgClose(msg);
1130 /* pCertInfo must still be set, but can be empty if the SignerId's issuer
1131 * and serial number are set.
1133 certInfo.Issuer.cbData = 0;
1134 certInfo.SerialNumber.cbData = 0;
1135 signer.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
1136 U(signer.SignerId).IssuerSerialNumber.Issuer.cbData =
1137 sizeof(encodedCommonName);
1138 U(signer.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonName;
1139 U(signer.SignerId).IssuerSerialNumber.SerialNumber.cbData =
1140 sizeof(serialNum);
1141 U(signer.SignerId).IssuerSerialNumber.SerialNumber.pbData = serialNum;
1142 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1143 NULL, NULL);
1144 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1145 CryptMsgClose(msg);
1147 CryptReleaseContext(signer.hCryptProv, 0);
1148 pCryptAcquireContextA(&signer.hCryptProv, cspNameA, MS_DEF_PROV_A,
1149 PROV_RSA_FULL, CRYPT_DELETEKEYSET);
1152 static const BYTE privKey[] = {
1153 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1154 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1155 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1156 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1157 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1158 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1159 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1160 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1161 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1162 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1163 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1164 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1165 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1166 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1167 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1168 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1169 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1170 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1171 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1172 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1173 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1174 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1175 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1176 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1177 static BYTE pubKey[] = {
1178 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,
1179 0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,
1180 0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,
1181 0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,
1182 0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
1184 static void test_signed_msg_update(void)
1186 HCRYPTMSG msg;
1187 BOOL ret;
1188 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1189 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1190 CERT_INFO certInfo = { 0 };
1191 HCRYPTKEY key;
1193 certInfo.SerialNumber.cbData = sizeof(serialNum);
1194 certInfo.SerialNumber.pbData = serialNum;
1195 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1196 certInfo.Issuer.pbData = encodedCommonName;
1197 signer.pCertInfo = &certInfo;
1198 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1199 signInfo.cSigners = 1;
1200 signInfo.rgSigners = &signer;
1202 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1203 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1204 if (!ret && GetLastError() == NTE_EXISTS) {
1205 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1206 PROV_RSA_FULL, 0);
1208 ok(ret, "CryptAcquireContext failed: 0x%x\n", GetLastError());
1210 if (!ret) {
1211 skip("No context for tests\n");
1212 return;
1215 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1216 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1217 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1218 /* Detached CMSG_SIGNED allows non-final updates. */
1219 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1220 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1221 /* Detached CMSG_SIGNED also allows non-final updates with no data. */
1222 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1223 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1224 /* The final update requires a private key in the hCryptProv, in order to
1225 * generate the signature.
1227 SetLastError(0xdeadbeef);
1228 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1229 ok(!ret && (GetLastError() == NTE_BAD_KEYSET ||
1230 GetLastError() == NTE_NO_KEY),
1231 "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %x\n", GetLastError());
1232 ret = CryptImportKey(signer.hCryptProv, privKey, sizeof(privKey),
1233 0, 0, &key);
1234 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1235 /* The final update should be able to succeed now that a key exists, but
1236 * the previous (invalid) final update prevents it.
1238 SetLastError(0xdeadbeef);
1239 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1240 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1241 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1242 CryptMsgClose(msg);
1244 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1245 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1246 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1247 /* Detached CMSG_SIGNED allows non-final updates. */
1248 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1249 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1250 /* Detached CMSG_SIGNED also allows non-final updates with no data. */
1251 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1252 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1253 /* Now that the private key exists, the final update can succeed (even
1254 * with no data.)
1256 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1257 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1258 /* But no updates are allowed after the final update. */
1259 SetLastError(0xdeadbeef);
1260 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1261 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1262 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1263 SetLastError(0xdeadbeef);
1264 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1265 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1266 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1267 CryptMsgClose(msg);
1269 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1270 NULL, NULL);
1271 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1272 /* Non-detached messages don't allow non-final updates.. */
1273 SetLastError(0xdeadbeef);
1274 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1275 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1276 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1277 /* but they do allow final ones. */
1278 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1279 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1280 CryptMsgClose(msg);
1281 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1282 NULL, NULL);
1283 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1284 /* They also allow final updates with no data. */
1285 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1286 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1287 CryptMsgClose(msg);
1289 CryptDestroyKey(key);
1290 CryptReleaseContext(signer.hCryptProv, 0);
1291 pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL, PROV_RSA_FULL,
1292 CRYPT_DELETEKEYSET);
1295 static const BYTE signedEmptyBareContent[] = {
1296 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1297 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
1298 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1299 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
1300 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
1301 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1302 static const BYTE signedEmptyContent[] = {
1303 0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52,
1304 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1305 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
1306 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1307 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
1308 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
1309 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1310 static const BYTE detachedSignedBareContent[] = {
1311 0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1312 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,
1313 0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,
1314 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1315 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,
1316 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,
1317 0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,
1318 0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,
1319 0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,
1320 0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,
1321 0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1322 static const BYTE detachedSignedContent[] = {
1323 0x30,0x81,0xaa,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1324 0x81,0x9c,0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1325 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
1326 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,
1327 0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
1328 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,
1329 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,
1330 0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,
1331 0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,
1332 0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,
1333 0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,
1334 0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1335 static const BYTE signedBareContent[] = {
1336 0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1337 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,
1338 0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x31,0x77,
1339 0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1340 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1341 0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,
1342 0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,
1343 0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,
1344 0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,
1345 0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,
1346 0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1347 static const BYTE signedContent[] = {
1348 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1349 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1350 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1351 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1352 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1353 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1354 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1355 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1356 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1357 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1358 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1359 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1360 0x0d };
1361 static const BYTE signedHash[] = {
1362 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,
1363 0x2f };
1364 static const BYTE signedKeyIdEmptyContent[] = {
1365 0x30,0x46,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x39,
1366 0x30,0x37,0x02,0x01,0x03,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1367 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x1e,0x30,0x1c,0x02,
1368 0x01,0x03,0x80,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1369 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1370 static const BYTE signedEncodedSigner[] = {
1371 0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1372 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1373 0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,
1374 0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,
1375 0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,
1376 0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,
1377 0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,
1378 0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1379 static const BYTE signedWithAuthAttrsBareContent[] = {
1380 0x30,0x82,0x01,0x00,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1381 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1382 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x31,
1383 0x81,0xd5,0x30,0x81,0xd2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,
1384 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1385 0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1386 0x0d,0x02,0x05,0x05,0x00,0xa0,0x5b,0x30,0x18,0x06,0x09,0x2a,0x86,0x48,0x86,
1387 0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1388 0x01,0x07,0x01,0x30,0x1e,0x06,0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,
1389 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
1390 0x4c,0x61,0x6e,0x67,0x00,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1391 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,
1392 0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
1393 0x40,0xbf,0x65,0xde,0x7a,0x3e,0xa2,0x19,0x59,0xc3,0xc7,0x02,0x53,0xc9,0x72,
1394 0xcd,0x74,0x96,0x70,0x0b,0x3b,0xcf,0x8b,0xd9,0x17,0x5c,0xc5,0xd1,0x83,0x41,
1395 0x32,0x93,0xa6,0xf3,0x52,0x83,0x94,0xa9,0x6b,0x0a,0x92,0xcf,0xaf,0x12,0xfa,
1396 0x40,0x53,0x12,0x84,0x03,0xab,0x10,0xa2,0x3d,0xe6,0x9f,0x5a,0xbf,0xc5,0xb8,
1397 0xff,0xc6,0x33,0x63,0x34 };
1398 static BYTE cert[] = {
1399 0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
1400 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1401 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1402 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1403 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
1404 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
1405 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,
1406 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
1407 0xff,0x02,0x01,0x01 };
1408 static BYTE v1CertWithPubKey[] = {
1409 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1410 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1411 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1412 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1413 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1414 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1415 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1416 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1417 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
1418 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
1419 0x01,0x01 };
1420 static const BYTE signedWithCertEmptyBareContent[] = {
1421 0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1422 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,0x30,0x7a,
1423 0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1424 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1425 0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
1426 0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1427 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
1428 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
1429 0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
1430 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
1431 0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,
1432 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,
1433 0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1434 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1435 static const BYTE signedWithCertBareContent[] = {
1436 0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1437 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1438 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1439 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1440 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1441 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1442 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1443 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1444 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1445 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1446 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1447 0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,
1448 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1449 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,
1450 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,
1451 0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,
1452 0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,
1453 0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,
1454 0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,
1455 0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1456 static BYTE crl[] = { 0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1457 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1458 0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
1459 0x30,0x30,0x30,0x30,0x5a };
1460 static const BYTE signedWithCrlEmptyBareContent[] = {
1461 0x30,0x81,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1462 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa1,0x2e,0x30,0x2c,
1463 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1464 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
1465 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,
1466 0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
1467 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
1468 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
1469 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1470 static const BYTE signedWithCrlBareContent[] = {
1471 0x30,0x81,0xd1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1472 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,
1473 0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa1,0x2e,
1474 0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
1475 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,
1476 0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,
1477 0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,
1478 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1479 0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1480 0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,
1481 0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,
1482 0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,
1483 0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,
1484 0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,
1485 0xa8,0x0d };
1486 static const BYTE signedWithCertAndCrlEmptyBareContent[] = {
1487 0x30,0x81,0xfe,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1488 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,0x30,0x7a,
1489 0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1490 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1491 0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
1492 0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1493 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
1494 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
1495 0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
1496 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
1497 0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1498 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1499 0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
1500 0x30,0x30,0x30,0x30,0x5a,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,
1501 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1502 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,
1503 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,
1504 0x04,0x00 };
1505 static const BYTE signedWithCertAndCrlBareContent[] = {
1506 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1507 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1508 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1509 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1510 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1511 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1512 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1513 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1514 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1515 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1516 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1517 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1518 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1519 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1520 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1521 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1522 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1523 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1524 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1525 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1526 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1527 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1528 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1529 static const BYTE signedWithCertWithPubKeyBareContent[] = {
1530 0x30,0x81,0xeb,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1531 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x81,0x98,0x30,
1532 0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
1533 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1534 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1535 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1536 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
1537 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
1538 0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
1539 0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
1540 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,
1541 0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,
1542 0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,
1543 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1544 0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1545 0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1546 static BYTE v1CertWithValidPubKey[] = {
1547 0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1548 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1549 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1550 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1551 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1552 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1553 0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1554 0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,
1555 0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,
1556 0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,
1557 0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,
1558 0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,
1559 0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
1560 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1561 static const BYTE signedWithCertWithValidPubKeyEmptyContent[] = {
1562 0x30,0x82,0x01,0x38,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
1563 0xa0,0x82,0x01,0x29,0x30,0x82,0x01,0x25,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
1564 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,
1565 0x00,0xa0,0x81,0xd2,0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1566 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1567 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1568 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1569 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1570 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1571 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1572 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,
1573 0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,
1574 0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,
1575 0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,
1576 0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
1577 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
1578 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
1579 0xff,0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,
1580 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1581 0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,
1582 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
1583 0x00 };
1584 static const BYTE signedWithCertWithValidPubKeyContent[] = {
1585 0x30,0x82,0x01,0x89,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
1586 0xa0,0x82,0x01,0x7a,0x30,0x82,0x01,0x76,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
1587 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
1588 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
1589 0x02,0x03,0x04,0xa0,0x81,0xd2,0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,
1590 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
1591 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1592 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
1593 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
1594 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
1595 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,
1596 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,
1597 0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,
1598 0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
1599 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,
1600 0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,
1601 0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,
1602 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
1603 0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
1604 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
1605 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
1606 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
1607 0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,
1608 0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,
1609 0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,
1610 0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,
1611 0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1613 static void test_signed_msg_encoding(void)
1615 HCRYPTMSG msg;
1616 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1617 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1618 CERT_INFO certInfo = { 0 };
1619 CERT_BLOB encodedCert = { sizeof(cert), cert };
1620 CRL_BLOB encodedCrl = { sizeof(crl), crl };
1621 char oid_common_name[] = szOID_COMMON_NAME;
1622 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
1623 encodedCommonName };
1624 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
1625 BOOL ret;
1626 HCRYPTKEY key;
1627 DWORD size;
1629 certInfo.SerialNumber.cbData = sizeof(serialNum);
1630 certInfo.SerialNumber.pbData = serialNum;
1631 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1632 certInfo.Issuer.pbData = encodedCommonName;
1633 signer.pCertInfo = &certInfo;
1634 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1635 signInfo.cSigners = 1;
1636 signInfo.rgSigners = &signer;
1638 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1639 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1640 if (!ret && GetLastError() == NTE_EXISTS) {
1641 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1642 PROV_RSA_FULL, 0);
1644 ok(ret, "CryptAcquireContext failed: 0x%x\n", GetLastError());
1646 if (!ret) {
1647 skip("No context for tests\n");
1648 return;
1651 ret = CryptImportKey(signer.hCryptProv, privKey, sizeof(privKey),
1652 0, 0, &key);
1653 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1655 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1656 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1657 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1659 check_param("detached signed empty bare content", msg,
1660 CMSG_BARE_CONTENT_PARAM, signedEmptyBareContent,
1661 sizeof(signedEmptyBareContent));
1662 check_param("detached signed empty content", msg, CMSG_CONTENT_PARAM,
1663 signedEmptyContent, sizeof(signedEmptyContent));
1664 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1665 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1666 check_param("detached signed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1667 signedHash, sizeof(signedHash));
1668 check_param("detached signed bare content", msg, CMSG_BARE_CONTENT_PARAM,
1669 detachedSignedBareContent, sizeof(detachedSignedBareContent));
1670 check_param("detached signed content", msg, CMSG_CONTENT_PARAM,
1671 detachedSignedContent, sizeof(detachedSignedContent));
1672 SetLastError(0xdeadbeef);
1673 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size);
1674 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1675 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1676 check_param("detached signed encoded signer", msg, CMSG_ENCODED_SIGNER,
1677 signedEncodedSigner, sizeof(signedEncodedSigner));
1679 CryptMsgClose(msg);
1681 certInfo.SerialNumber.cbData = 0;
1682 certInfo.Issuer.cbData = 0;
1683 signer.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
1684 U(signer.SignerId).KeyId.cbData = sizeof(serialNum);
1685 U(signer.SignerId).KeyId.pbData = serialNum;
1686 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1687 NULL, NULL);
1688 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1689 check_param("signed key id empty content", msg, CMSG_CONTENT_PARAM,
1690 signedKeyIdEmptyContent, sizeof(signedKeyIdEmptyContent));
1691 CryptMsgClose(msg);
1693 certInfo.SerialNumber.cbData = sizeof(serialNum);
1694 certInfo.SerialNumber.pbData = serialNum;
1695 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1696 certInfo.Issuer.pbData = encodedCommonName;
1697 signer.SignerId.dwIdChoice = 0;
1698 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1699 NULL, NULL);
1700 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1702 check_param("signed empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
1703 signedEmptyBareContent, sizeof(signedEmptyBareContent));
1704 check_param("signed empty content", msg, CMSG_CONTENT_PARAM,
1705 signedEmptyContent, sizeof(signedEmptyContent));
1706 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1707 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1708 check_param("signed bare content", msg, CMSG_BARE_CONTENT_PARAM,
1709 signedBareContent, sizeof(signedBareContent));
1710 check_param("signed content", msg, CMSG_CONTENT_PARAM,
1711 signedContent, sizeof(signedContent));
1713 CryptMsgClose(msg);
1715 signer.cAuthAttr = 1;
1716 signer.rgAuthAttr = &attr;
1717 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1718 NULL, NULL);
1719 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1721 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1722 check_param("signed with auth attrs bare content", msg,
1723 CMSG_BARE_CONTENT_PARAM, signedWithAuthAttrsBareContent,
1724 sizeof(signedWithAuthAttrsBareContent));
1726 CryptMsgClose(msg);
1728 signer.cAuthAttr = 0;
1729 signInfo.rgCertEncoded = &encodedCert;
1730 signInfo.cCertEncoded = 1;
1731 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1732 NULL, NULL);
1733 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1735 check_param("signed with cert empty bare content", msg,
1736 CMSG_BARE_CONTENT_PARAM, signedWithCertEmptyBareContent,
1737 sizeof(signedWithCertEmptyBareContent));
1738 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1739 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1740 check_param("signed with cert bare content", msg, CMSG_BARE_CONTENT_PARAM,
1741 signedWithCertBareContent, sizeof(signedWithCertBareContent));
1743 CryptMsgClose(msg);
1745 signInfo.cCertEncoded = 0;
1746 signInfo.rgCrlEncoded = &encodedCrl;
1747 signInfo.cCrlEncoded = 1;
1748 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1749 NULL, NULL);
1750 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1752 check_param("signed with crl empty bare content", msg,
1753 CMSG_BARE_CONTENT_PARAM, signedWithCrlEmptyBareContent,
1754 sizeof(signedWithCrlEmptyBareContent));
1755 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1756 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1757 check_param("signed with crl bare content", msg, CMSG_BARE_CONTENT_PARAM,
1758 signedWithCrlBareContent, sizeof(signedWithCrlBareContent));
1760 CryptMsgClose(msg);
1762 signInfo.cCertEncoded = 1;
1763 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1764 NULL, NULL);
1765 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1767 check_param("signed with cert and crl empty bare content", msg,
1768 CMSG_BARE_CONTENT_PARAM, signedWithCertAndCrlEmptyBareContent,
1769 sizeof(signedWithCertAndCrlEmptyBareContent));
1770 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1771 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1772 check_param("signed with cert and crl bare content", msg,
1773 CMSG_BARE_CONTENT_PARAM, signedWithCertAndCrlBareContent,
1774 sizeof(signedWithCertAndCrlBareContent));
1776 CryptMsgClose(msg);
1778 /* Test with a cert with a (bogus) public key */
1779 signInfo.cCrlEncoded = 0;
1780 encodedCert.cbData = sizeof(v1CertWithPubKey);
1781 encodedCert.pbData = v1CertWithPubKey;
1782 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1783 NULL, NULL);
1784 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1785 check_param("signedWithCertWithPubKeyBareContent", msg,
1786 CMSG_BARE_CONTENT_PARAM, signedWithCertWithPubKeyBareContent,
1787 sizeof(signedWithCertWithPubKeyBareContent));
1788 CryptMsgClose(msg);
1790 encodedCert.cbData = sizeof(v1CertWithValidPubKey);
1791 encodedCert.pbData = v1CertWithValidPubKey;
1792 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1793 NULL, NULL);
1794 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1795 check_param("signedWithCertWithValidPubKeyEmptyContent", msg,
1796 CMSG_CONTENT_PARAM, signedWithCertWithValidPubKeyEmptyContent,
1797 sizeof(signedWithCertWithValidPubKeyEmptyContent));
1798 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1799 check_param("signedWithCertWithValidPubKeyContent", msg,
1800 CMSG_CONTENT_PARAM, signedWithCertWithValidPubKeyContent,
1801 sizeof(signedWithCertWithValidPubKeyContent));
1802 CryptMsgClose(msg);
1804 CryptDestroyKey(key);
1805 CryptReleaseContext(signer.hCryptProv, 0);
1806 pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL, PROV_RSA_FULL,
1807 CRYPT_DELETEKEYSET);
1810 static void test_signed_msg_get_param(void)
1812 BOOL ret;
1813 HCRYPTMSG msg;
1814 DWORD size, value = 0;
1815 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1816 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1817 CERT_INFO certInfo = { 0 };
1819 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1820 NULL, NULL);
1821 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1823 /* Content and bare content are always gettable */
1824 size = 0;
1825 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
1826 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1827 size = 0;
1828 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
1829 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1830 /* For "signed" messages, so is the version. */
1831 size = 0;
1832 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
1833 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1834 size = sizeof(value);
1835 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, &value, &size);
1836 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1837 ok(value == CMSG_SIGNED_DATA_V1, "Expected version 1, got %d\n", value);
1838 /* But for this message, with no signers, the hash and signer aren't
1839 * available.
1841 size = 0;
1842 SetLastError(0xdeadbeef);
1843 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
1844 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1845 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1846 SetLastError(0xdeadbeef);
1847 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
1848 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1849 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1850 /* As usual, the type isn't available. */
1851 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
1852 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1853 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1855 CryptMsgClose(msg);
1857 certInfo.SerialNumber.cbData = sizeof(serialNum);
1858 certInfo.SerialNumber.pbData = serialNum;
1859 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1860 certInfo.Issuer.pbData = encodedCommonName;
1861 signer.pCertInfo = &certInfo;
1862 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1863 signInfo.cSigners = 1;
1864 signInfo.rgSigners = &signer;
1866 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1867 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1868 if (!ret && GetLastError() == NTE_EXISTS) {
1869 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1870 PROV_RSA_FULL, 0);
1872 ok(ret, "CryptAcquireContext failed: 0x%x\n", GetLastError());
1874 if (!ret) {
1875 skip("No context for tests\n");
1876 return;
1879 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1880 NULL, NULL);
1881 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1883 /* This message, with one signer, has the hash and signer for index 0
1884 * available, but not for other indexes.
1886 size = 0;
1887 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
1888 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
1889 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
1890 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
1891 size = 0;
1892 SetLastError(0xdeadbeef);
1893 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 1, NULL, &size);
1894 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1895 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1896 SetLastError(0xdeadbeef);
1897 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size);
1898 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1899 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1900 /* As usual, the type isn't available. */
1901 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
1902 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1903 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1905 CryptMsgClose(msg);
1907 /* Opening the message using the CMS fields.. */
1908 certInfo.SerialNumber.cbData = 0;
1909 certInfo.Issuer.cbData = 0;
1910 signer.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
1911 U(signer.SignerId).IssuerSerialNumber.Issuer.cbData =
1912 sizeof(encodedCommonName);
1913 U(signer.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonName;
1914 U(signer.SignerId).IssuerSerialNumber.SerialNumber.cbData =
1915 sizeof(serialNum);
1916 U(signer.SignerId).IssuerSerialNumber.SerialNumber.pbData = serialNum;
1917 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1918 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1919 if (!ret && GetLastError() == NTE_EXISTS)
1920 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1921 PROV_RSA_FULL, 0);
1922 ok(ret, "CryptAcquireContextA failed: %x\n", GetLastError());
1923 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1924 CMSG_CRYPT_RELEASE_CONTEXT_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1925 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1926 /* still results in the version being 1 when the issuer and serial number
1927 * are used and no additional CMS fields are used.
1929 size = sizeof(value);
1930 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, &value, &size);
1931 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1932 ok(value == CMSG_SIGNED_DATA_V1, "expected version 1, got %d\n", value);
1933 /* Apparently the encoded signer can be retrieved.. */
1934 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
1935 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1936 /* but the signer info, CMS signer info, and cert ID can't be. */
1937 SetLastError(0xdeadbeef);
1938 ret = CryptMsgGetParam(msg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &size);
1939 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1940 "expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1941 SetLastError(0xdeadbeef);
1942 ret = CryptMsgGetParam(msg, CMSG_CMS_SIGNER_INFO_PARAM, 0, NULL, &size);
1943 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1944 "expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1945 SetLastError(0xdeadbeef);
1946 ret = CryptMsgGetParam(msg, CMSG_SIGNER_CERT_ID_PARAM, 0, NULL, &size);
1947 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1948 "expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1949 CryptMsgClose(msg);
1951 /* Using the KeyId field of the SignerId results in the version becoming
1952 * the CMS version.
1954 signer.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
1955 U(signer.SignerId).KeyId.cbData = sizeof(serialNum);
1956 U(signer.SignerId).KeyId.pbData = serialNum;
1957 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1958 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1959 if (!ret && GetLastError() == NTE_EXISTS)
1960 ret = pCryptAcquireContextA(&signer.hCryptProv, cspNameA, NULL,
1961 PROV_RSA_FULL, 0);
1962 ok(ret, "CryptAcquireContextA failed: %x\n", GetLastError());
1963 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1964 CMSG_CRYPT_RELEASE_CONTEXT_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1965 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1966 size = sizeof(value);
1967 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, &value, &size);
1968 ok(value == CMSG_SIGNED_DATA_V3, "expected version 3, got %d\n", value);
1969 /* Even for a CMS message, the signer can be retrieved.. */
1970 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
1971 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1972 /* but the signer info, CMS signer info, and cert ID can't be. */
1973 SetLastError(0xdeadbeef);
1974 ret = CryptMsgGetParam(msg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &size);
1975 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1976 "expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1977 SetLastError(0xdeadbeef);
1978 ret = CryptMsgGetParam(msg, CMSG_CMS_SIGNER_INFO_PARAM, 0, NULL, &size);
1979 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1980 "expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1981 SetLastError(0xdeadbeef);
1982 ret = CryptMsgGetParam(msg, CMSG_SIGNER_CERT_ID_PARAM, 0, NULL, &size);
1983 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1984 "expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1985 CryptMsgClose(msg);
1987 CryptReleaseContext(signer.hCryptProv, 0);
1988 pCryptAcquireContextA(&signer.hCryptProv, cspNameA, MS_DEF_PROV_A,
1989 PROV_RSA_FULL, CRYPT_DELETEKEYSET);
1992 static void test_signed_msg(void)
1994 test_signed_msg_open();
1995 test_signed_msg_update();
1996 test_signed_msg_encoding();
1997 test_signed_msg_get_param();
2000 static CRYPT_DATA_BLOB b4 = { 0, NULL };
2001 static const struct update_accum a4 = { 1, &b4 };
2003 static const BYTE bogusOIDContent[] = {
2004 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
2005 0x04,0x00 };
2006 static const BYTE bogusHashContent[] = {
2007 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
2008 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
2009 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2010 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x00,0xd6,0xc0,
2011 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
2013 static void test_decode_msg_update(void)
2015 HCRYPTMSG msg;
2016 BOOL ret;
2017 CMSG_STREAM_INFO streamInfo = { 0 };
2018 DWORD i;
2019 struct update_accum accum = { 0, NULL };
2021 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2022 /* Update with a full message in a final update */
2023 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
2024 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
2025 /* Can't update after a final update */
2026 SetLastError(0xdeadbeef);
2027 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
2028 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
2029 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
2030 CryptMsgClose(msg);
2032 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2033 /* Can't send a non-final update without streaming */
2034 SetLastError(0xdeadbeef);
2035 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
2036 FALSE);
2037 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
2038 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
2039 /* A subsequent final update succeeds */
2040 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
2041 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
2042 CryptMsgClose(msg);
2044 if (have_nt)
2046 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
2047 /* Updating a message that has a NULL stream callback fails */
2048 SetLastError(0xdeadbeef);
2049 /* Crashes on some Win9x */
2050 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
2051 FALSE);
2052 todo_wine
2053 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
2054 GetLastError() == STATUS_ILLEGAL_INSTRUCTION /* WinME */),
2055 "Expected STATUS_ACCESS_VIOLATION or STATUS_ILLEGAL_INSTRUCTION, got %x\n",
2056 GetLastError());
2057 /* Changing the callback pointer after the fact yields the same error (so
2058 * the message must copy the stream info, not just store a pointer to it)
2060 streamInfo.pfnStreamOutput = nop_stream_output;
2061 SetLastError(0xdeadbeef);
2062 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
2063 FALSE);
2064 todo_wine
2065 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
2066 GetLastError() == STATUS_ILLEGAL_INSTRUCTION /* WinME */),
2067 "Expected STATUS_ACCESS_VIOLATION or STATUS_ILLEGAL_INSTRUCTION, got %x\n",
2068 GetLastError());
2069 CryptMsgClose(msg);
2072 /* Empty non-final updates are allowed when streaming.. */
2073 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
2074 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
2075 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
2076 /* but final updates aren't when not enough data has been received. */
2077 SetLastError(0xdeadbeef);
2078 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
2079 todo_wine
2080 ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
2081 "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
2082 CryptMsgClose(msg);
2084 /* Updating the message byte by byte is legal */
2085 streamInfo.pfnStreamOutput = accumulating_stream_output;
2086 streamInfo.pvArg = &accum;
2087 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
2088 for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
2089 ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
2090 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
2091 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
2092 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
2093 CryptMsgClose(msg);
2094 todo_wine
2095 check_updates("byte-by-byte empty content", &a4, &accum);
2096 free_updates(&accum);
2098 /* Decoding bogus content fails in non-streaming mode.. */
2099 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2100 SetLastError(0xdeadbeef);
2101 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
2102 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2103 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
2104 CryptMsgClose(msg);
2105 /* and as the final update in streaming mode.. */
2106 streamInfo.pfnStreamOutput = nop_stream_output;
2107 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
2108 SetLastError(0xdeadbeef);
2109 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
2110 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2111 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
2112 CryptMsgClose(msg);
2113 /* and even as a non-final update in streaming mode. */
2114 streamInfo.pfnStreamOutput = nop_stream_output;
2115 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
2116 SetLastError(0xdeadbeef);
2117 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
2118 todo_wine
2119 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2120 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
2121 CryptMsgClose(msg);
2123 /* An empty message can be opened with undetermined type.. */
2124 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2125 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
2126 TRUE);
2127 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
2128 CryptMsgClose(msg);
2129 /* but decoding it as an explicitly typed message fails. */
2130 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
2131 NULL);
2132 SetLastError(0xdeadbeef);
2133 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
2134 TRUE);
2135 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2136 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
2137 CryptMsgClose(msg);
2138 /* On the other hand, decoding the bare content of an empty message fails
2139 * with unspecified type..
2141 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2142 SetLastError(0xdeadbeef);
2143 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
2144 sizeof(dataEmptyBareContent), TRUE);
2145 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2146 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
2147 CryptMsgClose(msg);
2148 /* but succeeds with explicit type. */
2149 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
2150 NULL);
2151 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
2152 sizeof(dataEmptyBareContent), TRUE);
2153 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
2154 CryptMsgClose(msg);
2156 /* Decoding valid content with an unsupported OID fails */
2157 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2158 SetLastError(0xdeadbeef);
2159 ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
2160 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2161 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
2162 CryptMsgClose(msg);
2164 /* Similarly, opening an empty hash with unspecified type succeeds.. */
2165 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2166 SetLastError(0xdeadbeef);
2167 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
2168 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2169 CryptMsgClose(msg);
2170 /* while with specified type it fails. */
2171 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
2172 NULL);
2173 SetLastError(0xdeadbeef);
2174 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
2175 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2176 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
2177 CryptMsgClose(msg);
2178 /* On the other hand, decoding the bare content of an empty hash message
2179 * fails with unspecified type..
2181 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2182 SetLastError(0xdeadbeef);
2183 ret = CryptMsgUpdate(msg, hashEmptyBareContent,
2184 sizeof(hashEmptyBareContent), TRUE);
2185 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2186 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
2187 CryptMsgClose(msg);
2188 /* but succeeds with explicit type. */
2189 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
2190 NULL);
2191 ret = CryptMsgUpdate(msg, hashEmptyBareContent,
2192 sizeof(hashEmptyBareContent), TRUE);
2193 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
2194 CryptMsgClose(msg);
2196 /* And again, opening a (non-empty) hash message with unspecified type
2197 * succeeds..
2199 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2200 SetLastError(0xdeadbeef);
2201 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
2202 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2203 CryptMsgClose(msg);
2204 /* while with specified type it fails.. */
2205 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
2206 NULL);
2207 SetLastError(0xdeadbeef);
2208 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
2209 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2210 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
2211 CryptMsgClose(msg);
2212 /* and decoding the bare content of a non-empty hash message fails with
2213 * unspecified type..
2215 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2216 SetLastError(0xdeadbeef);
2217 ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
2218 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2219 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
2220 CryptMsgClose(msg);
2221 /* but succeeds with explicit type. */
2222 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
2223 NULL);
2224 ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
2225 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
2226 CryptMsgClose(msg);
2228 /* Opening a (non-empty) hash message with unspecified type and a bogus
2229 * hash value succeeds..
2231 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2232 SetLastError(0xdeadbeef);
2233 ret = CryptMsgUpdate(msg, bogusHashContent, sizeof(bogusHashContent), TRUE);
2234 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2235 CryptMsgClose(msg);
2237 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2238 ret = CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
2239 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2240 CryptMsgClose(msg);
2241 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2242 SetLastError(0xdeadbeef);
2243 ret = CryptMsgUpdate(msg, signedWithCertAndCrlBareContent,
2244 sizeof(signedWithCertAndCrlBareContent), TRUE);
2245 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2246 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
2247 CryptMsgClose(msg);
2248 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
2249 NULL);
2250 ret = CryptMsgUpdate(msg, signedWithCertAndCrlBareContent,
2251 sizeof(signedWithCertAndCrlBareContent), TRUE);
2252 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2253 CryptMsgClose(msg);
2255 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, 0, 0,
2256 NULL, NULL);
2257 /* The first update succeeds.. */
2258 ret = CryptMsgUpdate(msg, detachedSignedContent,
2259 sizeof(detachedSignedContent), TRUE);
2260 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2261 /* as does a second (probably to update the detached portion).. */
2262 ret = CryptMsgUpdate(msg, detachedSignedContent,
2263 sizeof(detachedSignedContent), TRUE);
2264 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2265 /* while a third fails. */
2266 ret = CryptMsgUpdate(msg, detachedSignedContent,
2267 sizeof(detachedSignedContent), TRUE);
2268 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
2269 "expected CRYPT_E_MSG_ERROR, got %08x\n", GetLastError());
2270 CryptMsgClose(msg);
2272 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, 0, 0, NULL, &streamInfo);
2273 ret = CryptMsgUpdate(msg, detachedSignedContent, sizeof(detachedSignedContent), FALSE);
2274 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2275 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
2276 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2277 ret = CryptMsgUpdate(msg, detachedSignedContent, sizeof(detachedSignedContent), FALSE);
2278 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2279 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
2280 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2282 ret = CryptMsgUpdate(msg, detachedSignedContent, sizeof(detachedSignedContent), TRUE);
2283 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
2284 "expected CRYPT_E_MSG_ERROR, got %08x\n", GetLastError());
2285 CryptMsgClose(msg);
2288 static const BYTE hashParam[] = { 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,
2289 0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
2291 static void compare_signer_info(const CMSG_SIGNER_INFO *got,
2292 const CMSG_SIGNER_INFO *expected)
2294 ok(got->dwVersion == expected->dwVersion, "Expected version %d, got %d\n",
2295 expected->dwVersion, got->dwVersion);
2296 ok(got->Issuer.cbData == expected->Issuer.cbData,
2297 "Expected issuer size %d, got %d\n", expected->Issuer.cbData,
2298 got->Issuer.cbData);
2299 ok(!memcmp(got->Issuer.pbData, got->Issuer.pbData, got->Issuer.cbData),
2300 "Unexpected issuer\n");
2301 ok(got->SerialNumber.cbData == expected->SerialNumber.cbData,
2302 "Expected serial number size %d, got %d\n", expected->SerialNumber.cbData,
2303 got->SerialNumber.cbData);
2304 ok(!memcmp(got->SerialNumber.pbData, got->SerialNumber.pbData,
2305 got->SerialNumber.cbData), "Unexpected serial number\n");
2306 /* FIXME: check more things */
2309 static void compare_cms_signer_info(const CMSG_CMS_SIGNER_INFO *got,
2310 const CMSG_CMS_SIGNER_INFO *expected)
2312 ok(got->dwVersion == expected->dwVersion, "Expected version %d, got %d\n",
2313 expected->dwVersion, got->dwVersion);
2314 ok(got->SignerId.dwIdChoice == expected->SignerId.dwIdChoice,
2315 "Expected id choice %d, got %d\n", expected->SignerId.dwIdChoice,
2316 got->SignerId.dwIdChoice);
2317 if (got->SignerId.dwIdChoice == expected->SignerId.dwIdChoice)
2319 if (got->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
2321 ok(U(got->SignerId).IssuerSerialNumber.Issuer.cbData ==
2322 U(expected->SignerId).IssuerSerialNumber.Issuer.cbData,
2323 "Expected issuer size %d, got %d\n",
2324 U(expected->SignerId).IssuerSerialNumber.Issuer.cbData,
2325 U(got->SignerId).IssuerSerialNumber.Issuer.cbData);
2326 ok(!memcmp(U(got->SignerId).IssuerSerialNumber.Issuer.pbData,
2327 U(expected->SignerId).IssuerSerialNumber.Issuer.pbData,
2328 U(got->SignerId).IssuerSerialNumber.Issuer.cbData),
2329 "Unexpected issuer\n");
2330 ok(U(got->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
2331 U(expected->SignerId).IssuerSerialNumber.SerialNumber.cbData,
2332 "Expected serial number size %d, got %d\n",
2333 U(expected->SignerId).IssuerSerialNumber.SerialNumber.cbData,
2334 U(got->SignerId).IssuerSerialNumber.SerialNumber.cbData);
2335 ok(!memcmp(U(got->SignerId).IssuerSerialNumber.SerialNumber.pbData,
2336 U(expected->SignerId).IssuerSerialNumber.SerialNumber.pbData,
2337 U(got->SignerId).IssuerSerialNumber.SerialNumber.cbData),
2338 "Unexpected serial number\n");
2340 else
2342 ok(U(got->SignerId).KeyId.cbData == U(expected->SignerId).KeyId.cbData,
2343 "expected key id size %d, got %d\n",
2344 U(expected->SignerId).KeyId.cbData, U(got->SignerId).KeyId.cbData);
2345 ok(!memcmp(U(expected->SignerId).KeyId.pbData,
2346 U(got->SignerId).KeyId.pbData, U(got->SignerId).KeyId.cbData),
2347 "unexpected key id\n");
2350 /* FIXME: check more things */
2353 static const BYTE signedWithCertAndCrlComputedHash[] = {
2354 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,
2355 0x2f };
2356 static BYTE keyIdIssuer[] = {
2357 0x30,0x13,0x31,0x11,0x30,0x0f,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,
2358 0x0a,0x07,0x01,0x04,0x01,0x01 };
2360 static void test_decode_msg_get_param(void)
2362 HCRYPTMSG msg;
2363 BOOL ret;
2364 DWORD size = 0, value;
2365 LPBYTE buf;
2367 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2368 SetLastError(0xdeadbeef);
2369 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
2370 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2371 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
2372 ret = CryptMsgUpdate(msg, dataContent, sizeof(dataContent), TRUE);
2373 check_param("data content", msg, CMSG_CONTENT_PARAM, msgData,
2374 sizeof(msgData));
2375 CryptMsgClose(msg);
2377 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2378 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
2379 if (ret)
2381 /* Crashes on some Win9x */
2382 check_param("empty hash content", msg, CMSG_CONTENT_PARAM, NULL, 0);
2383 check_param("empty hash hash data", msg, CMSG_HASH_DATA_PARAM, NULL, 0);
2384 check_param("empty hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
2385 emptyHashParam, sizeof(emptyHashParam));
2387 CryptMsgClose(msg);
2388 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2389 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
2390 check_param("hash content", msg, CMSG_CONTENT_PARAM, msgData,
2391 sizeof(msgData));
2392 check_param("hash hash data", msg, CMSG_HASH_DATA_PARAM, hashParam,
2393 sizeof(hashParam));
2394 check_param("hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
2395 hashParam, sizeof(hashParam));
2396 /* Curiously, getting the hash of index 1 succeeds, even though there's
2397 * only one hash.
2399 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size);
2400 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2401 buf = CryptMemAlloc(size);
2402 if (buf)
2404 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, buf, &size);
2405 ok(size == sizeof(hashParam), "Unexpected size %d\n", size);
2406 ok(!memcmp(buf, hashParam, size), "Unexpected value\n");
2407 CryptMemFree(buf);
2409 check_param("hash inner OID", msg, CMSG_INNER_CONTENT_TYPE_PARAM,
2410 (const BYTE *)szOID_RSA_data, strlen(szOID_RSA_data) + 1);
2411 value = CMSG_HASHED_DATA_V0;
2412 check_param("hash version", msg, CMSG_VERSION_PARAM, (const BYTE *)&value,
2413 sizeof(value));
2414 CryptMsgClose(msg);
2416 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2417 ret = CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
2418 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2419 check_param("signed content", msg, CMSG_CONTENT_PARAM, msgData,
2420 sizeof(msgData));
2421 check_param("inner content", msg, CMSG_INNER_CONTENT_TYPE_PARAM,
2422 (const BYTE *)szOID_RSA_data, strlen(szOID_RSA_data) + 1);
2423 size = sizeof(value);
2424 value = 2112;
2425 ret = CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &value, &size);
2426 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2427 ok(value == 1, "Expected 1 signer, got %d\n", value);
2428 size = 0;
2429 ret = CryptMsgGetParam(msg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &size);
2430 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2431 if (ret)
2432 buf = CryptMemAlloc(size);
2433 else
2434 buf = NULL;
2435 if (buf)
2437 CMSG_SIGNER_INFO signer = { 0 };
2439 signer.dwVersion = 1;
2440 signer.Issuer.cbData = sizeof(encodedCommonName);
2441 signer.Issuer.pbData = encodedCommonName;
2442 signer.SerialNumber.cbData = sizeof(serialNum);
2443 signer.SerialNumber.pbData = serialNum;
2444 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
2445 CryptMsgGetParam(msg, CMSG_SIGNER_INFO_PARAM, 0, buf, &size);
2446 compare_signer_info((CMSG_SIGNER_INFO *)buf, &signer);
2447 CryptMemFree(buf);
2449 /* Getting the CMS signer info of a PKCS7 message is possible. */
2450 size = 0;
2451 ret = CryptMsgGetParam(msg, CMSG_CMS_SIGNER_INFO_PARAM, 0, NULL, &size);
2452 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2453 if (ret)
2454 buf = CryptMemAlloc(size);
2455 else
2456 buf = NULL;
2457 if (buf)
2459 CMSG_CMS_SIGNER_INFO signer = { 0 };
2461 signer.dwVersion = 1;
2462 signer.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
2463 U(signer.SignerId).IssuerSerialNumber.Issuer.cbData =
2464 sizeof(encodedCommonName);
2465 U(signer.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonName;
2466 U(signer.SignerId).IssuerSerialNumber.SerialNumber.cbData =
2467 sizeof(serialNum);
2468 U(signer.SignerId).IssuerSerialNumber.SerialNumber.pbData = serialNum;
2469 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
2470 CryptMsgGetParam(msg, CMSG_CMS_SIGNER_INFO_PARAM, 0, buf, &size);
2471 compare_cms_signer_info((CMSG_CMS_SIGNER_INFO *)buf, &signer);
2472 CryptMemFree(buf);
2474 /* index is ignored when getting signer count */
2475 size = sizeof(value);
2476 ret = CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 1, &value, &size);
2477 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2478 ok(value == 1, "Expected 1 signer, got %d\n", value);
2479 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &value, &size);
2480 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2481 ok(value == 0, "Expected 0 certs, got %d\n", value);
2482 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &value, &size);
2483 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2484 ok(value == 0, "Expected 0 CRLs, got %d\n", value);
2485 CryptMsgClose(msg);
2486 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
2487 NULL);
2488 ret = CryptMsgUpdate(msg, signedWithCertAndCrlBareContent,
2489 sizeof(signedWithCertAndCrlBareContent), TRUE);
2490 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2491 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &value, &size);
2492 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2493 ok(value == 1, "Expected 1 cert, got %d\n", value);
2494 check_param("cert", msg, CMSG_CERT_PARAM, cert, sizeof(cert));
2495 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &value, &size);
2496 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2497 ok(value == 1, "Expected 1 CRL, got %d\n", value);
2498 check_param("crl", msg, CMSG_CRL_PARAM, crl, sizeof(crl));
2499 check_param("signed with cert and CRL computed hash", msg,
2500 CMSG_COMPUTED_HASH_PARAM, signedWithCertAndCrlComputedHash,
2501 sizeof(signedWithCertAndCrlComputedHash));
2502 CryptMsgClose(msg);
2504 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2505 ret = CryptMsgUpdate(msg, signedKeyIdEmptyContent,
2506 sizeof(signedKeyIdEmptyContent), TRUE);
2507 if (!ret && GetLastError() == OSS_DATA_ERROR)
2509 /* Subsequent tests crashes on some Win9x, so bail out */
2510 CryptMsgClose(msg);
2511 return;
2513 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2514 size = sizeof(value);
2515 ret = CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &value, &size);
2516 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2517 ok(value == 1, "Expected 1 signer, got %d\n", value);
2518 /* Getting the regular (non-CMS) signer info from a CMS message is also
2519 * possible..
2521 size = 0;
2522 ret = CryptMsgGetParam(msg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &size);
2523 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2524 if (ret)
2525 buf = CryptMemAlloc(size);
2526 else
2527 buf = NULL;
2528 if (buf)
2530 CMSG_SIGNER_INFO signer;
2531 BYTE zero = 0;
2533 /* and here's the little oddity: for a CMS message using the key id
2534 * variant of a SignerId, retrieving the CMSG_SIGNER_INFO param yields
2535 * a signer with a zero (not empty) serial number, and whose issuer is
2536 * an RDN with OID szOID_KEYID_RDN, value type CERT_RDN_OCTET_STRING,
2537 * and value of the key id.
2539 signer.dwVersion = CMSG_SIGNED_DATA_V3;
2540 signer.Issuer.cbData = sizeof(keyIdIssuer);
2541 signer.Issuer.pbData = keyIdIssuer;
2542 signer.SerialNumber.cbData = 1;
2543 signer.SerialNumber.pbData = &zero;
2544 CryptMsgGetParam(msg, CMSG_SIGNER_INFO_PARAM, 0, buf, &size);
2545 compare_signer_info((CMSG_SIGNER_INFO *)buf, &signer);
2546 CryptMemFree(buf);
2548 size = 0;
2549 ret = CryptMsgGetParam(msg, CMSG_CMS_SIGNER_INFO_PARAM, 0, NULL, &size);
2550 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2551 if (ret)
2552 buf = CryptMemAlloc(size);
2553 else
2554 buf = NULL;
2555 if (buf)
2557 CMSG_CMS_SIGNER_INFO signer = { 0 };
2559 signer.dwVersion = CMSG_SIGNED_DATA_V3;
2560 signer.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
2561 U(signer.SignerId).KeyId.cbData = sizeof(serialNum);
2562 U(signer.SignerId).KeyId.pbData = serialNum;
2563 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
2564 CryptMsgGetParam(msg, CMSG_CMS_SIGNER_INFO_PARAM, 0, buf, &size);
2565 compare_cms_signer_info((CMSG_CMS_SIGNER_INFO *)buf, &signer);
2566 CryptMemFree(buf);
2568 CryptMsgClose(msg);
2571 static void test_decode_msg(void)
2573 test_decode_msg_update();
2574 test_decode_msg_get_param();
2577 static BYTE aKey[] = { 0,1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf };
2578 /* aKey encoded as a X509_PUBLIC_KEY_INFO */
2579 static BYTE encodedPubKey[] = {
2580 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,
2581 0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
2582 0x0d,0x0e,0x0f };
2583 /* a weird modulus encoded as RSA_CSP_PUBLICKEYBLOB */
2584 static BYTE mod_encoded[] = {
2585 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,
2586 0x01,0x00,0x01 };
2588 static void test_msg_control(void)
2590 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2591 BOOL ret;
2592 HCRYPTMSG msg;
2593 DWORD i;
2594 CERT_INFO certInfo = { 0 };
2595 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
2596 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
2597 CMSG_CTRL_DECRYPT_PARA decryptPara = { sizeof(decryptPara), 0 };
2599 /* Crashes
2600 ret = CryptMsgControl(NULL, 0, 0, NULL);
2603 /* Data encode messages don't allow any sort of control.. */
2604 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
2605 NULL);
2606 /* either with no prior update.. */
2607 for (i = 1; have_nt && (i <= CMSG_CTRL_ADD_CMS_SIGNER_INFO); i++)
2609 SetLastError(0xdeadbeef);
2610 ret = CryptMsgControl(msg, 0, i, NULL);
2611 ok(!ret && GetLastError() == E_INVALIDARG,
2612 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2614 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
2615 /* or after an update. */
2616 for (i = 1; have_nt && (i <= CMSG_CTRL_ADD_CMS_SIGNER_INFO); i++)
2618 SetLastError(0xdeadbeef);
2619 ret = CryptMsgControl(msg, 0, i, NULL);
2620 ok(!ret && GetLastError() == E_INVALIDARG,
2621 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2623 CryptMsgClose(msg);
2625 /* Hash encode messages don't allow any sort of control.. */
2626 hashInfo.cbSize = sizeof(hashInfo);
2627 hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
2628 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
2629 NULL, NULL);
2630 /* either with no prior update.. */
2631 for (i = 1; have_nt && (i <= CMSG_CTRL_ADD_CMS_SIGNER_INFO); i++)
2633 SetLastError(0xdeadbeef);
2634 ret = CryptMsgControl(msg, 0, i, NULL);
2635 ok(!ret && GetLastError() == E_INVALIDARG,
2636 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2638 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
2639 /* or after an update. */
2640 for (i = 1; have_nt && (i <= CMSG_CTRL_ADD_CMS_SIGNER_INFO); i++)
2642 SetLastError(0xdeadbeef);
2643 ret = CryptMsgControl(msg, 0, i, NULL);
2644 ok(!ret && GetLastError() == E_INVALIDARG,
2645 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2647 CryptMsgClose(msg);
2649 /* Signed encode messages likewise don't allow any sort of control.. */
2650 signInfo.cbSize = sizeof(signInfo);
2651 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
2652 NULL, NULL);
2653 /* either before an update.. */
2654 for (i = 1; have_nt && (i <= CMSG_CTRL_ADD_CMS_SIGNER_INFO); i++)
2656 SetLastError(0xdeadbeef);
2657 ret = CryptMsgControl(msg, 0, i, NULL);
2658 ok(!ret && GetLastError() == E_INVALIDARG,
2659 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2661 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
2662 /* or after an update. */
2663 for (i = 1; have_nt && (i <= CMSG_CTRL_ADD_CMS_SIGNER_INFO); i++)
2665 SetLastError(0xdeadbeef);
2666 ret = CryptMsgControl(msg, 0, i, NULL);
2667 ok(!ret && GetLastError() == E_INVALIDARG,
2668 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2670 CryptMsgClose(msg);
2672 /* Decode messages behave a bit differently. */
2673 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2674 /* Bad control type */
2675 SetLastError(0xdeadbeef);
2676 ret = CryptMsgControl(msg, 0, 0, NULL);
2677 ok(!ret && GetLastError() == CRYPT_E_CONTROL_TYPE,
2678 "Expected CRYPT_E_CONTROL_TYPE, got %08x\n", GetLastError());
2679 SetLastError(0xdeadbeef);
2680 ret = CryptMsgControl(msg, 1, 0, NULL);
2681 ok(!ret && GetLastError() == CRYPT_E_CONTROL_TYPE,
2682 "Expected CRYPT_E_CONTROL_TYPE, got %08x\n", GetLastError());
2683 /* Can't verify the hash of an indeterminate-type message */
2684 SetLastError(0xdeadbeef);
2685 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
2686 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2687 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
2688 /* Crashes
2689 ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, NULL);
2691 /* Can't decrypt an indeterminate-type message */
2692 ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
2693 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2694 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
2695 CryptMsgClose(msg);
2697 if (have_nt)
2699 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
2700 NULL);
2701 /* Can't verify the hash of an empty message */
2702 SetLastError(0xdeadbeef);
2703 /* Crashes on some Win9x */
2704 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
2705 todo_wine
2706 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2707 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2708 /* Crashes
2709 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, NULL);
2711 /* Can't verify the signature of a hash message */
2712 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2713 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2714 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
2715 CryptMsgUpdate(msg, hashEmptyBareContent, sizeof(hashEmptyBareContent),
2716 TRUE);
2717 /* Oddly enough, this fails, crashes on some Win9x */
2718 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
2719 ok(!ret, "Expected failure\n");
2720 CryptMsgClose(msg);
2722 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
2723 NULL);
2724 CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
2725 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
2726 ok(ret, "CryptMsgControl failed: %08x\n", GetLastError());
2727 /* Can't decrypt an indeterminate-type message */
2728 SetLastError(0xdeadbeef);
2729 ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
2730 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2731 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
2732 CryptMsgClose(msg);
2734 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, 0, 0,
2735 NULL, NULL);
2736 /* Can't verify the hash of a detached message before it's been updated. */
2737 SetLastError(0xdeadbeef);
2738 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
2739 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2740 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
2741 ret = CryptMsgUpdate(msg, detachedHashContent, sizeof(detachedHashContent),
2742 TRUE);
2743 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2744 /* Still can't verify the hash of a detached message with the content
2745 * of the detached hash given..
2747 SetLastError(0xdeadbeef);
2748 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
2749 ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
2750 "Expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
2751 /* and giving the content of the message after attempting to verify the
2752 * hash fails.
2754 SetLastError(0xdeadbeef);
2755 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
2756 todo_wine
2757 ok(!ret &&
2758 (GetLastError() == NTE_BAD_HASH_STATE ||
2759 GetLastError() == NTE_BAD_ALGID || /* Win9x */
2760 GetLastError() == CRYPT_E_MSG_ERROR), /* Vista */
2761 "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID or CRYPT_E_MSG_ERROR, "
2762 "got %08x\n", GetLastError());
2763 CryptMsgClose(msg);
2765 /* Finally, verifying the hash of a detached message in the correct order:
2766 * 1. Update with the detached hash message
2767 * 2. Update with the content of the message
2768 * 3. Verifying the hash of the message
2769 * succeeds.
2771 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, 0, 0,
2772 NULL, NULL);
2773 ret = CryptMsgUpdate(msg, detachedHashContent, sizeof(detachedHashContent),
2774 TRUE);
2775 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2776 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
2777 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2778 SetLastError(0xdeadbeef);
2779 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
2780 ok(ret, "CryptMsgControl failed: %08x\n", GetLastError());
2781 CryptMsgClose(msg);
2783 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
2784 NULL);
2785 /* Can't verify the hash of a signed message */
2786 SetLastError(0xdeadbeef);
2787 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
2788 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2789 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
2790 /* Can't decrypt a signed message */
2791 SetLastError(0xdeadbeef);
2792 ret = CryptMsgControl(msg, 0, CMSG_CTRL_DECRYPT, &decryptPara);
2793 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2794 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
2795 /* Crash
2796 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, NULL);
2797 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2799 CryptMsgUpdate(msg, signedWithCertBareContent,
2800 sizeof(signedWithCertBareContent), TRUE);
2801 /* With an empty cert info, the signer can't be found in the message (and
2802 * the signature can't be verified.
2804 SetLastError(0xdeadbeef);
2805 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2806 ok(!ret && (GetLastError() == CRYPT_E_SIGNER_NOT_FOUND ||
2807 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2808 "Expected CRYPT_E_SIGNER_NOT_FOUND or OSS_DATA_ERROR, got %08x\n",
2809 GetLastError());
2810 /* The cert info is expected to have an issuer, serial number, and public
2811 * key info set.
2813 certInfo.SerialNumber.cbData = sizeof(serialNum);
2814 certInfo.SerialNumber.pbData = serialNum;
2815 certInfo.Issuer.cbData = sizeof(encodedCommonName);
2816 certInfo.Issuer.pbData = encodedCommonName;
2817 SetLastError(0xdeadbeef);
2818 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2819 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2820 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2821 "Expected CRYPT_E_ASN1_EOD or OSS_DATA_ERROR, got %08x\n", GetLastError());
2822 CryptMsgClose(msg);
2823 /* This cert has a public key, but it's not in a usable form */
2824 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
2825 NULL);
2826 ret = CryptMsgUpdate(msg, signedWithCertWithPubKeyBareContent,
2827 sizeof(signedWithCertWithPubKeyBareContent), TRUE);
2828 if (ret)
2830 /* Crashes on some Win9x */
2831 /* Again, cert info needs to have a public key set */
2832 SetLastError(0xdeadbeef);
2833 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2834 ok(!ret &&
2835 (GetLastError() == CRYPT_E_ASN1_EOD ||
2836 GetLastError() == TRUST_E_NOSIGNATURE /* Vista */),
2837 "Expected CRYPT_E_ASN1_EOD or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError());
2838 /* The public key is supposed to be in encoded form.. */
2839 certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2840 certInfo.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2841 certInfo.SubjectPublicKeyInfo.PublicKey.pbData = aKey;
2842 SetLastError(0xdeadbeef);
2843 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2844 ok(!ret &&
2845 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
2846 GetLastError() == TRUST_E_NOSIGNATURE /* Vista */),
2847 "Expected CRYPT_E_ASN1_BADTAG or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError());
2848 /* but not as a X509_PUBLIC_KEY_INFO.. */
2849 certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2850 certInfo.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(encodedPubKey);
2851 certInfo.SubjectPublicKeyInfo.PublicKey.pbData = encodedPubKey;
2852 SetLastError(0xdeadbeef);
2853 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2854 ok(!ret &&
2855 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
2856 GetLastError() == TRUST_E_NOSIGNATURE /* Vista */),
2857 "Expected CRYPT_E_ASN1_BADTAG or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError());
2858 /* This decodes successfully, but it doesn't match any key in the message */
2859 certInfo.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(mod_encoded);
2860 certInfo.SubjectPublicKeyInfo.PublicKey.pbData = mod_encoded;
2861 SetLastError(0xdeadbeef);
2862 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2863 /* In Wine's rsaenh, this fails to decode because the key length is too
2864 * small. Not sure if that's a bug in rsaenh, so leaving todo_wine for
2865 * now.
2867 todo_wine
2868 ok(!ret &&
2869 (GetLastError() == NTE_BAD_SIGNATURE ||
2870 GetLastError() == TRUST_E_NOSIGNATURE /* Vista */),
2871 "Expected NTE_BAD_SIGNATURE or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError());
2873 CryptMsgClose(msg);
2874 /* A message with no data doesn't have a valid signature */
2875 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2876 ret = CryptMsgUpdate(msg, signedWithCertWithValidPubKeyEmptyContent,
2877 sizeof(signedWithCertWithValidPubKeyEmptyContent), TRUE);
2878 if (ret)
2880 certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2881 certInfo.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(pubKey);
2882 certInfo.SubjectPublicKeyInfo.PublicKey.pbData = pubKey;
2883 SetLastError(0xdeadbeef);
2884 /* Crashes on some Win9x */
2885 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2886 ok(!ret &&
2887 (GetLastError() == NTE_BAD_SIGNATURE ||
2888 GetLastError() == TRUST_E_NOSIGNATURE /* Vista */),
2889 "Expected NTE_BAD_SIGNATURE or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError());
2891 CryptMsgClose(msg);
2892 /* Finally, this succeeds */
2893 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2894 CryptMsgUpdate(msg, signedWithCertWithValidPubKeyContent,
2895 sizeof(signedWithCertWithValidPubKeyContent), TRUE);
2896 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2897 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
2898 "CryptMsgControl failed: %08x\n", GetLastError());
2899 CryptMsgClose(msg);
2901 /* Test verifying signature of a detached signed message */
2902 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, 0, 0,
2903 NULL, NULL);
2904 ret = CryptMsgUpdate(msg, detachedSignedContent,
2905 sizeof(detachedSignedContent), TRUE);
2906 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2907 /* Can't verify the sig without having updated the data */
2908 SetLastError(0xdeadbeef);
2909 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2910 ok(!ret && (GetLastError() == NTE_BAD_SIGNATURE ||
2911 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2912 "expected NTE_BAD_SIGNATURE or OSS_DATA_ERROR, got %08x\n",
2913 GetLastError());
2914 /* Now that the signature's been checked, can't do the final update */
2915 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
2916 todo_wine
2917 ok(!ret &&
2918 (GetLastError() == NTE_BAD_HASH_STATE ||
2919 GetLastError() == NTE_BAD_ALGID || /* Win9x */
2920 GetLastError() == CRYPT_E_MSG_ERROR), /* Vista */
2921 "expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID or CRYPT_E_MSG_ERROR, "
2922 "got %08x\n", GetLastError());
2923 CryptMsgClose(msg);
2924 /* Updating with the detached portion of the message and the data of the
2925 * the message allows the sig to be verified.
2927 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, 0, 0,
2928 NULL, NULL);
2929 ret = CryptMsgUpdate(msg, detachedSignedContent,
2930 sizeof(detachedSignedContent), TRUE);
2931 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2932 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
2933 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2934 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
2935 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
2936 "CryptMsgControl failed: %08x\n", GetLastError());
2937 CryptMsgClose(msg);
2940 /* win9x has much less parameter checks and will crash on many tests
2941 * this code is from test_signed_msg_update()
2943 static BOOL detect_nt(void)
2945 BOOL ret;
2946 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
2947 CERT_INFO certInfo = { 0 };
2949 if (!pCryptAcquireContextW)
2950 return FALSE;
2952 certInfo.SerialNumber.cbData = sizeof(serialNum);
2953 certInfo.SerialNumber.pbData = serialNum;
2954 certInfo.Issuer.cbData = sizeof(encodedCommonName);
2955 certInfo.Issuer.pbData = encodedCommonName;
2956 signer.pCertInfo = &certInfo;
2957 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
2959 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
2960 PROV_RSA_FULL, CRYPT_NEWKEYSET);
2961 if (!ret && GetLastError() == NTE_EXISTS) {
2962 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
2963 PROV_RSA_FULL, 0);
2966 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) return FALSE;
2968 /* cleanup */
2969 CryptReleaseContext(signer.hCryptProv, 0);
2970 pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL, PROV_RSA_FULL,
2971 CRYPT_DELETEKEYSET);
2973 return TRUE;
2976 static void test_msg_get_and_verify_signer(void)
2978 BOOL ret;
2979 HCRYPTMSG msg;
2980 PCCERT_CONTEXT signer;
2981 DWORD signerIndex;
2982 HCERTSTORE store;
2984 /* Crash */
2985 if (0)
2987 ret = CryptMsgGetAndVerifySigner(NULL, 0, NULL, 0, NULL, NULL);
2988 ret = CryptMsgGetAndVerifySigner(NULL, 0, NULL, 0, NULL, &signerIndex);
2991 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
2992 /* An empty message has no signer */
2993 SetLastError(0xdeadbeef);
2994 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL);
2995 ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
2996 "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
2997 /* The signer is cleared on error */
2998 signer = (PCCERT_CONTEXT)0xdeadbeef;
2999 SetLastError(0xdeadbeef);
3000 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, &signer, NULL);
3001 ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
3002 "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
3003 ok(!signer, "expected signer to be NULL\n");
3004 /* The signer index is also cleared on error */
3005 signerIndex = 0xdeadbeef;
3006 SetLastError(0xdeadbeef);
3007 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, &signerIndex);
3008 ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
3009 "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
3010 ok(!signerIndex, "expected 0, got %d\n", signerIndex);
3011 /* An unsigned message (msgData isn't a signed message at all)
3012 * likewise has no signer.
3014 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
3015 SetLastError(0xdeadbeef);
3016 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL);
3017 ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
3018 "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
3019 CryptMsgClose(msg);
3021 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
3022 /* A "signed" message created with no signer cert likewise has no signer */
3023 ret = CryptMsgUpdate(msg, signedEmptyContent, sizeof(signedEmptyContent), TRUE);
3024 if (ret)
3026 /* Crashes on most Win9x */
3027 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL);
3028 ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
3029 "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
3031 CryptMsgClose(msg);
3033 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
3034 /* A signed message succeeds, .. */
3035 CryptMsgUpdate(msg, signedWithCertWithValidPubKeyContent,
3036 sizeof(signedWithCertWithValidPubKeyContent), TRUE);
3037 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL);
3038 ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError());
3039 /* the signer index can be retrieved, .. */
3040 signerIndex = 0xdeadbeef;
3041 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, &signerIndex);
3042 ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError());
3043 ok(signerIndex == 0, "expected 0, got %d\n", signerIndex);
3044 /* as can the signer cert. */
3045 signer = (PCCERT_CONTEXT)0xdeadbeef;
3046 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, &signer, NULL);
3047 ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError());
3048 ok(signer != NULL && signer != (PCCERT_CONTEXT)0xdeadbeef,
3049 "expected a valid signer\n");
3050 if (signer && signer != (PCCERT_CONTEXT)0xdeadbeef)
3051 CertFreeCertificateContext(signer);
3052 /* Specifying CMSG_USE_SIGNER_INDEX_FLAG and an invalid signer index fails
3054 signerIndex = 0xdeadbeef;
3055 SetLastError(0xdeadbeef);
3056 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, CMSG_USE_SIGNER_INDEX_FLAG,
3057 NULL, &signerIndex);
3058 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
3059 "expected CRYPT_E_INVALID_INDEX, got 0x%08x\n", GetLastError());
3060 /* Specifying CMSG_TRUSTED_SIGNER_FLAG and no cert stores causes the
3061 * message signer not to be found.
3063 SetLastError(0xdeadbeef);
3064 ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, CMSG_TRUSTED_SIGNER_FLAG,
3065 NULL, NULL);
3066 ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
3067 "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
3068 /* Specifying CMSG_TRUSTED_SIGNER_FLAG and an empty cert store also causes
3069 * the message signer not to be found.
3071 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
3072 CERT_STORE_CREATE_NEW_FLAG, NULL);
3073 SetLastError(0xdeadbeef);
3074 ret = CryptMsgGetAndVerifySigner(msg, 1, &store, CMSG_TRUSTED_SIGNER_FLAG,
3075 NULL, NULL);
3076 ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
3077 "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
3078 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
3079 v1CertWithValidPubKey, sizeof(v1CertWithValidPubKey),
3080 CERT_STORE_ADD_ALWAYS, NULL);
3081 ok(ret, "CertAddEncodedCertificateToStore failed: 0x%08x\n",
3082 GetLastError());
3083 /* Specifying CMSG_TRUSTED_SIGNER_FLAG with a cert store that contains
3084 * the signer succeeds.
3086 SetLastError(0xdeadbeef);
3087 ret = CryptMsgGetAndVerifySigner(msg, 1, &store, CMSG_TRUSTED_SIGNER_FLAG,
3088 NULL, NULL);
3089 ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError());
3090 CertCloseStore(store, 0);
3091 CryptMsgClose(msg);
3094 START_TEST(msg)
3096 init_function_pointers();
3097 have_nt = detect_nt();
3098 if (!have_nt)
3099 win_skip("Win9x crashes on some parameter checks\n");
3101 /* Basic parameter checking tests */
3102 test_msg_open_to_encode();
3103 test_msg_open_to_decode();
3104 test_msg_get_param();
3105 test_msg_close();
3106 test_msg_control();
3108 /* Message-type specific tests */
3109 test_data_msg();
3110 test_hash_msg();
3111 test_signed_msg();
3112 test_decode_msg();
3114 test_msg_get_and_verify_signer();