2 * Unit test suite for crypt32.dll's CryptMsg functions
4 * Copyright 2007 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/test.h"
30 static void test_msg_open_to_encode(void)
35 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, NULL,
37 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, NULL, NULL,
39 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, NULL, NULL,
44 SetLastError(0xdeadbeef);
45 msg
= CryptMsgOpenToEncode(0, 0, 0, NULL
, NULL
, NULL
);
46 ok(!msg
&& GetLastError() == E_INVALIDARG
,
47 "Expected E_INVALIDARG, got %x\n", GetLastError());
48 SetLastError(0xdeadbeef);
49 msg
= CryptMsgOpenToEncode(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
, NULL
);
50 ok(!msg
&& GetLastError() == E_INVALIDARG
,
51 "Expected E_INVALIDARG, got %x\n", GetLastError());
53 /* Bad message types */
54 SetLastError(0xdeadbeef);
55 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0, 0, NULL
, NULL
, NULL
);
56 ok(!msg
&& GetLastError() == CRYPT_E_INVALID_MSG_TYPE
,
57 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
58 SetLastError(0xdeadbeef);
59 msg
= CryptMsgOpenToEncode(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, 0, 0,
61 ok(!msg
&& GetLastError() == CRYPT_E_INVALID_MSG_TYPE
,
62 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
63 SetLastError(0xdeadbeef);
64 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0,
65 CMSG_SIGNED_AND_ENVELOPED
, NULL
, NULL
, NULL
);
66 ok(!msg
&& GetLastError() == CRYPT_E_INVALID_MSG_TYPE
,
67 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
68 SetLastError(0xdeadbeef);
69 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0, CMSG_ENCRYPTED
, NULL
,
71 ok(!msg
&& GetLastError() == CRYPT_E_INVALID_MSG_TYPE
,
72 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
75 static void test_msg_open_to_decode(void)
78 CMSG_STREAM_INFO streamInfo
= { 0 };
80 SetLastError(0xdeadbeef);
81 msg
= CryptMsgOpenToDecode(0, 0, 0, 0, NULL
, NULL
);
82 ok(!msg
&& GetLastError() == E_INVALIDARG
,
83 "Expected E_INVALIDARG, got %x\n", GetLastError());
86 SetLastError(0xdeadbeef);
87 msg
= CryptMsgOpenToDecode(X509_ASN_ENCODING
, 0, 0, 0, NULL
, NULL
);
88 ok(!msg
&& GetLastError() == E_INVALIDARG
,
89 "Expected E_INVALIDARG, got %x\n", GetLastError());
90 SetLastError(0xdeadbeef);
91 msg
= CryptMsgOpenToDecode(X509_ASN_ENCODING
, 0, CMSG_DATA
, 0, NULL
, NULL
);
92 ok(!msg
&& GetLastError() == E_INVALIDARG
,
93 "Expected E_INVALIDARG, got %x\n", GetLastError());
95 /* The message type can be explicit... */
96 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_DATA
, 0, NULL
,
99 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
101 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_ENVELOPED
, 0, NULL
,
103 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
105 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_HASHED
, 0, NULL
,
107 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
109 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_SIGNED
, 0, NULL
,
111 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
113 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0,
114 CMSG_SIGNED_AND_ENVELOPED
, 0, NULL
, NULL
);
115 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
118 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, 0, 0, NULL
, NULL
);
119 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
121 /* or even invalid. */
122 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_ENCRYPTED
, 0, NULL
,
124 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
126 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, 1000, 0, NULL
, NULL
);
127 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
131 /* And even though the stream info parameter "must be set to NULL" for
132 * CMSG_HASHED, it's still accepted.
134 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_HASHED
, 0, NULL
,
137 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
141 static void test_msg_get_param(void)
145 DWORD size
, i
, value
;
146 CMSG_SIGNED_ENCODE_INFO signInfo
= { sizeof(signInfo
), 0 };
147 CMSG_SIGNER_ENCODE_INFO signer
= { sizeof(signer
), 0 };
150 ret = CryptMsgGetParam(NULL, 0, 0, NULL, NULL);
151 ret = CryptMsgGetParam(NULL, 0, 0, NULL, &size);
152 ret = CryptMsgGetParam(msg, 0, 0, NULL, NULL);
155 /* Decoded messages */
156 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, 0, 0, NULL
, NULL
);
158 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
159 /* For decoded messages, the type is always available */
161 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, NULL
, &size
);
163 ok(ret
, "CryptMsgGetParam failed: %x\n", GetLastError());
164 size
= sizeof(value
);
165 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, (LPBYTE
)&value
, &size
);
166 ok(ret
, "CryptMsgGetParam failed: %x\n", GetLastError());
167 /* For this (empty) message, the type isn't set */
168 ok(value
== 0, "Expected type 0, got %d\n", value
);
172 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_DATA
, 0, NULL
,
175 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
176 /* For explicitly typed messages, the type is known. */
177 size
= sizeof(value
);
178 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, (LPBYTE
)&value
, &size
);
180 ok(ret
, "CryptMsgGetParam failed: %x\n", GetLastError());
181 ok(value
== CMSG_DATA
, "Expected CMSG_DATA, got %d\n", value
);
183 for (i
= CMSG_CONTENT_PARAM
; i
<= CMSG_CMS_SIGNER_INFO_PARAM
; i
++)
186 ret
= CryptMsgGetParam(msg
, i
, 0, NULL
, &size
);
187 ok(!ret
, "Parameter %d: expected failure\n", i
);
191 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_ENVELOPED
, 0, NULL
,
194 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
195 size
= sizeof(value
);
196 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, (LPBYTE
)&value
, &size
);
197 ok(ret
, "CryptMsgGetParam failed: %x\n", GetLastError());
198 ok(value
== CMSG_ENVELOPED
, "Expected CMSG_ENVELOPED, got %d\n", value
);
200 for (i
= CMSG_CONTENT_PARAM
; i
<= CMSG_CMS_SIGNER_INFO_PARAM
; i
++)
203 ret
= CryptMsgGetParam(msg
, i
, 0, NULL
, &size
);
204 ok(!ret
, "Parameter %d: expected failure\n", i
);
208 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_HASHED
, 0, NULL
,
211 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
212 size
= sizeof(value
);
213 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, (LPBYTE
)&value
, &size
);
214 ok(ret
, "CryptMsgGetParam failed: %x\n", GetLastError());
215 ok(value
== CMSG_HASHED
, "Expected CMSG_HASHED, got %d\n", value
);
217 for (i
= CMSG_CONTENT_PARAM
; i
<= CMSG_CMS_SIGNER_INFO_PARAM
; i
++)
220 ret
= CryptMsgGetParam(msg
, i
, 0, NULL
, &size
);
221 ok(!ret
, "Parameter %d: expected failure\n", i
);
225 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_SIGNED
, 0, NULL
,
228 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
229 size
= sizeof(value
);
230 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, (LPBYTE
)&value
, &size
);
231 ok(ret
, "CryptMsgGetParam failed: %x\n", GetLastError());
232 ok(value
== CMSG_SIGNED
, "Expected CMSG_SIGNED, got %d\n", value
);
234 for (i
= CMSG_CONTENT_PARAM
; i
<= CMSG_CMS_SIGNER_INFO_PARAM
; i
++)
237 ret
= CryptMsgGetParam(msg
, i
, 0, NULL
, &size
);
238 ok(!ret
, "Parameter %d: expected failure\n", i
);
242 /* Explicitly typed messages get their types set, even if they're invalid */
243 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, CMSG_ENCRYPTED
, 0, NULL
,
246 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
247 size
= sizeof(value
);
248 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, (LPBYTE
)&value
, &size
);
249 ok(ret
, "CryptMsgGetParam failed: %x\n", GetLastError());
250 ok(value
== CMSG_ENCRYPTED
, "Expected CMSG_ENCRYPTED, got %d\n", value
);
254 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
, 0, 1000, 0, NULL
, NULL
);
256 ok(msg
!= NULL
, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
257 size
= sizeof(value
);
258 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, (LPBYTE
)&value
, &size
);
259 ok(ret
, "CryptMsgGetParam failed: %x\n", GetLastError());
260 ok(value
== 1000, "Expected 1000, got %d\n", value
);
265 static void test_msg_close(void)
270 /* NULL succeeds.. */
271 ret
= CryptMsgClose(NULL
);
272 ok(ret
, "CryptMsgClose failed: %x\n", GetLastError());
273 /* but an arbitrary pointer crashes. */
275 ret
= CryptMsgClose((HCRYPTMSG
)1);
276 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0, CMSG_DATA
, NULL
, NULL
,
278 ok(msg
!= NULL
, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
279 ret
= CryptMsgClose(msg
);
280 ok(ret
, "CryptMsgClose failed: %x\n", GetLastError());
283 static void check_param(LPCSTR test
, HCRYPTMSG msg
, DWORD param
,
284 const BYTE
*expected
, DWORD expectedSize
)
291 ret
= CryptMsgGetParam(msg
, param
, 0, NULL
, &size
);
292 ok(ret
, "%s: CryptMsgGetParam failed: %08x\n", test
, GetLastError());
293 buf
= HeapAlloc(GetProcessHeap(), 0, size
);
294 ret
= CryptMsgGetParam(msg
, param
, 0, buf
, &size
);
295 ok(ret
, "%s: CryptMsgGetParam failed: %08x\n", test
, GetLastError());
296 ok(size
== expectedSize
, "%s: expected size %d, got %d\n", test
,
299 ok(!memcmp(buf
, expected
, size
), "%s: unexpected data\n", test
);
300 HeapFree(GetProcessHeap(), 0, buf
);
303 static void test_data_msg_open(void)
306 CMSG_HASHED_ENCODE_INFO hashInfo
= { 0 };
308 /* The data message type takes no additional info */
309 SetLastError(0xdeadbeef);
310 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0, CMSG_DATA
, &hashInfo
,
312 ok(!msg
&& GetLastError() == E_INVALIDARG
,
313 "Expected E_INVALIDARG, got %x\n", GetLastError());
314 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0, CMSG_DATA
, NULL
, NULL
,
316 ok(msg
!= NULL
, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
320 static const BYTE msgData
[] = { 1, 2, 3, 4 };
322 static void test_data_msg_update(void)
327 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0, CMSG_DATA
, NULL
, NULL
,
329 /* Can't update a message that wasn't opened detached with final = FALSE */
330 SetLastError(0xdeadbeef);
331 ret
= CryptMsgUpdate(msg
, NULL
, 0, FALSE
);
332 ok(!ret
&& GetLastError() == CRYPT_E_MSG_ERROR
,
333 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
334 /* Updating it with final = TRUE succeeds */
335 ret
= CryptMsgUpdate(msg
, msgData
, sizeof(msgData
), TRUE
);
336 ok(ret
, "CryptMsgUpdate failed: %x\n", GetLastError());
337 /* Any subsequent update will fail, as the last was final */
338 SetLastError(0xdeadbeef);
339 ret
= CryptMsgUpdate(msg
, msgData
, sizeof(msgData
), TRUE
);
340 ok(!ret
&& GetLastError() == CRYPT_E_MSG_ERROR
,
341 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
344 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0, CMSG_DATA
, NULL
, NULL
,
346 /* Can't update a message with no data */
347 SetLastError(0xdeadbeef);
348 ret
= CryptMsgUpdate(msg
, NULL
, 0, TRUE
);
349 ok(!ret
&& GetLastError() == E_INVALIDARG
,
350 "Expected E_INVALIDARG, got %x\n", GetLastError());
351 /* Curiously, a valid update will now fail as well, presumably because of
352 * the last (invalid, but final) update.
354 ret
= CryptMsgUpdate(msg
, msgData
, sizeof(msgData
), TRUE
);
355 ok(!ret
&& GetLastError() == CRYPT_E_MSG_ERROR
,
356 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
359 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, CMSG_DETACHED_FLAG
,
360 CMSG_DATA
, NULL
, NULL
, NULL
);
361 /* Dont appear to be able to update CMSG-DATA with non-final updates */
362 SetLastError(0xdeadbeef);
363 ret
= CryptMsgUpdate(msg
, NULL
, 0, FALSE
);
364 ok(!ret
&& GetLastError() == E_INVALIDARG
,
365 "Expected E_INVALIDARG, got %x\n", GetLastError());
366 SetLastError(0xdeadbeef);
367 ret
= CryptMsgUpdate(msg
, msgData
, sizeof(msgData
), FALSE
);
368 ok(!ret
&& GetLastError() == E_INVALIDARG
,
369 "Expected E_INVALIDARG, got %x\n", GetLastError());
370 ret
= CryptMsgUpdate(msg
, msgData
, sizeof(msgData
), TRUE
);
371 ok(ret
, "CryptMsgUpdate failed: %x\n", GetLastError());
375 static void test_data_msg_get_param(void)
381 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0, CMSG_DATA
, NULL
, NULL
,
384 /* Content and bare content are always gettable */
386 ret
= CryptMsgGetParam(msg
, CMSG_CONTENT_PARAM
, 0, NULL
, &size
);
387 ok(ret
, "CryptMsgGetParam failed: %08x\n", GetLastError());
389 ret
= CryptMsgGetParam(msg
, CMSG_BARE_CONTENT_PARAM
, 0, NULL
, &size
);
390 ok(ret
, "CryptMsgGetParam failed: %08x\n", GetLastError());
391 /* But for this type of message, the signer and hash aren't applicable,
392 * and the type isn't available.
395 SetLastError(0xdeadbeef);
396 ret
= CryptMsgGetParam(msg
, CMSG_ENCODED_SIGNER
, 0, NULL
, &size
);
397 ok(!ret
&& GetLastError() == CRYPT_E_INVALID_MSG_TYPE
,
398 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
399 SetLastError(0xdeadbeef);
400 ret
= CryptMsgGetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0, NULL
, &size
);
401 ok(!ret
&& GetLastError() == CRYPT_E_INVALID_MSG_TYPE
,
402 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
403 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, NULL
, &size
);
404 ok(!ret
&& GetLastError() == CRYPT_E_INVALID_MSG_TYPE
,
405 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
410 static const BYTE dataEmptyBareContent
[] = { 0x04,0x00 };
411 static const BYTE dataEmptyContent
[] = {
412 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
414 static const BYTE dataBareContent
[] = { 0x04,0x04,0x01,0x02,0x03,0x04 };
415 static const BYTE dataContent
[] = {
416 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,
417 0x04,0x04,0x01,0x02,0x03,0x04 };
419 static void test_data_msg_encoding(void)
424 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, 0, CMSG_DATA
, NULL
, NULL
,
426 check_param("data empty bare content", msg
, CMSG_BARE_CONTENT_PARAM
,
427 dataEmptyBareContent
, sizeof(dataEmptyBareContent
));
428 check_param("data empty content", msg
, CMSG_CONTENT_PARAM
, dataEmptyContent
,
429 sizeof(dataEmptyContent
));
430 ret
= CryptMsgUpdate(msg
, msgData
, sizeof(msgData
), TRUE
);
431 ok(ret
, "CryptMsgUpdate failed: %x\n", GetLastError());
432 check_param("data bare content", msg
, CMSG_BARE_CONTENT_PARAM
,
433 dataBareContent
, sizeof(dataBareContent
));
434 check_param("data content", msg
, CMSG_CONTENT_PARAM
, dataContent
,
435 sizeof(dataContent
));
437 /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
438 msg
= CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING
, CMSG_BARE_CONTENT_FLAG
,
439 CMSG_DATA
, NULL
, NULL
, NULL
);
440 check_param("data empty bare content", msg
, CMSG_BARE_CONTENT_PARAM
,
441 dataEmptyBareContent
, sizeof(dataEmptyBareContent
));
442 check_param("data empty content", msg
, CMSG_CONTENT_PARAM
, dataEmptyContent
,
443 sizeof(dataEmptyContent
));
444 ret
= CryptMsgUpdate(msg
, msgData
, sizeof(msgData
), TRUE
);
445 ok(ret
, "CryptMsgUpdate failed: %x\n", GetLastError());
446 check_param("data bare content", msg
, CMSG_BARE_CONTENT_PARAM
,
447 dataBareContent
, sizeof(dataBareContent
));
448 check_param("data content", msg
, CMSG_CONTENT_PARAM
, dataContent
,
449 sizeof(dataContent
));
453 static void test_data_msg(void)
455 test_data_msg_open();
456 test_data_msg_update();
457 test_data_msg_get_param();
458 test_data_msg_encoding();
463 /* Basic parameter checking tests */
464 test_msg_open_to_encode();
465 test_msg_open_to_decode();
466 test_msg_get_param();
469 /* Message-type specific tests */