Make CryptImport/ExportPublicKeyInfoEx behave the way MSDN describes
[wine/wine-kai.git] / dlls / crypt32 / tests / encode.c
blobc22db546a24c0e397caa89701baf39840ec2c469
1 /*
2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
4 * Copyright 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
27 #include "wine/test.h"
29 struct encodedInt
31 int val;
32 const BYTE *encoded;
35 static const BYTE bin1[] = {0x02,0x01,0x01,0};
36 static const BYTE bin2[] = {0x02,0x01,0x7f,0};
37 static const BYTE bin3[] = {0x02,0x02,0x00,0x80,0};
38 static const BYTE bin4[] = {0x02,0x02,0x01,0x00,0};
39 static const BYTE bin5[] = {0x02,0x01,0x80,0};
40 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f,0};
41 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d,0};
43 static const struct encodedInt ints[] = {
44 { 1, bin1 },
45 { 127, bin2 },
46 { 128, bin3 },
47 { 256, bin4 },
48 { -128, bin5 },
49 { -129, bin6 },
50 { 0xbaddf00d, bin7 },
53 struct encodedBigInt
55 const BYTE *val;
56 const BYTE *encoded;
57 const BYTE *decoded;
60 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
61 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
62 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
64 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
65 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
66 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
68 static const struct encodedBigInt bigInts[] = {
69 { bin8, bin9, bin10 },
70 { bin11, bin12, bin13 },
73 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
74 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
75 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
76 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 /* Decoded is the same as original, so don't bother storing a separate copy */
79 static const struct encodedBigInt bigUInts[] = {
80 { bin14, bin15, NULL },
81 { bin16, bin17, NULL },
84 static void test_encodeInt(DWORD dwEncoding)
86 DWORD bufSize = 0;
87 int i;
88 BOOL ret;
89 CRYPT_INTEGER_BLOB blob;
90 BYTE *buf = NULL;
92 /* CryptEncodeObjectEx with NULL bufSize crashes..
93 ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
94 NULL);
96 /* check bogus encoding */
97 ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98 &bufSize);
99 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
100 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
101 /* check with NULL integer buffer. Windows XP incorrectly returns an
102 * NTSTATUS.
104 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
105 &bufSize);
106 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
107 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
108 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
110 /* encode as normal integer */
111 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
112 NULL, NULL, &bufSize);
113 ok(ret, "Expected success, got %ld\n", GetLastError());
114 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
115 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
116 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
117 if (buf)
119 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
120 buf[0]);
121 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
122 buf[1], ints[i].encoded[1]);
123 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
124 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
125 LocalFree(buf);
127 /* encode as multibyte integer */
128 blob.cbData = sizeof(ints[i].val);
129 blob.pbData = (BYTE *)&ints[i].val;
130 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
131 0, NULL, NULL, &bufSize);
132 ok(ret, "Expected success, got %ld\n", GetLastError());
133 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
134 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
135 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
136 if (buf)
138 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
139 buf[0]);
140 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
141 buf[1], ints[i].encoded[1]);
142 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
143 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
144 LocalFree(buf);
147 /* encode a couple bigger ints, just to show it's little-endian and leading
148 * sign bytes are dropped
150 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
152 blob.cbData = strlen((const char*)bigInts[i].val);
153 blob.pbData = (BYTE *)bigInts[i].val;
154 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
155 0, NULL, NULL, &bufSize);
156 ok(ret, "Expected success, got %ld\n", GetLastError());
157 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
158 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
159 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
160 if (buf)
162 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
163 buf[0]);
164 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
165 buf[1], bigInts[i].encoded[1]);
166 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
167 bigInts[i].encoded[1] + 1),
168 "Encoded value didn't match expected\n");
169 LocalFree(buf);
172 /* and, encode some uints */
173 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
175 blob.cbData = strlen((const char*)bigUInts[i].val);
176 blob.pbData = (BYTE*)bigUInts[i].val;
177 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
178 0, NULL, NULL, &bufSize);
179 ok(ret, "Expected success, got %ld\n", GetLastError());
180 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
181 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
182 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
183 if (buf)
185 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
186 buf[0]);
187 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
188 buf[1], bigUInts[i].encoded[1]);
189 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
190 bigUInts[i].encoded[1] + 1),
191 "Encoded value didn't match expected\n");
192 LocalFree(buf);
197 static void test_decodeInt(DWORD dwEncoding)
199 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
200 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
201 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
202 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
203 BYTE *buf = NULL;
204 DWORD bufSize = 0;
205 int i;
206 BOOL ret;
208 /* CryptDecodeObjectEx with NULL bufSize crashes..
209 ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
210 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
212 /* check bogus encoding */
213 ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
214 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
215 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
216 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
217 /* check with NULL integer buffer */
218 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
219 &bufSize);
220 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
221 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
222 /* check with a valid, but too large, integer */
223 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
224 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
225 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
226 "Expected CRYPT_E_ASN1_LARGE, got %ld\n", GetLastError());
227 /* check with a DER-encoded string */
228 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
229 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
231 "Expected CRYPT_E_ASN1_BADTAG, got %ld\n", GetLastError());
232 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
234 /* When the output buffer is NULL, this always succeeds */
235 SetLastError(0xdeadbeef);
236 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
237 (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
238 &bufSize);
239 ok(ret && GetLastError() == NOERROR,
240 "Expected success and NOERROR, got %ld\n", GetLastError());
241 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242 (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2,
243 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
244 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
245 ok(bufSize == sizeof(int), "Expected size %d, got %ld\n", sizeof(int),
246 bufSize);
247 ok(buf != NULL, "Expected allocated buffer\n");
248 if (buf)
250 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
251 ints[i].val, *(int *)buf);
252 LocalFree(buf);
255 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
257 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
258 (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
259 &bufSize);
260 ok(ret && GetLastError() == NOERROR,
261 "Expected success and NOERROR, got %ld\n", GetLastError());
262 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
263 (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2,
264 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
265 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
266 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
267 "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
268 bufSize);
269 ok(buf != NULL, "Expected allocated buffer\n");
270 if (buf)
272 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
274 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
275 "Expected len %d, got %ld\n", strlen((const char*)bigInts[i].decoded),
276 blob->cbData);
277 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
278 "Unexpected value\n");
279 LocalFree(buf);
282 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
284 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
285 (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
286 &bufSize);
287 ok(ret && GetLastError() == NOERROR,
288 "Expected success and NOERROR, got %ld\n", GetLastError());
289 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
290 (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
291 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
292 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
293 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
294 "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
295 bufSize);
296 ok(buf != NULL, "Expected allocated buffer\n");
297 if (buf)
299 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
301 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
302 "Expected len %d, got %ld\n", strlen((const char*)bigUInts[i].val),
303 blob->cbData);
304 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
305 "Unexpected value\n");
306 LocalFree(buf);
309 /* Decode the value 1 with long-form length */
310 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
311 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
312 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
313 if (buf)
315 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
316 LocalFree(buf);
318 /* Try to decode some bogus large items */
319 /* The buffer size is smaller than the encoded length, so this should fail
320 * with CRYPT_E_ASN1_EOD if it's being decoded.
321 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
322 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
323 * So this test unfortunately isn't useful.
324 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
325 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
326 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
327 "Expected CRYPT_E_ASN1_LARGE, got %08lx\n", GetLastError());
329 /* This will try to decode the buffer and overflow it, check that it's
330 * caught.
332 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
333 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
334 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
335 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
338 static const BYTE bin18[] = {0x0a,0x01,0x01,0};
339 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80,0};
341 /* These are always encoded unsigned, and aren't constrained to be any
342 * particular value
344 static const struct encodedInt enums[] = {
345 { 1, bin18 },
346 { -128, bin19 },
349 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
350 * X509_ENUMERATED.
352 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
353 szOID_CRL_REASON_CODE };
355 static void test_encodeEnumerated(DWORD dwEncoding)
357 DWORD i, j;
359 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
361 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
363 BOOL ret;
364 BYTE *buf = NULL;
365 DWORD bufSize = 0;
367 ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
368 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
369 &bufSize);
370 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
371 if (buf)
373 ok(buf[0] == 0xa,
374 "Got unexpected type %d for enumerated (expected 0xa)\n",
375 buf[0]);
376 ok(buf[1] == enums[j].encoded[1],
377 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
378 ok(!memcmp(buf + 1, enums[j].encoded + 1,
379 enums[j].encoded[1] + 1),
380 "Encoded value of 0x%08x didn't match expected\n",
381 enums[j].val);
382 LocalFree(buf);
388 static void test_decodeEnumerated(DWORD dwEncoding)
390 DWORD i, j;
392 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
394 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
396 BOOL ret;
397 DWORD bufSize = sizeof(int);
398 int val;
400 ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
401 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
402 (BYTE *)&val, &bufSize);
403 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
404 ok(bufSize == sizeof(int),
405 "Got unexpected size %ld for enumerated (expected %d)\n",
406 bufSize, sizeof(int));
407 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
408 val, enums[j].val);
413 struct encodedFiletime
415 SYSTEMTIME sysTime;
416 const BYTE *encodedTime;
419 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
420 const struct encodedFiletime *time)
422 FILETIME ft = { 0 };
423 BYTE *buf = NULL;
424 DWORD bufSize = 0;
425 BOOL ret;
427 ret = SystemTimeToFileTime(&time->sysTime, &ft);
428 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
429 ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
430 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
431 /* years other than 1950-2050 are not allowed for encodings other than
432 * X509_CHOICE_OF_TIME.
434 if (structType == X509_CHOICE_OF_TIME ||
435 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
437 ok(ret, "CryptEncodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
438 GetLastError());
439 ok(buf != NULL, "Expected an allocated buffer\n");
440 if (buf)
442 ok(buf[0] == time->encodedTime[0],
443 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
444 buf[0]);
445 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %ld\n",
446 time->encodedTime[1], bufSize);
447 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
448 "Got unexpected value for time encoding\n");
449 LocalFree(buf);
452 else
453 ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
454 "Expected CRYPT_E_BAD_ENCODE, got 0x%08lx\n", GetLastError());
457 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
458 const struct encodedFiletime *time)
460 FILETIME ft1 = { 0 }, ft2 = { 0 };
461 DWORD size = sizeof(ft2);
462 BOOL ret;
464 ret = SystemTimeToFileTime(&time->sysTime, &ft1);
465 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
466 ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
467 time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
468 /* years other than 1950-2050 are not allowed for encodings other than
469 * X509_CHOICE_OF_TIME.
471 if (structType == X509_CHOICE_OF_TIME ||
472 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
474 ok(ret, "CryptDecodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
475 GetLastError());
476 ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
477 "Got unexpected value for time decoding\n");
479 else
480 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
481 "Expected CRYPT_E_ASN1_BADTAG, got 0x%08lx\n", GetLastError());
484 static const BYTE bin20[] = {
485 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z',0};
486 static const BYTE bin21[] = {
487 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z',0};
488 static const BYTE bin22[] = {
489 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z',0};
491 static const struct encodedFiletime times[] = {
492 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
493 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
494 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
497 static void test_encodeFiletime(DWORD dwEncoding)
499 DWORD i;
501 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
503 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
504 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
505 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
509 static const BYTE bin23[] = {
510 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z',0};
511 static const BYTE bin24[] = {
512 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z',0};
513 static const BYTE bin25[] = {
514 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0',0};
515 static const BYTE bin26[] = {
516 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0',0};
517 static const BYTE bin27[] = {
518 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5',0};
519 static const BYTE bin28[] = {
520 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6',0};
521 static const BYTE bin29[] = {
522 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0',0};
523 static const BYTE bin30[] = {
524 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z',0};
525 static const BYTE bin31[] = {
526 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1',0};
527 static const BYTE bin32[] = {
528 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1',0};
529 static const BYTE bin33[] = {
530 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0',0};
531 static const BYTE bin34[] = {
532 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0',0};
533 static const BYTE bin35[] = {
534 0x17,0x08, '4','5','0','6','0','6','1','6',0};
535 static const BYTE bin36[] = {
536 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z',0};
537 static const BYTE bin37[] = {
538 0x18,0x04, '2','1','4','5',0};
539 static const BYTE bin38[] = {
540 0x18,0x08, '2','1','4','5','0','6','0','6',0};
542 static void test_decodeFiletime(DWORD dwEncoding)
544 static const struct encodedFiletime otherTimes[] = {
545 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
546 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
547 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
548 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
549 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
550 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
551 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
552 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
553 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
554 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
555 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
556 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
558 /* An oddball case that succeeds in Windows, but doesn't seem correct
559 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
561 static const unsigned char *bogusTimes[] = {
562 /* oddly, this succeeds on Windows, with year 2765
563 "\x18" "\x0f" "21r50606161000Z",
565 bin35,
566 bin36,
567 bin37,
568 bin38,
570 DWORD i, size;
571 FILETIME ft1 = { 0 }, ft2 = { 0 };
572 BOOL ret;
574 /* Check bogus length with non-NULL buffer */
575 ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
576 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
577 size = 1;
578 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
579 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
580 ok(!ret && GetLastError() == ERROR_MORE_DATA,
581 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
582 /* Normal tests */
583 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
585 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
586 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
587 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
589 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
591 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
592 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
593 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
595 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
597 size = sizeof(ft1);
598 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
599 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
600 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
601 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
605 struct EncodedName
607 CERT_RDN_ATTR attr;
608 const BYTE *encoded;
611 static const char commonName[] = "Juan Lang";
612 static const char surName[] = "Lang";
613 static const char bogusIA5[] = "\x80";
614 static const char bogusPrintable[] = "~";
615 static const char bogusNumeric[] = "A";
616 static const unsigned char bin39[] = {
617 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
618 static const unsigned char bin40[] = {
619 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x16,0x0a,'J','u','a','n',' ','L','a','n','g',0};
620 static const unsigned char bin41[] = {
621 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x16,0x05,'L','a','n','g',0};
622 static const unsigned char bin42[] = {
623 0x30,0x12,0x31,0x10,0x30,0x0e,0x06,0x00,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
624 static const unsigned char bin43[] = {
625 0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x03,0x16,0x02,0x80,0};
626 static const unsigned char bin44[] = {
627 0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x03,0x13,0x02,0x7e,0};
628 static const unsigned char bin45[] = {
629 0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x03,0x12,0x02,0x41,0};
630 static const struct EncodedName names[] = {
631 { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
632 { sizeof(commonName), (BYTE *)commonName } }, bin39 },
633 { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
634 { sizeof(commonName), (BYTE *)commonName } }, bin40 },
635 { { szOID_SUR_NAME, CERT_RDN_IA5_STRING,
636 { sizeof(surName), (BYTE *)surName } }, bin41 },
637 { { NULL, CERT_RDN_PRINTABLE_STRING,
638 { sizeof(commonName), (BYTE *)commonName } }, bin42 },
639 /* The following test isn't a very good one, because it doesn't encode any
640 * Japanese characters. I'm leaving it out for now.
641 { { szOID_COMMON_NAME, CERT_RDN_T61_STRING,
642 { sizeof(commonName), (BYTE *)commonName } },
643 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x14\x0aJuan Lang" },
645 /* The following tests succeed under Windows, but really should fail,
646 * they contain characters that are illegal for the encoding. I'm
647 * including them to justify my lazy encoding.
649 { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
650 { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin43 },
651 { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
652 { sizeof(bogusPrintable), (BYTE *)bogusPrintable } }, bin44 },
653 { { szOID_COMMON_NAME, CERT_RDN_NUMERIC_STRING,
654 { sizeof(bogusNumeric), (BYTE *)bogusNumeric } }, bin45 },
657 static const BYTE emptyName[] = { 0x30, 0 };
658 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
659 static const BYTE twoRDNs[] = {
660 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
661 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
662 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
664 static void test_encodeName(DWORD dwEncoding)
666 CERT_RDN_ATTR attrs[2];
667 CERT_RDN rdn;
668 CERT_NAME_INFO info;
669 BYTE *buf = NULL;
670 DWORD size = 0, i;
671 BOOL ret;
673 /* Test with NULL pvStructInfo */
674 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
675 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
676 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
677 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
678 /* Test with empty CERT_NAME_INFO */
679 info.cRDN = 0;
680 info.rgRDN = NULL;
681 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
682 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
683 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
684 if (buf)
686 ok(!memcmp(buf, emptyName, sizeof(emptyName)),
687 "Got unexpected encoding for empty name\n");
688 LocalFree(buf);
690 /* Test with bogus CERT_RDN */
691 info.cRDN = 1;
692 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
693 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
694 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
695 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
696 /* Test with empty CERT_RDN */
697 rdn.cRDNAttr = 0;
698 rdn.rgRDNAttr = NULL;
699 info.cRDN = 1;
700 info.rgRDN = &rdn;
701 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
702 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
703 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
704 if (buf)
706 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
707 "Got unexpected encoding for empty RDN array\n");
708 LocalFree(buf);
710 /* Test with bogus attr array */
711 rdn.cRDNAttr = 1;
712 rdn.rgRDNAttr = NULL;
713 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
714 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
715 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
716 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
717 /* oddly, a bogus OID is accepted by Windows XP; not testing.
718 attrs[0].pszObjId = "bogus";
719 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
720 attrs[0].Value.cbData = sizeof(commonName);
721 attrs[0].Value.pbData = (BYTE *)commonName;
722 rdn.cRDNAttr = 1;
723 rdn.rgRDNAttr = attrs;
724 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
725 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
726 ok(!ret, "Expected failure, got success\n");
728 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
729 * the encoded attributes to be swapped.
731 attrs[0].pszObjId = szOID_COMMON_NAME;
732 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
733 attrs[0].Value.cbData = sizeof(commonName);
734 attrs[0].Value.pbData = (BYTE *)commonName;
735 attrs[1].pszObjId = szOID_SUR_NAME;
736 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
737 attrs[1].Value.cbData = sizeof(surName);
738 attrs[1].Value.pbData = (BYTE *)surName;
739 rdn.cRDNAttr = 2;
740 rdn.rgRDNAttr = attrs;
741 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
742 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
743 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
744 if (buf)
746 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
747 "Got unexpected encoding for two RDN array\n");
748 LocalFree(buf);
750 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
751 rdn.cRDNAttr = 1;
752 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
753 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
754 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
755 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
756 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
757 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
759 rdn.cRDNAttr = 1;
760 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
761 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
762 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
763 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
764 if (buf)
766 ok(size == names[i].encoded[1] + 2, "Expected size %d, got %ld\n",
767 names[i].encoded[1] + 2, size);
768 ok(!memcmp(buf, names[i].encoded, names[i].encoded[1] + 2),
769 "Got unexpected encoding\n");
770 LocalFree(buf);
775 static void compareNames(const CERT_NAME_INFO *expected,
776 const CERT_NAME_INFO *got)
778 ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
779 expected->cRDN, got->cRDN);
780 if (expected->cRDN)
782 ok(got->rgRDN[0].cRDNAttr == expected->rgRDN[0].cRDNAttr,
783 "Expected %ld RDN attrs, got %ld\n", expected->rgRDN[0].cRDNAttr,
784 got->rgRDN[0].cRDNAttr);
785 if (expected->rgRDN[0].cRDNAttr)
787 if (expected->rgRDN[0].rgRDNAttr[0].pszObjId &&
788 strlen(expected->rgRDN[0].rgRDNAttr[0].pszObjId))
790 ok(got->rgRDN[0].rgRDNAttr[0].pszObjId != NULL,
791 "Expected OID %s, got NULL\n",
792 expected->rgRDN[0].rgRDNAttr[0].pszObjId);
793 if (got->rgRDN[0].rgRDNAttr[0].pszObjId)
794 ok(!strcmp(got->rgRDN[0].rgRDNAttr[0].pszObjId,
795 expected->rgRDN[0].rgRDNAttr[0].pszObjId),
796 "Got unexpected OID %s, expected %s\n",
797 got->rgRDN[0].rgRDNAttr[0].pszObjId,
798 expected->rgRDN[0].rgRDNAttr[0].pszObjId);
800 ok(got->rgRDN[0].rgRDNAttr[0].Value.cbData ==
801 expected->rgRDN[0].rgRDNAttr[0].Value.cbData,
802 "Unexpected data size, got %ld, expected %ld\n",
803 got->rgRDN[0].rgRDNAttr[0].Value.cbData,
804 expected->rgRDN[0].rgRDNAttr[0].Value.cbData);
805 if (expected->rgRDN[0].rgRDNAttr[0].Value.pbData)
806 ok(!memcmp(got->rgRDN[0].rgRDNAttr[0].Value.pbData,
807 expected->rgRDN[0].rgRDNAttr[0].Value.pbData,
808 expected->rgRDN[0].rgRDNAttr[0].Value.cbData),
809 "Unexpected value\n");
814 static void test_decodeName(DWORD dwEncoding)
816 int i;
817 BYTE *buf = NULL;
818 DWORD bufSize = 0;
819 BOOL ret;
820 CERT_RDN rdn;
821 CERT_NAME_INFO info = { 1, &rdn };
823 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
825 /* When the output buffer is NULL, this always succeeds */
826 SetLastError(0xdeadbeef);
827 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
828 names[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
829 ok(ret && GetLastError() == NOERROR,
830 "Expected success and NOERROR, got %08lx\n", GetLastError());
831 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
832 names[i].encoded[1] + 2,
833 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
834 (BYTE *)&buf, &bufSize);
835 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
836 rdn.cRDNAttr = 1;
837 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
838 if (buf)
840 compareNames((CERT_NAME_INFO *)buf, &info);
841 LocalFree(buf);
844 /* test empty name */
845 bufSize = 0;
846 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyName,
847 emptyName[1] + 2,
848 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
849 (BYTE *)&buf, &bufSize);
850 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
851 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
852 * decoder works the same way, so only test the count.
854 if (buf)
856 ok(bufSize == sizeof(CERT_NAME_INFO),
857 "Expected bufSize %d, got %ld\n", sizeof(CERT_NAME_INFO), bufSize);
858 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
859 "Expected 0 RDNs in empty info, got %ld\n",
860 ((CERT_NAME_INFO *)buf)->cRDN);
861 LocalFree(buf);
863 /* test empty RDN */
864 bufSize = 0;
865 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
866 emptyRDNs[1] + 2,
867 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
868 (BYTE *)&buf, &bufSize);
869 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
870 if (buf)
872 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
874 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
875 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
876 "Got unexpected value for empty RDN\n");
877 LocalFree(buf);
879 /* test two RDN attrs */
880 bufSize = 0;
881 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
882 twoRDNs[1] + 2,
883 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
884 (BYTE *)&buf, &bufSize);
885 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
886 if (buf)
888 CERT_RDN_ATTR attrs[] = {
889 { szOID_SUR_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
890 (BYTE *)surName } },
891 { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
892 (BYTE *)commonName } },
895 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
896 rdn.rgRDNAttr = attrs;
897 compareNames((CERT_NAME_INFO *)buf, &info);
898 LocalFree(buf);
902 static const BYTE emptyAltName[] = { 0x30, 0x00 };
903 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
904 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
905 'h','q','.','o','r','g',0 };
906 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
907 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
908 0x6f, 0x72, 0x67 };
909 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
910 0x575b, 0 };
911 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
912 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
913 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
914 static const BYTE localhost[] = { 127, 0, 0, 1 };
915 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
916 0x01 };
918 static void test_encodeAltName(DWORD dwEncoding)
920 CERT_ALT_NAME_INFO info = { 0 };
921 CERT_ALT_NAME_ENTRY entry = { 0 };
922 BYTE *buf = NULL;
923 DWORD size = 0;
924 BOOL ret;
926 /* Test with empty info */
927 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
928 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
929 if (buf)
931 ok(size == sizeof(emptyAltName), "Expected size %d, got %ld\n",
932 sizeof(emptyAltName), size);
933 ok(!memcmp(buf, emptyAltName, size), "Unexpected value\n");
934 LocalFree(buf);
936 /* Test with an empty entry */
937 info.cAltEntry = 1;
938 info.rgAltEntry = &entry;
939 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
940 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
941 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
942 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
943 GetLastError());
944 /* Test with an empty pointer */
945 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
946 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
947 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
948 if (buf)
950 ok(size == sizeof(emptyURL), "Expected size %d, got %ld\n",
951 sizeof(emptyURL), size);
952 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
953 LocalFree(buf);
955 /* Test with a real URL */
956 U(entry).pwszURL = (LPWSTR)url;
957 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
958 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
959 if (buf)
961 ok(size == sizeof(encodedURL), "Expected size %d, got %ld\n",
962 sizeof(encodedURL), size);
963 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
964 LocalFree(buf);
966 /* Now with the URL containing an invalid IA5 char */
967 U(entry).pwszURL = (LPWSTR)nihongoURL;
968 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
969 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
970 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
971 "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
972 /* The first invalid character is at index 7 */
973 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
974 "Expected invalid char at index 7, got %ld\n",
975 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
976 /* Now with the URL missing a scheme */
977 U(entry).pwszURL = (LPWSTR)dnsName;
978 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
979 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
980 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
981 if (buf)
983 /* This succeeds, but it shouldn't, so don't worry about conforming */
984 LocalFree(buf);
986 /* Now with a DNS name */
987 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
988 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
989 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
990 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
991 if (buf)
993 ok(size == sizeof(encodedDnsName), "Expected size %d, got %ld\n",
994 sizeof(encodedDnsName), size);
995 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
996 LocalFree(buf);
998 /* Test with an IP address */
999 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1000 U(entry).IPAddress.cbData = sizeof(localhost);
1001 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1002 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1003 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1004 if (buf)
1006 ok(size == sizeof(encodedIPAddr), "Expected size %d, got %ld\n",
1007 sizeof(encodedIPAddr), size);
1008 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1009 LocalFree(buf);
1013 static void test_decodeAltName(DWORD dwEncoding)
1015 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1016 0x00, 0x00, 0x01 };
1017 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1018 0x01 };
1019 BOOL ret;
1020 BYTE *buf = NULL;
1021 DWORD bufSize = 0;
1022 CERT_ALT_NAME_INFO *info;
1024 /* Test some bogus ones first */
1025 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1026 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1027 NULL, (BYTE *)&buf, &bufSize);
1028 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1029 "Expected CRYPT_E_ASN1_BADTAG, got %08lx\n", GetLastError());
1030 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1031 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1032 &bufSize);
1033 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1034 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1035 /* Now expected cases */
1036 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyAltName,
1037 emptyAltName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1038 &bufSize);
1039 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1040 if (buf)
1042 info = (CERT_ALT_NAME_INFO *)buf;
1044 ok(info->cAltEntry == 0, "Expected 0 entries, got %ld\n",
1045 info->cAltEntry);
1046 LocalFree(buf);
1048 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1049 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1050 &bufSize);
1051 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1052 if (buf)
1054 info = (CERT_ALT_NAME_INFO *)buf;
1056 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1057 info->cAltEntry);
1058 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1059 "Expected CERT_ALT_NAME_URL, got %ld\n",
1060 info->rgAltEntry[0].dwAltNameChoice);
1061 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1062 "Expected empty URL\n");
1063 LocalFree(buf);
1065 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1066 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1067 &bufSize);
1068 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1069 if (buf)
1071 info = (CERT_ALT_NAME_INFO *)buf;
1073 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1074 info->cAltEntry);
1075 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1076 "Expected CERT_ALT_NAME_URL, got %ld\n",
1077 info->rgAltEntry[0].dwAltNameChoice);
1078 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1079 LocalFree(buf);
1081 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1082 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1083 &bufSize);
1084 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1085 if (buf)
1087 info = (CERT_ALT_NAME_INFO *)buf;
1089 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1090 info->cAltEntry);
1091 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1092 "Expected CERT_ALT_NAME_DNS_NAME, got %ld\n",
1093 info->rgAltEntry[0].dwAltNameChoice);
1094 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1095 "Unexpected DNS name\n");
1096 LocalFree(buf);
1098 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1099 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1100 &bufSize);
1101 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1102 if (buf)
1104 info = (CERT_ALT_NAME_INFO *)buf;
1106 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1107 info->cAltEntry);
1108 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1109 "Expected CERT_ALT_NAME_IP_ADDRESS, got %ld\n",
1110 info->rgAltEntry[0].dwAltNameChoice);
1111 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1112 "Unexpected IP address length %ld\n",
1113 U(info->rgAltEntry[0]).IPAddress.cbData);
1114 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1115 sizeof(localhost)), "Unexpected IP address value\n");
1116 LocalFree(buf);
1120 struct encodedOctets
1122 const BYTE *val;
1123 const BYTE *encoded;
1126 static const unsigned char bin46[] = { 'h','i',0 };
1127 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1128 static const unsigned char bin48[] = {
1129 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1130 static const unsigned char bin49[] = {
1131 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1132 static const unsigned char bin50[] = { 0 };
1133 static const unsigned char bin51[] = { 0x04,0x00,0 };
1135 static const struct encodedOctets octets[] = {
1136 { bin46, bin47 },
1137 { bin48, bin49 },
1138 { bin50, bin51 },
1141 static void test_encodeOctets(DWORD dwEncoding)
1143 CRYPT_DATA_BLOB blob;
1144 DWORD i;
1146 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1148 BYTE *buf = NULL;
1149 BOOL ret;
1150 DWORD bufSize = 0;
1152 blob.cbData = strlen((const char*)octets[i].val);
1153 blob.pbData = (BYTE*)octets[i].val;
1154 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1155 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1156 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
1157 if (buf)
1159 ok(buf[0] == 4,
1160 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1161 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1162 buf[1], octets[i].encoded[1]);
1163 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1164 octets[i].encoded[1] + 1), "Got unexpected value\n");
1165 LocalFree(buf);
1170 static void test_decodeOctets(DWORD dwEncoding)
1172 DWORD i;
1174 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1176 BYTE *buf = NULL;
1177 BOOL ret;
1178 DWORD bufSize = 0;
1180 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1181 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1182 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1183 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1184 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1185 "Expected size >= %d, got %ld\n",
1186 sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1187 ok(buf != NULL, "Expected allocated buffer\n");
1188 if (buf)
1190 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1192 if (blob->cbData)
1193 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1194 "Unexpected value\n");
1195 LocalFree(buf);
1200 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1202 struct encodedBits
1204 DWORD cUnusedBits;
1205 const BYTE *encoded;
1206 DWORD cbDecoded;
1207 const BYTE *decoded;
1210 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff,0 };
1211 static const unsigned char bin53[] = { 0xff,0xff,0 };
1212 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe,0 };
1213 static const unsigned char bin55[] = { 0xff,0xfe,0 };
1214 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe,0 };
1215 static const unsigned char bin57[] = { 0xfe,0 };
1216 static const unsigned char bin58[] = { 0x03,0x01,0x00,0 };
1218 static const struct encodedBits bits[] = {
1219 /* normal test cases */
1220 { 0, bin52, 2, bin53 },
1221 { 1, bin54, 2, bin55 },
1222 /* strange test case, showing cUnusedBits >= 8 is allowed */
1223 { 9, bin56, 1, bin57 },
1224 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1225 { 17, bin58, 0, NULL },
1228 static void test_encodeBits(DWORD dwEncoding)
1230 DWORD i;
1232 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1234 CRYPT_BIT_BLOB blob;
1235 BOOL ret;
1236 BYTE *buf = NULL;
1237 DWORD bufSize = 0;
1239 blob.cbData = sizeof(bytesToEncode);
1240 blob.pbData = (BYTE *)bytesToEncode;
1241 blob.cUnusedBits = bits[i].cUnusedBits;
1242 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1243 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1244 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1245 if (buf)
1247 ok(bufSize == bits[i].encoded[1] + 2,
1248 "Got unexpected size %ld, expected %d\n", bufSize,
1249 bits[i].encoded[1] + 2);
1250 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1251 "Unexpected value\n");
1252 LocalFree(buf);
1257 static void test_decodeBits(DWORD dwEncoding)
1259 static const BYTE ber[] = "\x03\x02\x01\xff";
1260 static const BYTE berDecoded = 0xfe;
1261 DWORD i;
1262 BOOL ret;
1263 BYTE *buf = NULL;
1264 DWORD bufSize = 0;
1266 /* normal cases */
1267 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1269 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1270 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1271 &bufSize);
1272 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1273 if (buf)
1275 CRYPT_BIT_BLOB *blob;
1277 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1278 "Got unexpected size %ld, expected >= %ld\n", bufSize,
1279 sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
1280 blob = (CRYPT_BIT_BLOB *)buf;
1281 ok(blob->cbData == bits[i].cbDecoded,
1282 "Got unexpected length %ld, expected %ld\n", blob->cbData,
1283 bits[i].cbDecoded);
1284 if (blob->cbData && bits[i].cbDecoded)
1285 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1286 "Unexpected value\n");
1287 LocalFree(buf);
1290 /* special case: check that something that's valid in BER but not in DER
1291 * decodes successfully
1293 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1294 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1295 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1296 if (buf)
1298 CRYPT_BIT_BLOB *blob;
1300 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1301 "Got unexpected size %ld, expected >= %d\n", bufSize,
1302 sizeof(CRYPT_BIT_BLOB) + berDecoded);
1303 blob = (CRYPT_BIT_BLOB *)buf;
1304 ok(blob->cbData == sizeof(berDecoded),
1305 "Got unexpected length %ld, expected %d\n", blob->cbData,
1306 sizeof(berDecoded));
1307 if (blob->cbData)
1308 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1309 LocalFree(buf);
1313 struct Constraints2
1315 CERT_BASIC_CONSTRAINTS2_INFO info;
1316 const BYTE *encoded;
1319 static const unsigned char bin59[] = { 0x30,0x00,0 };
1320 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff,0 };
1321 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00,0 };
1322 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0 };
1323 static const struct Constraints2 constraints2[] = {
1324 /* empty constraints */
1325 { { FALSE, FALSE, 0}, bin59 },
1326 /* can be a CA */
1327 { { TRUE, FALSE, 0}, bin60 },
1328 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1329 * but that's not the case
1331 { { FALSE, TRUE, 0}, bin61 },
1332 /* can be a CA and has path length constraints set */
1333 { { TRUE, TRUE, 1}, bin62 },
1336 static void test_encodeBasicConstraints(DWORD dwEncoding)
1338 DWORD i;
1340 /* First test with the simpler info2 */
1341 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1343 BOOL ret;
1344 BYTE *buf = NULL;
1345 DWORD bufSize = 0;
1347 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1348 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1349 &bufSize);
1350 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1351 if (buf)
1353 ok(bufSize == constraints2[i].encoded[1] + 2,
1354 "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1355 bufSize);
1356 ok(!memcmp(buf, constraints2[i].encoded,
1357 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1358 LocalFree(buf);
1363 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01,0 };
1365 static void test_decodeBasicConstraints(DWORD dwEncoding)
1367 static const BYTE inverted[] = "\x30\x06\x02\x01\x01\x01\x01\xff";
1368 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1369 DWORD i;
1370 BOOL ret;
1371 BYTE *buf = NULL;
1372 DWORD bufSize = 0;
1374 /* First test with simpler info2 */
1375 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1377 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1378 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1379 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1380 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1381 if (buf)
1383 CERT_BASIC_CONSTRAINTS2_INFO *info =
1384 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1386 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1387 "Unexpected value\n");
1388 LocalFree(buf);
1391 /* Check with the order of encoded elements inverted */
1392 buf = (PBYTE)1;
1393 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1394 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1395 &bufSize);
1396 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1397 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1398 ok(!buf, "Expected buf to be set to NULL\n");
1399 /* Check with a non-DER bool */
1400 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1401 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1402 (BYTE *)&buf, &bufSize);
1403 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1404 if (buf)
1406 CERT_BASIC_CONSTRAINTS2_INFO *info =
1407 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1409 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1410 LocalFree(buf);
1412 /* Check with a non-basic constraints value */
1413 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1414 names[0].encoded, names[0].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1415 (BYTE *)&buf, &bufSize);
1416 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1417 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1420 /* These are terrible public keys of course, I'm just testing encoding */
1421 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
1422 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
1423 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
1424 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
1425 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
1426 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1427 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
1428 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1430 struct EncodedRSAPubKey
1432 const BYTE *modulus;
1433 size_t modulusLen;
1434 const BYTE *encoded;
1435 size_t decodedModulusLen;
1438 struct EncodedRSAPubKey rsaPubKeys[] = {
1439 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
1440 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
1441 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
1442 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
1445 static void test_encodeRsaPublicKey(DWORD dwEncoding)
1447 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
1448 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
1449 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
1450 BOOL ret;
1451 BYTE *buf = NULL;
1452 DWORD bufSize = 0, i;
1454 /* Try with a bogus blob type */
1455 hdr->bType = 2;
1456 hdr->bVersion = CUR_BLOB_VERSION;
1457 hdr->reserved = 0;
1458 hdr->aiKeyAlg = CALG_RSA_KEYX;
1459 rsaPubKey->magic = 0x31415352;
1460 rsaPubKey->bitlen = sizeof(modulus1) * 8;
1461 rsaPubKey->pubexp = 65537;
1462 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
1463 sizeof(modulus1));
1465 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1466 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1467 &bufSize);
1468 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1469 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1470 GetLastError());
1471 /* Now with a bogus reserved field */
1472 hdr->bType = PUBLICKEYBLOB;
1473 hdr->reserved = 1;
1474 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1475 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1476 &bufSize);
1477 if (buf)
1479 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1480 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1481 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1482 LocalFree(buf);
1484 /* Now with a bogus blob version */
1485 hdr->reserved = 0;
1486 hdr->bVersion = 0;
1487 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1488 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1489 &bufSize);
1490 if (buf)
1492 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1493 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1494 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1495 LocalFree(buf);
1497 /* And with a bogus alg ID */
1498 hdr->bVersion = CUR_BLOB_VERSION;
1499 hdr->aiKeyAlg = CALG_DES;
1500 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1501 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1502 &bufSize);
1503 if (buf)
1505 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1506 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1507 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1508 LocalFree(buf);
1510 /* Check a couple of RSA-related OIDs */
1511 hdr->aiKeyAlg = CALG_RSA_KEYX;
1512 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
1513 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1514 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1515 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1516 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1517 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1518 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1519 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1520 /* Finally, all valid */
1521 hdr->aiKeyAlg = CALG_RSA_KEYX;
1522 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1524 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1525 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
1526 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1527 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1528 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1529 if (buf)
1531 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
1532 "Expected size %d, got %ld\n", rsaPubKeys[i].encoded[1] + 2,
1533 bufSize);
1534 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
1535 "Unexpected value\n");
1536 LocalFree(buf);
1541 static void test_decodeRsaPublicKey(DWORD dwEncoding)
1543 DWORD i;
1544 LPBYTE buf = NULL;
1545 DWORD bufSize = 0;
1546 BOOL ret;
1548 /* Try with a bad length */
1549 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1550 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
1551 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1552 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1553 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", CRYPT_E_ASN1_EOD);
1554 /* Try with a couple of RSA-related OIDs */
1555 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
1556 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1557 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1558 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1559 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1560 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1561 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1562 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1563 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1564 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1565 /* Now try success cases */
1566 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1568 bufSize = 0;
1569 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1570 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
1571 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1572 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1573 if (buf)
1575 BLOBHEADER *hdr = (BLOBHEADER *)buf;
1576 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
1578 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1579 rsaPubKeys[i].decodedModulusLen,
1580 "Expected size at least %d, got %ld\n",
1581 sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1582 rsaPubKeys[i].decodedModulusLen, bufSize);
1583 ok(hdr->bType == PUBLICKEYBLOB,
1584 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
1585 hdr->bType);
1586 ok(hdr->bVersion == CUR_BLOB_VERSION,
1587 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
1588 CUR_BLOB_VERSION, hdr->bVersion);
1589 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
1590 hdr->reserved);
1591 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
1592 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
1593 ok(rsaPubKey->magic == 0x31415352,
1594 "Expected magic RSA1, got %08lx\n", rsaPubKey->magic);
1595 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
1596 "Expected bit len %d, got %ld\n",
1597 rsaPubKeys[i].decodedModulusLen * 8, rsaPubKey->bitlen);
1598 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %ld\n",
1599 rsaPubKey->pubexp);
1600 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1601 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
1602 "Unexpected modulus\n");
1603 LocalFree(buf);
1608 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
1609 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
1610 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1612 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
1613 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
1614 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
1615 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1617 static void test_encodeSequenceOfAny(DWORD dwEncoding)
1619 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
1620 CRYPT_SEQUENCE_OF_ANY seq;
1621 DWORD i;
1622 BOOL ret;
1623 BYTE *buf = NULL;
1624 DWORD bufSize = 0;
1626 /* Encode a homogenous sequence */
1627 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
1629 blobs[i].cbData = ints[i].encoded[1] + 2;
1630 blobs[i].pbData = (BYTE *)ints[i].encoded;
1632 seq.cValue = sizeof(ints) / sizeof(ints[0]);
1633 seq.rgValue = blobs;
1635 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1636 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1637 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1638 if (buf)
1640 ok(bufSize == sizeof(intSequence), "Expected %d bytes, got %ld\n",
1641 sizeof(intSequence), bufSize);
1642 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
1643 LocalFree(buf);
1645 /* Change the type of the first element in the sequence, and give it
1646 * another go
1648 blobs[0].cbData = times[0].encodedTime[1] + 2;
1649 blobs[0].pbData = (BYTE *)times[0].encodedTime;
1650 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1651 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1652 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1653 if (buf)
1655 ok(bufSize == sizeof(mixedSequence), "Expected %d bytes, got %ld\n",
1656 sizeof(mixedSequence), bufSize);
1657 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
1658 "Unexpected value\n");
1659 LocalFree(buf);
1663 static void test_decodeSequenceOfAny(DWORD dwEncoding)
1665 BOOL ret;
1666 BYTE *buf = NULL;
1667 DWORD bufSize = 0;
1669 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
1670 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1671 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1672 if (buf)
1674 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1675 DWORD i;
1677 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1678 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1679 seq->cValue);
1680 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
1682 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
1683 "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
1684 seq->rgValue[i].cbData);
1685 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
1686 ints[i].encoded[1] + 2), "Unexpected value\n");
1688 LocalFree(buf);
1690 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
1691 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1692 &bufSize);
1693 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1694 if (buf)
1696 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1698 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1699 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1700 seq->cValue);
1701 /* Just check the first element since it's all that changed */
1702 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
1703 "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
1704 seq->rgValue[0].cbData);
1705 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
1706 times[0].encodedTime[1] + 2), "Unexpected value\n");
1707 LocalFree(buf);
1711 struct encodedExtensions
1713 CERT_EXTENSIONS exts;
1714 const BYTE *encoded;
1717 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1718 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1720 static CERT_EXTENSION criticalExt =
1721 { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, crit_ext_data } };
1722 static CERT_EXTENSION nonCriticalExt =
1723 { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, noncrit_ext_data } };
1725 static const BYTE ext0[] = { 0x30,0x00 };
1726 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
1727 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1728 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
1729 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1731 static const struct encodedExtensions exts[] = {
1732 { { 0, NULL }, ext0 },
1733 { { 1, &criticalExt }, ext1 },
1734 { { 1, &nonCriticalExt }, ext2 },
1737 static void test_encodeExtensions(DWORD dwEncoding)
1739 DWORD i;
1741 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1743 BOOL ret;
1744 BYTE *buf = NULL;
1745 DWORD bufSize = 0;
1747 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
1748 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1749 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1750 if (buf)
1752 ok(bufSize == exts[i].encoded[1] + 2,
1753 "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
1754 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
1755 "Unexpected value\n");
1756 LocalFree(buf);
1761 static void test_decodeExtensions(DWORD dwEncoding)
1763 DWORD i;
1765 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1767 BOOL ret;
1768 BYTE *buf = NULL;
1769 DWORD bufSize = 0;
1771 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
1772 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1773 NULL, (BYTE *)&buf, &bufSize);
1774 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1775 if (buf)
1777 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
1778 DWORD j;
1780 ok(ext->cExtension == exts[i].exts.cExtension,
1781 "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
1782 ext->cExtension);
1783 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
1785 ok(!strcmp(ext->rgExtension[j].pszObjId,
1786 exts[i].exts.rgExtension[j].pszObjId),
1787 "Expected OID %s, got %s\n",
1788 exts[i].exts.rgExtension[j].pszObjId,
1789 ext->rgExtension[j].pszObjId);
1790 ok(!memcmp(ext->rgExtension[j].Value.pbData,
1791 exts[i].exts.rgExtension[j].Value.pbData,
1792 exts[i].exts.rgExtension[j].Value.cbData),
1793 "Unexpected value\n");
1795 LocalFree(buf);
1800 /* MS encodes public key info with a NULL if the algorithm identifier's
1801 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
1802 * it encodes them by omitting the algorithm parameters. This latter approach
1803 * seems more correct, so accept either form.
1805 struct encodedPublicKey
1807 CERT_PUBLIC_KEY_INFO info;
1808 const BYTE *encoded;
1809 const BYTE *encodedNoNull;
1810 CERT_PUBLIC_KEY_INFO decoded;
1813 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1814 0xe, 0xf };
1815 static const BYTE params[] = { 0x02, 0x01, 0x01 };
1817 static const unsigned char bin64[] = {
1818 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00,0};
1819 static const unsigned char bin65[] = {
1820 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00,0};
1821 static const unsigned char bin66[] = {
1822 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00,0};
1823 static const unsigned char bin67[] = {
1824 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00,0};
1825 static const unsigned char bin68[] = {
1826 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
1827 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0};
1828 static const unsigned char bin69[] = {
1829 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
1830 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0};
1831 static const unsigned char bin70[] = {
1832 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
1833 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
1834 0x0f,0};
1835 static const unsigned char bin71[] = {
1836 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
1837 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
1838 0x0f,0};
1839 static unsigned char bin72[] = { 0x05,0x00,0};
1841 static const struct encodedPublicKey pubKeys[] = {
1842 /* with a bogus OID */
1843 { { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
1844 bin64, bin65,
1845 { { "1.2.3", { 2, bin72 } }, { 0, NULL, 0 } } },
1846 /* some normal keys */
1847 { { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
1848 bin66, bin67,
1849 { { szOID_RSA, { 2, bin72 } }, { 0, NULL, 0 } } },
1850 { { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
1851 bin68, bin69,
1852 { { szOID_RSA, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
1853 /* with add'l parameters--note they must be DER-encoded */
1854 { { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1855 (BYTE *)aKey, 0 } },
1856 bin70, bin71,
1857 { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1858 (BYTE *)aKey, 0 } } },
1861 static void test_encodePublicKeyInfo(DWORD dwEncoding)
1863 DWORD i;
1865 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1867 BOOL ret;
1868 BYTE *buf = NULL;
1869 DWORD bufSize = 0;
1871 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1872 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1873 &bufSize);
1874 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1875 if (buf)
1877 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
1878 bufSize == pubKeys[i].encodedNoNull[1] + 2,
1879 "Expected %d or %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
1880 pubKeys[i].encodedNoNull[1] + 2, bufSize);
1881 if (bufSize == pubKeys[i].encoded[1] + 2)
1882 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
1883 "Unexpected value\n");
1884 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
1885 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
1886 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
1887 LocalFree(buf);
1892 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
1893 const CERT_PUBLIC_KEY_INFO *got)
1895 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
1896 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
1897 got->Algorithm.pszObjId);
1898 ok(expected->Algorithm.Parameters.cbData ==
1899 got->Algorithm.Parameters.cbData,
1900 "Expected parameters of %ld bytes, got %ld\n",
1901 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
1902 if (expected->Algorithm.Parameters.cbData)
1903 ok(!memcmp(expected->Algorithm.Parameters.pbData,
1904 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
1905 "Unexpected algorithm parameters\n");
1906 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
1907 "Expected public key of %ld bytes, got %ld\n",
1908 expected->PublicKey.cbData, got->PublicKey.cbData);
1909 if (expected->PublicKey.cbData)
1910 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
1911 got->PublicKey.cbData), "Unexpected public key value\n");
1914 static void test_decodePublicKeyInfo(DWORD dwEncoding)
1916 static const BYTE bogusPubKeyInfo[] =
1917 "\x30\x22\x30\x0d\x06\x06\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x01\x01"
1918 "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1919 "\x0f";
1920 DWORD i;
1921 BOOL ret;
1922 BYTE *buf = NULL;
1923 DWORD bufSize = 0;
1925 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1927 /* The NULL form decodes to the decoded member */
1928 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1929 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1930 NULL, (BYTE *)&buf, &bufSize);
1931 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1932 if (buf)
1934 comparePublicKeyInfo(&pubKeys[i].decoded,
1935 (CERT_PUBLIC_KEY_INFO *)buf);
1936 LocalFree(buf);
1938 /* The non-NULL form decodes to the original */
1939 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1940 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
1941 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1942 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1943 if (buf)
1945 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
1946 LocalFree(buf);
1949 /* Test with bogus (not valid DER) parameters */
1950 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1951 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1952 NULL, (BYTE *)&buf, &bufSize);
1953 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1954 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1957 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
1958 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
1959 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
1960 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
1961 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
1962 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
1963 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
1964 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
1965 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1966 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
1967 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1968 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
1969 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
1970 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1971 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
1972 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
1973 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
1974 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
1975 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
1976 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
1977 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
1978 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
1979 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
1980 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
1981 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
1982 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
1983 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
1984 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
1985 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
1986 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
1987 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
1988 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
1989 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
1990 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
1991 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
1992 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
1993 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
1994 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
1995 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
1997 /* This is the encoded form of the printable string "Juan Lang" */
1998 static const BYTE encodedCommonName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11,
1999 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c,
2000 0x61, 0x6e, 0x67, 0x00 };
2001 static const BYTE serialNum[] = { 0x01 };
2003 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2005 BOOL ret;
2006 BYTE *buf = NULL;
2007 DWORD size = 0;
2008 CERT_INFO info = { 0 };
2010 /* Test with NULL pvStructInfo */
2011 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2012 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2013 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2014 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2015 /* Test with a V1 cert */
2016 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2017 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2018 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2019 if (buf)
2021 ok(size == v1Cert[1] + 2, "Expected size %d, got %ld\n",
2022 v1Cert[1] + 2, size);
2023 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2024 LocalFree(buf);
2026 /* Test v2 cert */
2027 info.dwVersion = CERT_V2;
2028 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2029 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2030 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2031 if (buf)
2033 ok(size == sizeof(v2Cert), "Expected size %d, got %ld\n",
2034 sizeof(v2Cert), size);
2035 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2036 LocalFree(buf);
2038 /* Test v3 cert */
2039 info.dwVersion = CERT_V3;
2040 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2041 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2042 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2043 if (buf)
2045 ok(size == sizeof(v3Cert), "Expected size %d, got %ld\n",
2046 sizeof(v3Cert), size);
2047 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2048 LocalFree(buf);
2050 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2051 * API doesn't prevent it)
2053 info.dwVersion = CERT_V1;
2054 info.cExtension = 1;
2055 info.rgExtension = &criticalExt;
2056 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2057 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2058 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2059 if (buf)
2061 ok(size == sizeof(v1CertWithConstraints), "Expected size %d, got %ld\n",
2062 sizeof(v1CertWithConstraints), size);
2063 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2064 LocalFree(buf);
2066 /* test v1 cert with a serial number */
2067 info.SerialNumber.cbData = sizeof(serialNum);
2068 info.SerialNumber.pbData = (BYTE *)serialNum;
2069 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2070 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2071 if (buf)
2073 ok(size == sizeof(v1CertWithSerial), "Expected size %d, got %ld\n",
2074 sizeof(v1CertWithSerial), size);
2075 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2076 LocalFree(buf);
2078 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2079 info.Issuer.cbData = sizeof(encodedCommonName);
2080 info.Issuer.pbData = (BYTE *)encodedCommonName;
2081 info.Subject.cbData = sizeof(encodedCommonName);
2082 info.Subject.pbData = (BYTE *)encodedCommonName;
2083 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2084 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2085 if (buf)
2087 ok(size == sizeof(bigCert), "Expected size %d, got %ld\n",
2088 sizeof(bigCert), size);
2089 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2090 LocalFree(buf);
2092 /* for now, I let more interesting tests be done for each subcomponent,
2093 * rather than retesting them all here.
2097 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2099 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2100 v1CertWithConstraints, v1CertWithSerial };
2101 BOOL ret;
2102 BYTE *buf = NULL;
2103 DWORD size = 0, i;
2105 /* Test with NULL pbEncoded */
2106 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2107 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2108 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2109 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
2110 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2111 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2112 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2113 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2114 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2115 * minimum a cert must have a non-zero serial number, an issuer, and a
2116 * subject.
2118 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2120 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2121 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2122 (BYTE *)&buf, &size);
2123 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2124 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2126 /* Now check with serial number, subject and issuer specified */
2127 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2128 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2129 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2130 if (buf)
2132 CERT_INFO *info = (CERT_INFO *)buf;
2134 ok(size >= sizeof(CERT_INFO), "Expected size at least %d, got %ld\n",
2135 sizeof(CERT_INFO), size);
2136 ok(info->SerialNumber.cbData == 1,
2137 "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
2138 ok(*info->SerialNumber.pbData == *serialNum,
2139 "Expected serial number %d, got %d\n", *serialNum,
2140 *info->SerialNumber.pbData);
2141 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2142 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2143 info->Issuer.cbData);
2144 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2145 "Unexpected issuer\n");
2146 ok(info->Subject.cbData == sizeof(encodedCommonName),
2147 "Expected subject of %d bytes, got %ld\n", sizeof(encodedCommonName),
2148 info->Subject.cbData);
2149 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2150 info->Subject.cbData), "Unexpected subject\n");
2151 LocalFree(buf);
2155 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2156 0xe, 0xf };
2158 static const BYTE signedBigCert[] = {
2159 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2160 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2161 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2162 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2163 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2164 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2165 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2166 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2167 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2168 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2169 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2170 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2172 static void test_encodeCert(DWORD dwEncoding)
2174 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2175 * also that bigCert is a NULL-terminated string, so don't count its
2176 * last byte (otherwise the signed cert won't decode.)
2178 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2179 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2180 BOOL ret;
2181 BYTE *buf = NULL;
2182 DWORD bufSize = 0;
2184 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2185 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2186 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2187 if (buf)
2189 ok(bufSize == sizeof(signedBigCert), "Expected size %d, got %ld\n",
2190 sizeof(signedBigCert), bufSize);
2191 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2192 LocalFree(buf);
2196 static void test_decodeCert(DWORD dwEncoding)
2198 BOOL ret;
2199 BYTE *buf = NULL;
2200 DWORD size = 0;
2202 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2203 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2204 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2205 if (buf)
2207 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2209 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2210 "Expected cert to be %d bytes, got %ld\n", sizeof(bigCert),
2211 info->ToBeSigned.cbData);
2212 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2213 "Unexpected cert\n");
2214 ok(info->Signature.cbData == sizeof(hash),
2215 "Expected signature size %d, got %ld\n", sizeof(hash),
2216 info->Signature.cbData);
2217 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2218 "Unexpected signature\n");
2219 LocalFree(buf);
2223 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
2224 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2225 0x30, 0x5a };
2226 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2227 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
2228 0x30, 0x30, 0x30, 0x30, 0x5a };
2229 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
2230 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
2231 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
2232 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
2233 0x5a };
2234 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
2235 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2236 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
2237 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
2238 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
2239 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2240 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
2241 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2242 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
2243 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2244 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
2245 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2246 static const BYTE v1CRLWithExt[] = { 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x30,
2247 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2248 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31, 0x36,
2249 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2250 0x30, 0x2c, 0x30, 0x2a, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2251 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14,
2252 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2253 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2255 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
2257 BOOL ret;
2258 BYTE *buf = NULL;
2259 DWORD size = 0;
2260 CRL_INFO info = { 0 };
2261 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
2263 /* Test with a V1 CRL */
2264 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2265 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2266 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2267 if (buf)
2269 ok(size == sizeof(v1CRL), "Expected size %d, got %ld\n",
2270 sizeof(v1CRL), size);
2271 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
2272 LocalFree(buf);
2274 /* Test v2 CRL */
2275 info.dwVersion = CRL_V2;
2276 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2277 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2278 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2279 if (buf)
2281 ok(size == v2CRL[1] + 2, "Expected size %d, got %ld\n",
2282 v2CRL[1] + 2, size);
2283 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
2284 LocalFree(buf);
2286 /* v1 CRL with a name */
2287 info.dwVersion = CRL_V1;
2288 info.Issuer.cbData = sizeof(encodedCommonName);
2289 info.Issuer.pbData = (BYTE *)encodedCommonName;
2290 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2291 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2292 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2293 if (buf)
2295 ok(size == sizeof(v1CRLWithIssuer), "Expected size %d, got %ld\n",
2296 sizeof(v1CRLWithIssuer), size);
2297 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
2298 LocalFree(buf);
2300 /* v1 CRL with a name and a NULL entry pointer */
2301 info.cCRLEntry = 1;
2302 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2303 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2304 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2305 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2306 /* now set an empty entry */
2307 info.rgCRLEntry = &entry;
2308 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2309 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2310 if (buf)
2312 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
2313 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEmptyEntry),
2314 size);
2315 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
2316 "Got unexpected value\n");
2317 LocalFree(buf);
2319 /* an entry with a serial number */
2320 entry.SerialNumber.cbData = sizeof(serialNum);
2321 entry.SerialNumber.pbData = (BYTE *)serialNum;
2322 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2323 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2324 if (buf)
2326 ok(size == sizeof(v1CRLWithIssuerAndEntry),
2327 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEntry), size);
2328 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
2329 "Got unexpected value\n");
2330 LocalFree(buf);
2332 /* and finally, an entry with an extension */
2333 entry.cExtension = 1;
2334 entry.rgExtension = &criticalExt;
2335 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2336 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2337 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2338 if (buf)
2340 ok(size == sizeof(v1CRLWithExt), "Expected size %d, got %ld\n",
2341 sizeof(v1CRLWithExt), size);
2342 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
2343 LocalFree(buf);
2347 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
2349 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
2350 BOOL ret;
2351 BYTE *buf = NULL;
2352 DWORD size = 0, i;
2354 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
2356 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2357 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2358 (BYTE *)&buf, &size);
2359 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2360 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2362 /* at a minimum, a CRL must contain an issuer: */
2363 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2364 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2365 (BYTE *)&buf, &size);
2366 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2367 if (buf)
2369 CRL_INFO *info = (CRL_INFO *)buf;
2371 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2372 sizeof(CRL_INFO), size);
2373 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %ld\n",
2374 info->cCRLEntry);
2375 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2376 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2377 info->Issuer.cbData);
2378 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2379 "Unexpected issuer\n");
2380 LocalFree(buf);
2382 /* check decoding with an empty CRL entry */
2383 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2384 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
2385 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2386 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2387 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2388 /* with a real CRL entry */
2389 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2390 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
2391 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2392 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2393 if (buf)
2395 CRL_INFO *info = (CRL_INFO *)buf;
2396 CRL_ENTRY *entry;
2398 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2399 sizeof(CRL_INFO), size);
2400 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2401 info->cCRLEntry);
2402 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2403 entry = info->rgCRLEntry;
2404 ok(entry->SerialNumber.cbData == 1,
2405 "Expected serial number size 1, got %ld\n",
2406 entry->SerialNumber.cbData);
2407 ok(*entry->SerialNumber.pbData == *serialNum,
2408 "Expected serial number %d, got %d\n", *serialNum,
2409 *entry->SerialNumber.pbData);
2410 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2411 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2412 info->Issuer.cbData);
2413 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2414 "Unexpected issuer\n");
2416 /* and finally, with an extension */
2417 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2418 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
2419 NULL, (BYTE *)&buf, &size);
2420 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2421 if (buf)
2423 CRL_INFO *info = (CRL_INFO *)buf;
2424 CRL_ENTRY *entry;
2426 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2427 sizeof(CRL_INFO), size);
2428 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2429 info->cCRLEntry);
2430 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2431 entry = info->rgCRLEntry;
2432 ok(entry->SerialNumber.cbData == 1,
2433 "Expected serial number size 1, got %ld\n",
2434 entry->SerialNumber.cbData);
2435 ok(*entry->SerialNumber.pbData == *serialNum,
2436 "Expected serial number %d, got %d\n", *serialNum,
2437 *entry->SerialNumber.pbData);
2438 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2439 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2440 info->Issuer.cbData);
2441 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2442 "Unexpected issuer\n");
2443 /* Oddly, the extensions don't seem to be decoded. Is this just an MS
2444 * bug, or am I missing something?
2446 ok(info->cExtension == 0, "Expected 0 extensions, got %ld\n",
2447 info->cExtension);
2451 static void test_registerOIDFunction(void)
2453 static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
2454 BOOL ret;
2456 /* oddly, this succeeds under WinXP; the function name key is merely
2457 * omitted. This may be a side effect of the registry code, I don't know.
2458 * I don't check it because I doubt anyone would depend on it.
2459 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, NULL,
2460 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2462 /* On windows XP, GetLastError is incorrectly being set with an HRESULT,
2463 * HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)
2465 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", NULL, bogusDll,
2466 NULL);
2467 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() ==
2468 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)),
2469 "Expected ERROR_INVALID_PARAMETER: %ld\n", GetLastError());
2470 /* This has no effect, but "succeeds" on XP */
2471 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo",
2472 "1.2.3.4.5.6.7.8.9.10", NULL, NULL);
2473 ok(ret, "Expected pseudo-success, got %ld\n", GetLastError());
2474 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
2475 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2476 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2477 ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
2478 "1.2.3.4.5.6.7.8.9.10");
2479 ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
2480 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "bogus",
2481 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2482 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2483 ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "bogus",
2484 "1.2.3.4.5.6.7.8.9.10");
2485 ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
2486 /* This has no effect */
2487 ret = CryptRegisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
2488 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2489 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2490 /* Check with bogus encoding type: */
2491 ret = CryptRegisterOIDFunction(0, "CryptDllEncodeObject",
2492 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2493 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2494 /* This is written with value 3 verbatim. Thus, the encoding type isn't
2495 * (for now) treated as a mask.
2497 ret = CryptRegisterOIDFunction(3, "CryptDllEncodeObject",
2498 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2499 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2500 ret = CryptUnregisterOIDFunction(3, "CryptDllEncodeObject",
2501 "1.2.3.4.5.6.7.8.9.10");
2502 ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
2505 /* Free *pInfo with HeapFree */
2506 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
2508 BOOL ret;
2509 DWORD size = 0;
2510 HCRYPTKEY key;
2512 /* This crashes
2513 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
2515 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
2516 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2517 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2518 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
2519 &size);
2520 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2521 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2522 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
2523 NULL, &size);
2524 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2525 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2526 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
2527 0, NULL, NULL, &size);
2528 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2529 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2530 /* Test with no key */
2531 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
2532 0, NULL, NULL, &size);
2533 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08lx\n",
2534 GetLastError());
2535 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
2536 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
2537 if (ret)
2539 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2540 NULL, 0, NULL, NULL, &size);
2541 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
2542 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2543 if (*pInfo)
2545 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
2546 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
2547 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n",
2548 GetLastError());
2549 if (ret)
2551 /* By default (we passed NULL as the OID) the OID is
2552 * szOID_RSA_RSA.
2554 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
2555 "Expected %s, got %s\n", szOID_RSA_RSA,
2556 (*pInfo)->Algorithm.pszObjId);
2562 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
2564 BOOL ret;
2565 HCRYPTKEY key;
2567 /* These crash
2568 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
2569 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
2570 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
2571 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
2572 NULL);
2574 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
2575 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2576 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
2577 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
2578 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2579 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
2580 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
2581 &key);
2582 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2583 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2584 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
2585 &key);
2586 ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
2587 CryptDestroyKey(key);
2590 static const char cspName[] = "WineCryptTemp";
2592 static void testPortPublicKeyInfo(void)
2594 HCRYPTPROV csp;
2595 BOOL ret;
2596 PCERT_PUBLIC_KEY_INFO info = NULL;
2598 /* Just in case a previous run failed, delete this thing */
2599 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
2600 CRYPT_DELETEKEYSET);
2601 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
2602 CRYPT_NEWKEYSET);
2604 testExportPublicKey(csp, &info);
2605 testImportPublicKey(csp, info);
2607 HeapFree(GetProcessHeap(), 0, info);
2608 CryptReleaseContext(csp, 0);
2609 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
2610 CRYPT_DELETEKEYSET);
2613 START_TEST(encode)
2615 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
2616 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
2617 DWORD i;
2619 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
2621 test_encodeInt(encodings[i]);
2622 test_decodeInt(encodings[i]);
2623 test_encodeEnumerated(encodings[i]);
2624 test_decodeEnumerated(encodings[i]);
2625 test_encodeFiletime(encodings[i]);
2626 test_decodeFiletime(encodings[i]);
2627 test_encodeName(encodings[i]);
2628 test_decodeName(encodings[i]);
2629 test_encodeAltName(encodings[i]);
2630 test_decodeAltName(encodings[i]);
2631 test_encodeOctets(encodings[i]);
2632 test_decodeOctets(encodings[i]);
2633 test_encodeBits(encodings[i]);
2634 test_decodeBits(encodings[i]);
2635 test_encodeBasicConstraints(encodings[i]);
2636 test_decodeBasicConstraints(encodings[i]);
2637 test_encodeRsaPublicKey(encodings[i]);
2638 test_decodeRsaPublicKey(encodings[i]);
2639 test_encodeSequenceOfAny(encodings[i]);
2640 test_decodeSequenceOfAny(encodings[i]);
2641 test_encodeExtensions(encodings[i]);
2642 test_decodeExtensions(encodings[i]);
2643 test_encodePublicKeyInfo(encodings[i]);
2644 test_decodePublicKeyInfo(encodings[i]);
2645 test_encodeCertToBeSigned(encodings[i]);
2646 test_decodeCertToBeSigned(encodings[i]);
2647 test_encodeCert(encodings[i]);
2648 test_decodeCert(encodings[i]);
2649 test_encodeCRLToBeSigned(encodings[i]);
2650 test_decodeCRLToBeSigned(encodings[i]);
2652 test_registerOIDFunction();
2653 testPortPublicKeyInfo();