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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
35 static const BYTE bin1[] = {0x02,0x01,0x01};
36 static const BYTE bin2[] = {0x02,0x01,0x7f};
37 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
38 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
39 static const BYTE bin5[] = {0x02,0x01,0x80};
40 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
41 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
43 static const struct encodedInt ints[] = {
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)
89 CRYPT_INTEGER_BLOB blob;
92 /* CryptEncodeObjectEx with NULL bufSize crashes..
93 ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
96 /* check bogus encoding */
97 ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
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
104 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
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());
119 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
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);
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());
138 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
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);
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());
162 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
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");
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());
185 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
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");
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 };
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,
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,
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),
247 ok(buf != NULL, "Expected allocated buffer\n");
250 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
251 ints[i].val, *(int *)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,
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),
269 ok(buf != NULL, "Expected allocated buffer\n");
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", lstrlenA((const char*)bigInts[i].decoded),
277 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
278 "Unexpected value\n");
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,
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),
296 ok(buf != NULL, "Expected allocated buffer\n");
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", lstrlenA((const char*)bigUInts[i].val),
304 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
305 "Unexpected value\n");
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());
315 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)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
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};
339 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
341 /* These are always encoded unsigned, and aren't constrained to be any
344 static const struct encodedInt enums[] = {
349 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
352 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
353 szOID_CRL_REASON_CODE };
355 static void test_encodeEnumerated(DWORD dwEncoding)
359 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
361 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
367 ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
368 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
370 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
374 "Got unexpected type %d for enumerated (expected 0xa)\n",
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",
388 static void test_decodeEnumerated(DWORD dwEncoding)
392 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
394 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
397 DWORD bufSize = sizeof(int);
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",
413 struct encodedFiletime
416 const BYTE *encodedTime;
419 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
420 const struct encodedFiletime *time)
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(),
439 ok(buf != NULL, "Expected an allocated buffer\n");
442 ok(buf[0] == time->encodedTime[0],
443 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[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");
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);
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(),
476 ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
477 "Got unexpected value for time decoding\n");
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'};
486 static const BYTE bin21[] = {
487 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
488 static const BYTE bin22[] = {
489 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
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)
501 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
503 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
504 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
505 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, ×[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'};
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'};
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'};
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'};
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'};
519 static const BYTE bin28[] = {
520 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
521 static const BYTE bin29[] = {
522 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
523 static const BYTE bin30[] = {
524 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
525 static const BYTE bin31[] = {
526 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
527 static const BYTE bin32[] = {
528 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
529 static const BYTE bin33[] = {
530 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
531 static const BYTE bin34[] = {
532 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
533 static const BYTE bin35[] = {
534 0x17,0x08, '4','5','0','6','0','6','1','6'};
535 static const BYTE bin36[] = {
536 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
537 static const BYTE bin37[] = {
538 0x18,0x04, '2','1','4','5'};
539 static const BYTE bin38[] = {
540 0x18,0x08, '2','1','4','5','0','6','0','6'};
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",
571 FILETIME ft1 = { 0 }, ft2 = { 0 };
574 /* Check bogus length with non-NULL buffer */
575 ret = SystemTimeToFileTime(×[0].sysTime, &ft1);
576 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
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());
583 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
585 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
586 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
587 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, ×[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++)
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 static const char commonName[] = "Juan Lang";
606 static const char surName[] = "Lang";
608 static const BYTE emptySequence[] = { 0x30, 0 };
609 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
610 static const BYTE twoRDNs[] = {
611 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
612 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
613 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
615 static const BYTE us[] = { 0x55, 0x53 };
616 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
618 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
619 0x6f, 0x6c, 0x69, 0x73 };
620 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
621 0x76, 0x65, 0x72, 0x73 };
622 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
623 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
624 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
626 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
627 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
629 #define _blob_of(arr) { sizeof(arr), (LPBYTE)arr }
630 const CERT_RDN_ATTR rdnAttrs[] = {
631 { "2.5.4.6", CERT_RDN_PRINTABLE_STRING, _blob_of(us) },
632 { "2.5.4.8", CERT_RDN_PRINTABLE_STRING, _blob_of(minnesota) },
633 { "2.5.4.7", CERT_RDN_PRINTABLE_STRING, _blob_of(minneapolis) },
634 { "2.5.4.10", CERT_RDN_PRINTABLE_STRING, _blob_of(codeweavers) },
635 { "2.5.4.11", CERT_RDN_PRINTABLE_STRING, _blob_of(wine) },
636 { "2.5.4.3", CERT_RDN_PRINTABLE_STRING, _blob_of(localhostAttr) },
637 { "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING, _blob_of(aric) },
639 const CERT_RDN_ATTR decodedRdnAttrs[] = {
640 { "2.5.4.6", CERT_RDN_PRINTABLE_STRING, _blob_of(us) },
641 { "2.5.4.3", CERT_RDN_PRINTABLE_STRING, _blob_of(localhostAttr) },
642 { "2.5.4.8", CERT_RDN_PRINTABLE_STRING, _blob_of(minnesota) },
643 { "2.5.4.7", CERT_RDN_PRINTABLE_STRING, _blob_of(minneapolis) },
644 { "2.5.4.10", CERT_RDN_PRINTABLE_STRING, _blob_of(codeweavers) },
645 { "2.5.4.11", CERT_RDN_PRINTABLE_STRING, _blob_of(wine) },
646 { "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING, _blob_of(aric) },
650 static const BYTE encodedRDNAttrs[] = {
651 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
652 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
653 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
654 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
655 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
656 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
657 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
658 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
659 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
660 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
663 static void test_encodeName(DWORD dwEncoding)
665 CERT_RDN_ATTR attrs[2];
672 /* Test with NULL pvStructInfo */
673 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
674 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
675 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
676 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
677 /* Test with empty CERT_NAME_INFO */
680 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
681 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
682 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
685 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
686 "Got unexpected encoding for empty name\n");
689 /* Test with bogus CERT_RDN */
691 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
692 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
693 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
694 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
695 /* Test with empty CERT_RDN */
697 rdn.rgRDNAttr = NULL;
700 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
701 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
702 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
705 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
706 "Got unexpected encoding for empty RDN array\n");
709 /* Test with bogus attr array */
711 rdn.rgRDNAttr = NULL;
712 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
713 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
714 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
715 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
716 /* oddly, a bogus OID is accepted by Windows XP; not testing.
717 attrs[0].pszObjId = "bogus";
718 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
719 attrs[0].Value.cbData = sizeof(commonName);
720 attrs[0].Value.pbData = (BYTE *)commonName;
722 rdn.rgRDNAttr = attrs;
723 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
724 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
725 ok(!ret, "Expected failure, got success\n");
727 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
728 * the encoded attributes to be swapped.
730 attrs[0].pszObjId = szOID_COMMON_NAME;
731 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
732 attrs[0].Value.cbData = sizeof(commonName);
733 attrs[0].Value.pbData = (BYTE *)commonName;
734 attrs[1].pszObjId = szOID_SUR_NAME;
735 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
736 attrs[1].Value.cbData = sizeof(surName);
737 attrs[1].Value.pbData = (BYTE *)surName;
739 rdn.rgRDNAttr = attrs;
740 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
741 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
742 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
745 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
746 "Got unexpected encoding for two RDN array\n");
749 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
751 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
752 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
753 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
754 ok(!ret && GetLastError() == E_INVALIDARG,
755 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
756 /* Test a more complex name */
757 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
758 rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
763 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
764 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
765 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
768 ok(size == sizeof(encodedRDNAttrs), "Expected size %d, got %ld\n",
769 sizeof(encodedRDNAttrs), size);
770 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
775 static void compareNameValues(const CERT_NAME_VALUE *expected,
776 const CERT_NAME_VALUE *got)
778 ok(got->dwValueType == expected->dwValueType,
779 "Expected string type %ld, got %ld\n", expected->dwValueType,
781 ok(got->Value.cbData == expected->Value.cbData,
782 "Unexpected data size, got %ld, expected %ld\n", got->Value.cbData,
783 expected->Value.cbData);
784 if (got->Value.cbData && got->Value.pbData)
785 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
786 min(got->Value.cbData, expected->Value.cbData)), "Unexpected value\n");
789 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
790 const CERT_RDN_ATTR *got)
792 if (expected->pszObjId && strlen(expected->pszObjId))
794 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
798 ok(!strcmp(got->pszObjId, expected->pszObjId),
799 "Got unexpected OID %s, expected %s\n", got->pszObjId,
803 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
804 (const CERT_NAME_VALUE *)&got->dwValueType);
807 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
809 ok(got->cRDNAttr == expected->cRDNAttr,
810 "Expected %ld RDN attrs, got %ld\n", expected->cRDNAttr, got->cRDNAttr);
815 for (i = 0; i < got->cRDNAttr; i++)
816 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
820 static void compareNames(const CERT_NAME_INFO *expected,
821 const CERT_NAME_INFO *got)
823 ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
824 expected->cRDN, got->cRDN);
829 for (i = 0; i < got->cRDN; i++)
830 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
834 static void test_decodeName(DWORD dwEncoding)
840 CERT_NAME_INFO info = { 1, &rdn };
842 /* test empty name */
844 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
845 emptySequence[1] + 2,
846 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
847 (BYTE *)&buf, &bufSize);
848 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
849 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
850 * decoder works the same way, so only test the count.
854 ok(bufSize == sizeof(CERT_NAME_INFO),
855 "Expected bufSize %d, got %ld\n", sizeof(CERT_NAME_INFO), bufSize);
856 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
857 "Expected 0 RDNs in empty info, got %ld\n",
858 ((CERT_NAME_INFO *)buf)->cRDN);
863 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
865 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
866 (BYTE *)&buf, &bufSize);
867 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
870 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
872 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
873 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
874 "Got unexpected value for empty RDN\n");
877 /* test two RDN attrs */
879 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
881 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
882 (BYTE *)&buf, &bufSize);
883 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
886 CERT_RDN_ATTR attrs[] = {
887 { szOID_SUR_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
889 { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
890 (BYTE *)commonName } },
893 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
894 rdn.rgRDNAttr = attrs;
895 compareNames(&info, (CERT_NAME_INFO *)buf);
898 /* And, a slightly more complicated name */
901 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
902 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
903 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
906 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
907 rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
908 compareNames(&info, (CERT_NAME_INFO *)buf);
913 struct EncodedNameValue
915 CERT_NAME_VALUE value;
919 static const char bogusIA5[] = "\x80";
920 static const char bogusPrintable[] = "~";
921 static const char bogusNumeric[] = "A";
922 static const char bogusT61[] = "\xff";
923 static const BYTE bin39[] = { 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
925 static const BYTE bin40[] = { 0x16,0x05,0x4c,0x61,0x6e,0x67,0x00 };
926 static const BYTE bin41[] = { 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
928 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
929 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
930 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
931 static const BYTE bin45[] = { 0x14,0x02,0xff,0x00 };
933 struct EncodedNameValue nameValues[] = {
934 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
936 { { CERT_RDN_IA5_STRING, { sizeof(surName), (BYTE *)surName } }, bin40 },
937 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } }, bin41 },
938 /* The following tests succeed under Windows, but really should fail,
939 * they contain characters that are illegal for the encoding. I'm
940 * including them to justify my lazy encoding.
942 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42 },
943 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
944 (BYTE *)bogusPrintable } }, bin43 },
945 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
947 { { CERT_RDN_T61_STRING, { sizeof(bogusT61), (BYTE *)bogusT61 } }, bin45 },
951 static void test_encodeNameValue(DWORD dwEncoding)
957 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
959 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
960 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
962 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
965 ok(size == nameValues[i].encoded[1] + 2,
966 "Expected size %d, got %ld\n", nameValues[i].encoded[1] + 2, size);
967 ok(!memcmp(buf, nameValues[i].encoded, size),
968 "Got unexpected encoding\n");
974 static void test_decodeNameValue(DWORD dwEncoding)
981 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
983 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
984 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
985 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
986 (BYTE *)&buf, &bufSize);
987 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
990 compareNameValues(&nameValues[i].value,
991 (const CERT_NAME_VALUE *)buf);
997 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
998 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
999 'h','q','.','o','r','g',0 };
1000 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1001 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1003 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1005 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1006 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1007 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1008 static const BYTE localhost[] = { 127, 0, 0, 1 };
1009 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1012 static void test_encodeAltName(DWORD dwEncoding)
1014 CERT_ALT_NAME_INFO info = { 0 };
1015 CERT_ALT_NAME_ENTRY entry = { 0 };
1020 /* Test with empty info */
1021 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1022 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1025 ok(size == sizeof(emptySequence), "Expected size %d, got %ld\n",
1026 sizeof(emptySequence), size);
1027 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1030 /* Test with an empty entry */
1032 info.rgAltEntry = &entry;
1033 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1034 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1035 ok(!ret && GetLastError() == E_INVALIDARG,
1036 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1037 /* Test with an empty pointer */
1038 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1039 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1040 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1043 ok(size == sizeof(emptyURL), "Expected size %d, got %ld\n",
1044 sizeof(emptyURL), size);
1045 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1048 /* Test with a real URL */
1049 U(entry).pwszURL = (LPWSTR)url;
1050 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1051 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1054 ok(size == sizeof(encodedURL), "Expected size %d, got %ld\n",
1055 sizeof(encodedURL), size);
1056 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1059 /* Now with the URL containing an invalid IA5 char */
1060 U(entry).pwszURL = (LPWSTR)nihongoURL;
1061 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1062 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1063 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1064 "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
1065 /* The first invalid character is at index 7 */
1066 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1067 "Expected invalid char at index 7, got %ld\n",
1068 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1069 /* Now with the URL missing a scheme */
1070 U(entry).pwszURL = (LPWSTR)dnsName;
1071 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1072 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1073 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1076 /* This succeeds, but it shouldn't, so don't worry about conforming */
1079 /* Now with a DNS name */
1080 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1081 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1082 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1083 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1086 ok(size == sizeof(encodedDnsName), "Expected size %d, got %ld\n",
1087 sizeof(encodedDnsName), size);
1088 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1091 /* Test with an IP address */
1092 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1093 U(entry).IPAddress.cbData = sizeof(localhost);
1094 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1095 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1096 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1099 ok(size == sizeof(encodedIPAddr), "Expected size %d, got %ld\n",
1100 sizeof(encodedIPAddr), size);
1101 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1106 static void test_decodeAltName(DWORD dwEncoding)
1108 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1110 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1115 CERT_ALT_NAME_INFO *info;
1117 /* Test some bogus ones first */
1118 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1119 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1120 NULL, (BYTE *)&buf, &bufSize);
1121 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1122 "Expected CRYPT_E_ASN1_BADTAG, got %08lx\n", GetLastError());
1123 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1124 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1126 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1127 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1128 /* Now expected cases */
1129 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1130 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1132 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1135 info = (CERT_ALT_NAME_INFO *)buf;
1137 ok(info->cAltEntry == 0, "Expected 0 entries, got %ld\n",
1141 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1142 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1144 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1147 info = (CERT_ALT_NAME_INFO *)buf;
1149 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1151 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1152 "Expected CERT_ALT_NAME_URL, got %ld\n",
1153 info->rgAltEntry[0].dwAltNameChoice);
1154 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1155 "Expected empty URL\n");
1158 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1159 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1161 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1164 info = (CERT_ALT_NAME_INFO *)buf;
1166 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1168 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1169 "Expected CERT_ALT_NAME_URL, got %ld\n",
1170 info->rgAltEntry[0].dwAltNameChoice);
1171 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1174 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1175 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1177 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1180 info = (CERT_ALT_NAME_INFO *)buf;
1182 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1184 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1185 "Expected CERT_ALT_NAME_DNS_NAME, got %ld\n",
1186 info->rgAltEntry[0].dwAltNameChoice);
1187 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1188 "Unexpected DNS name\n");
1191 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1192 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1194 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1197 info = (CERT_ALT_NAME_INFO *)buf;
1199 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1201 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1202 "Expected CERT_ALT_NAME_IP_ADDRESS, got %ld\n",
1203 info->rgAltEntry[0].dwAltNameChoice);
1204 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1205 "Unexpected IP address length %ld\n",
1206 U(info->rgAltEntry[0]).IPAddress.cbData);
1207 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1208 sizeof(localhost)), "Unexpected IP address value\n");
1213 struct encodedOctets
1216 const BYTE *encoded;
1219 static const unsigned char bin46[] = { 'h','i',0 };
1220 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1221 static const unsigned char bin48[] = {
1222 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1223 static const unsigned char bin49[] = {
1224 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1225 static const unsigned char bin50[] = { 0 };
1226 static const unsigned char bin51[] = { 0x04,0x00,0 };
1228 static const struct encodedOctets octets[] = {
1234 static void test_encodeOctets(DWORD dwEncoding)
1236 CRYPT_DATA_BLOB blob;
1239 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1245 blob.cbData = strlen((const char*)octets[i].val);
1246 blob.pbData = (BYTE*)octets[i].val;
1247 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1248 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1249 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
1253 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1254 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1255 buf[1], octets[i].encoded[1]);
1256 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1257 octets[i].encoded[1] + 1), "Got unexpected value\n");
1263 static void test_decodeOctets(DWORD dwEncoding)
1267 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1273 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1274 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1275 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1276 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1277 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1278 "Expected size >= %d, got %ld\n",
1279 sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1280 ok(buf != NULL, "Expected allocated buffer\n");
1283 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1286 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1287 "Unexpected value\n");
1293 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1298 const BYTE *encoded;
1300 const BYTE *decoded;
1303 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1304 static const unsigned char bin53[] = { 0xff,0xff };
1305 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1306 static const unsigned char bin55[] = { 0xff,0xfe };
1307 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1308 static const unsigned char bin57[] = { 0xfe };
1309 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1311 static const struct encodedBits bits[] = {
1312 /* normal test cases */
1313 { 0, bin52, 2, bin53 },
1314 { 1, bin54, 2, bin55 },
1315 /* strange test case, showing cUnusedBits >= 8 is allowed */
1316 { 9, bin56, 1, bin57 },
1317 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1318 { 17, bin58, 0, NULL },
1321 static void test_encodeBits(DWORD dwEncoding)
1325 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1327 CRYPT_BIT_BLOB blob;
1332 blob.cbData = sizeof(bytesToEncode);
1333 blob.pbData = (BYTE *)bytesToEncode;
1334 blob.cUnusedBits = bits[i].cUnusedBits;
1335 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1336 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1337 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1340 ok(bufSize == bits[i].encoded[1] + 2,
1341 "Got unexpected size %ld, expected %d\n", bufSize,
1342 bits[i].encoded[1] + 2);
1343 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1344 "Unexpected value\n");
1350 static void test_decodeBits(DWORD dwEncoding)
1352 static const BYTE ber[] = "\x03\x02\x01\xff";
1353 static const BYTE berDecoded = 0xfe;
1360 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1362 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1363 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1365 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1368 CRYPT_BIT_BLOB *blob;
1370 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1371 "Got unexpected size %ld, expected >= %ld\n", bufSize,
1372 sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
1373 blob = (CRYPT_BIT_BLOB *)buf;
1374 ok(blob->cbData == bits[i].cbDecoded,
1375 "Got unexpected length %ld, expected %ld\n", blob->cbData,
1377 if (blob->cbData && bits[i].cbDecoded)
1378 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1379 "Unexpected value\n");
1383 /* special case: check that something that's valid in BER but not in DER
1384 * decodes successfully
1386 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1387 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1388 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1391 CRYPT_BIT_BLOB *blob;
1393 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1394 "Got unexpected size %ld, expected >= %d\n", bufSize,
1395 sizeof(CRYPT_BIT_BLOB) + berDecoded);
1396 blob = (CRYPT_BIT_BLOB *)buf;
1397 ok(blob->cbData == sizeof(berDecoded),
1398 "Got unexpected length %ld, expected %d\n", blob->cbData,
1399 sizeof(berDecoded));
1401 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1408 CERT_BASIC_CONSTRAINTS2_INFO info;
1409 const BYTE *encoded;
1412 static const unsigned char bin59[] = { 0x30,0x00 };
1413 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1414 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1415 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1416 static const struct Constraints2 constraints2[] = {
1417 /* empty constraints */
1418 { { FALSE, FALSE, 0}, bin59 },
1420 { { TRUE, FALSE, 0}, bin60 },
1421 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1422 * but that's not the case
1424 { { FALSE, TRUE, 0}, bin61 },
1425 /* can be a CA and has path length constraints set */
1426 { { TRUE, TRUE, 1}, bin62 },
1429 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1430 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1431 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1432 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1433 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1434 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1435 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1436 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1437 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1438 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1440 static void test_encodeBasicConstraints(DWORD dwEncoding)
1442 DWORD i, bufSize = 0;
1443 CERT_BASIC_CONSTRAINTS_INFO info;
1444 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1445 (LPBYTE)encodedDomainName };
1449 /* First test with the simpler info2 */
1450 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1452 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1453 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1455 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1458 ok(bufSize == constraints2[i].encoded[1] + 2,
1459 "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1461 ok(!memcmp(buf, constraints2[i].encoded,
1462 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1466 /* Now test with more complex basic constraints */
1467 info.SubjectType.cbData = 0;
1468 info.fPathLenConstraint = FALSE;
1469 info.cSubtreesConstraint = 0;
1470 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1471 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1472 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1475 ok(bufSize == sizeof(emptyConstraint), "Expected %d bytes, got %ld\n",
1476 sizeof(emptyConstraint), bufSize);
1477 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1478 "Unexpected value\n");
1481 /* None of the certs I examined had any subtree constraint, but I test one
1482 * anyway just in case.
1484 info.cSubtreesConstraint = 1;
1485 info.rgSubtreesConstraint = &nameBlob;
1486 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1487 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1488 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1491 ok(bufSize == sizeof(constraintWithDomainName),
1492 "Expected %d bytes, got %ld\n", sizeof(constraintWithDomainName),
1494 ok(!memcmp(buf, constraintWithDomainName,
1495 sizeof(constraintWithDomainName)), "Unexpected value\n");
1498 /* FIXME: test encoding with subject type. */
1501 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1502 static const unsigned char encodedCommonName[] = {
1503 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1505 static void test_decodeBasicConstraints(DWORD dwEncoding)
1507 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1509 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1515 /* First test with simpler info2 */
1516 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1518 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1519 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1520 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1521 ok(ret, "CryptDecodeObjectEx failed for item %ld: %08lx\n", i,
1525 CERT_BASIC_CONSTRAINTS2_INFO *info =
1526 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1528 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1529 "Unexpected value for item %ld\n", i);
1533 /* Check with the order of encoded elements inverted */
1535 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1536 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1538 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1539 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1540 ok(!buf, "Expected buf to be set to NULL\n");
1541 /* Check with a non-DER bool */
1542 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1543 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1544 (BYTE *)&buf, &bufSize);
1545 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1548 CERT_BASIC_CONSTRAINTS2_INFO *info =
1549 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1551 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1554 /* Check with a non-basic constraints value */
1555 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1556 (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
1557 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1558 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1559 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1560 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
1561 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
1562 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
1563 (BYTE *)&buf, &bufSize);
1564 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1567 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
1569 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
1570 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
1571 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
1574 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
1575 constraintWithDomainName, sizeof(constraintWithDomainName),
1576 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1577 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1580 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
1582 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
1583 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
1584 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
1585 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
1587 ok(info->rgSubtreesConstraint[0].cbData ==
1588 sizeof(encodedDomainName), "Expected %d bytes, got %ld\n",
1589 sizeof(encodedDomainName), info->rgSubtreesConstraint[0].cbData);
1590 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
1591 sizeof(encodedDomainName)), "Unexpected value\n");
1597 /* These are terrible public keys of course, I'm just testing encoding */
1598 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
1599 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
1600 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
1601 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
1602 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
1603 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1604 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
1605 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1607 struct EncodedRSAPubKey
1609 const BYTE *modulus;
1611 const BYTE *encoded;
1612 size_t decodedModulusLen;
1615 struct EncodedRSAPubKey rsaPubKeys[] = {
1616 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
1617 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
1618 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
1619 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
1622 static void test_encodeRsaPublicKey(DWORD dwEncoding)
1624 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
1625 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
1626 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
1629 DWORD bufSize = 0, i;
1631 /* Try with a bogus blob type */
1633 hdr->bVersion = CUR_BLOB_VERSION;
1635 hdr->aiKeyAlg = CALG_RSA_KEYX;
1636 rsaPubKey->magic = 0x31415352;
1637 rsaPubKey->bitlen = sizeof(modulus1) * 8;
1638 rsaPubKey->pubexp = 65537;
1639 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
1642 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1643 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1645 ok(!ret && GetLastError() == E_INVALIDARG,
1646 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1647 /* Now with a bogus reserved field */
1648 hdr->bType = PUBLICKEYBLOB;
1650 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1651 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1655 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1656 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1657 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1660 /* Now with a bogus blob version */
1663 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1664 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1668 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1669 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1670 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1673 /* And with a bogus alg ID */
1674 hdr->bVersion = CUR_BLOB_VERSION;
1675 hdr->aiKeyAlg = CALG_DES;
1676 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1677 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1681 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1682 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1683 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1686 /* Check a couple of RSA-related OIDs */
1687 hdr->aiKeyAlg = CALG_RSA_KEYX;
1688 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
1689 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1690 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1691 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1692 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1693 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1694 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1695 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1696 /* Finally, all valid */
1697 hdr->aiKeyAlg = CALG_RSA_KEYX;
1698 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1700 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1701 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
1702 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1703 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1704 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1707 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
1708 "Expected size %d, got %ld\n", rsaPubKeys[i].encoded[1] + 2,
1710 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
1711 "Unexpected value\n");
1717 static void test_decodeRsaPublicKey(DWORD dwEncoding)
1724 /* Try with a bad length */
1725 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1726 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
1727 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1728 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1729 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", CRYPT_E_ASN1_EOD);
1730 /* Try with a couple of RSA-related OIDs */
1731 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
1732 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1733 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1734 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1735 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1736 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1737 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1738 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1739 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1740 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1741 /* Now try success cases */
1742 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1745 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1746 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
1747 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1748 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1751 BLOBHEADER *hdr = (BLOBHEADER *)buf;
1752 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
1754 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1755 rsaPubKeys[i].decodedModulusLen,
1756 "Expected size at least %d, got %ld\n",
1757 sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1758 rsaPubKeys[i].decodedModulusLen, bufSize);
1759 ok(hdr->bType == PUBLICKEYBLOB,
1760 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
1762 ok(hdr->bVersion == CUR_BLOB_VERSION,
1763 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
1764 CUR_BLOB_VERSION, hdr->bVersion);
1765 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
1767 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
1768 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
1769 ok(rsaPubKey->magic == 0x31415352,
1770 "Expected magic RSA1, got %08lx\n", rsaPubKey->magic);
1771 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
1772 "Expected bit len %d, got %ld\n",
1773 rsaPubKeys[i].decodedModulusLen * 8, rsaPubKey->bitlen);
1774 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %ld\n",
1776 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1777 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
1778 "Unexpected modulus\n");
1784 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
1785 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
1786 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1788 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
1789 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
1790 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
1791 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1793 static void test_encodeSequenceOfAny(DWORD dwEncoding)
1795 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
1796 CRYPT_SEQUENCE_OF_ANY seq;
1802 /* Encode a homogenous sequence */
1803 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
1805 blobs[i].cbData = ints[i].encoded[1] + 2;
1806 blobs[i].pbData = (BYTE *)ints[i].encoded;
1808 seq.cValue = sizeof(ints) / sizeof(ints[0]);
1809 seq.rgValue = blobs;
1811 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1812 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1813 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1816 ok(bufSize == sizeof(intSequence), "Expected %d bytes, got %ld\n",
1817 sizeof(intSequence), bufSize);
1818 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
1821 /* Change the type of the first element in the sequence, and give it
1824 blobs[0].cbData = times[0].encodedTime[1] + 2;
1825 blobs[0].pbData = (BYTE *)times[0].encodedTime;
1826 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1827 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1828 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1831 ok(bufSize == sizeof(mixedSequence), "Expected %d bytes, got %ld\n",
1832 sizeof(mixedSequence), bufSize);
1833 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
1834 "Unexpected value\n");
1839 static void test_decodeSequenceOfAny(DWORD dwEncoding)
1845 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
1846 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1847 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1850 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1853 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1854 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1856 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
1858 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
1859 "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
1860 seq->rgValue[i].cbData);
1861 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
1862 ints[i].encoded[1] + 2), "Unexpected value\n");
1866 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
1867 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1869 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1872 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1874 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1875 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1877 /* Just check the first element since it's all that changed */
1878 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
1879 "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
1880 seq->rgValue[0].cbData);
1881 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
1882 times[0].encodedTime[1] + 2), "Unexpected value\n");
1887 struct encodedExtensions
1889 CERT_EXTENSIONS exts;
1890 const BYTE *encoded;
1893 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1894 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1896 static CERT_EXTENSION criticalExt =
1897 { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, crit_ext_data } };
1898 static CERT_EXTENSION nonCriticalExt =
1899 { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, noncrit_ext_data } };
1901 static const BYTE ext0[] = { 0x30,0x00 };
1902 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
1903 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1904 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
1905 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1907 static const struct encodedExtensions exts[] = {
1908 { { 0, NULL }, ext0 },
1909 { { 1, &criticalExt }, ext1 },
1910 { { 1, &nonCriticalExt }, ext2 },
1913 static void test_encodeExtensions(DWORD dwEncoding)
1917 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1923 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
1924 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1925 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1928 ok(bufSize == exts[i].encoded[1] + 2,
1929 "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
1930 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
1931 "Unexpected value\n");
1937 static void test_decodeExtensions(DWORD dwEncoding)
1941 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1947 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
1948 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1949 NULL, (BYTE *)&buf, &bufSize);
1950 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1953 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
1956 ok(ext->cExtension == exts[i].exts.cExtension,
1957 "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
1959 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
1961 ok(!strcmp(ext->rgExtension[j].pszObjId,
1962 exts[i].exts.rgExtension[j].pszObjId),
1963 "Expected OID %s, got %s\n",
1964 exts[i].exts.rgExtension[j].pszObjId,
1965 ext->rgExtension[j].pszObjId);
1966 ok(!memcmp(ext->rgExtension[j].Value.pbData,
1967 exts[i].exts.rgExtension[j].Value.pbData,
1968 exts[i].exts.rgExtension[j].Value.cbData),
1969 "Unexpected value\n");
1976 /* MS encodes public key info with a NULL if the algorithm identifier's
1977 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
1978 * it encodes them by omitting the algorithm parameters. This latter approach
1979 * seems more correct, so accept either form.
1981 struct encodedPublicKey
1983 CERT_PUBLIC_KEY_INFO info;
1984 const BYTE *encoded;
1985 const BYTE *encodedNoNull;
1986 CERT_PUBLIC_KEY_INFO decoded;
1989 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1991 static const BYTE params[] = { 0x02, 0x01, 0x01 };
1993 static const unsigned char bin64[] = {
1994 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
1995 static const unsigned char bin65[] = {
1996 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
1997 static const unsigned char bin66[] = {
1998 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
1999 static const unsigned char bin67[] = {
2000 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2001 static const unsigned char bin68[] = {
2002 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2003 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2004 static const unsigned char bin69[] = {
2005 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2006 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2007 static const unsigned char bin70[] = {
2008 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2009 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2011 static const unsigned char bin71[] = {
2012 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2013 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2015 static unsigned char bin72[] = { 0x05,0x00};
2017 static const struct encodedPublicKey pubKeys[] = {
2018 /* with a bogus OID */
2019 { { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
2021 { { "1.2.3", { 2, bin72 } }, { 0, NULL, 0 } } },
2022 /* some normal keys */
2023 { { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
2025 { { szOID_RSA, { 2, bin72 } }, { 0, NULL, 0 } } },
2026 { { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2028 { { szOID_RSA, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2029 /* with add'l parameters--note they must be DER-encoded */
2030 { { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2031 (BYTE *)aKey, 0 } },
2033 { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2034 (BYTE *)aKey, 0 } } },
2037 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2041 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2047 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2048 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2050 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2053 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2054 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2055 "Expected %d or %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
2056 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2057 if (bufSize == pubKeys[i].encoded[1] + 2)
2058 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2059 "Unexpected value\n");
2060 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2061 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2062 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2068 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2069 const CERT_PUBLIC_KEY_INFO *got)
2071 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2072 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2073 got->Algorithm.pszObjId);
2074 ok(expected->Algorithm.Parameters.cbData ==
2075 got->Algorithm.Parameters.cbData,
2076 "Expected parameters of %ld bytes, got %ld\n",
2077 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2078 if (expected->Algorithm.Parameters.cbData)
2079 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2080 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2081 "Unexpected algorithm parameters\n");
2082 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2083 "Expected public key of %ld bytes, got %ld\n",
2084 expected->PublicKey.cbData, got->PublicKey.cbData);
2085 if (expected->PublicKey.cbData)
2086 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2087 got->PublicKey.cbData), "Unexpected public key value\n");
2090 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2092 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2093 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2094 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2095 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2101 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2103 /* The NULL form decodes to the decoded member */
2104 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2105 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2106 NULL, (BYTE *)&buf, &bufSize);
2107 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2110 comparePublicKeyInfo(&pubKeys[i].decoded,
2111 (CERT_PUBLIC_KEY_INFO *)buf);
2114 /* The non-NULL form decodes to the original */
2115 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2116 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2117 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2118 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2121 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2125 /* Test with bogus (not valid DER) parameters */
2126 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2127 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2128 NULL, (BYTE *)&buf, &bufSize);
2129 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2130 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2133 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2134 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2135 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2136 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2137 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2138 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2139 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2140 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2141 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2142 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2143 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2144 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2145 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2146 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2147 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2148 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2149 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2150 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2151 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2152 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2153 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2154 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2155 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2156 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2157 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2158 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2159 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2160 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2161 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2162 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2163 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2164 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2165 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2166 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2167 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2168 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2169 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2170 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2171 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2173 static const BYTE serialNum[] = { 0x01 };
2175 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2180 CERT_INFO info = { 0 };
2182 /* Test with NULL pvStructInfo */
2183 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2184 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2185 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2186 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2187 /* Test with a V1 cert */
2188 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2189 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2190 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2193 ok(size == v1Cert[1] + 2, "Expected size %d, got %ld\n",
2194 v1Cert[1] + 2, size);
2195 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2199 info.dwVersion = CERT_V2;
2200 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2201 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2202 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2205 ok(size == sizeof(v2Cert), "Expected size %d, got %ld\n",
2206 sizeof(v2Cert), size);
2207 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2211 info.dwVersion = CERT_V3;
2212 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2213 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2214 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2217 ok(size == sizeof(v3Cert), "Expected size %d, got %ld\n",
2218 sizeof(v3Cert), size);
2219 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2222 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2223 * API doesn't prevent it)
2225 info.dwVersion = CERT_V1;
2226 info.cExtension = 1;
2227 info.rgExtension = &criticalExt;
2228 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2229 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2230 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2233 ok(size == sizeof(v1CertWithConstraints), "Expected size %d, got %ld\n",
2234 sizeof(v1CertWithConstraints), size);
2235 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2238 /* test v1 cert with a serial number */
2239 info.SerialNumber.cbData = sizeof(serialNum);
2240 info.SerialNumber.pbData = (BYTE *)serialNum;
2241 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2242 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2245 ok(size == sizeof(v1CertWithSerial), "Expected size %d, got %ld\n",
2246 sizeof(v1CertWithSerial), size);
2247 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2250 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2251 info.Issuer.cbData = sizeof(encodedCommonName);
2252 info.Issuer.pbData = (BYTE *)encodedCommonName;
2253 info.Subject.cbData = sizeof(encodedCommonName);
2254 info.Subject.pbData = (BYTE *)encodedCommonName;
2255 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2256 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2259 ok(size == sizeof(bigCert), "Expected size %d, got %ld\n",
2260 sizeof(bigCert), size);
2261 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2264 /* for now, I let more interesting tests be done for each subcomponent,
2265 * rather than retesting them all here.
2269 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2271 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2272 v1CertWithConstraints, v1CertWithSerial };
2277 /* Test with NULL pbEncoded */
2278 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2279 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2280 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2281 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
2282 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2283 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2284 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2285 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2286 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2287 * minimum a cert must have a non-zero serial number, an issuer, and a
2290 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2292 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2293 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2294 (BYTE *)&buf, &size);
2295 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2296 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2298 /* Now check with serial number, subject and issuer specified */
2299 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2300 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2301 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2304 CERT_INFO *info = (CERT_INFO *)buf;
2306 ok(size >= sizeof(CERT_INFO), "Expected size at least %d, got %ld\n",
2307 sizeof(CERT_INFO), size);
2308 ok(info->SerialNumber.cbData == 1,
2309 "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
2310 ok(*info->SerialNumber.pbData == *serialNum,
2311 "Expected serial number %d, got %d\n", *serialNum,
2312 *info->SerialNumber.pbData);
2313 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2314 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2315 info->Issuer.cbData);
2316 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2317 "Unexpected issuer\n");
2318 ok(info->Subject.cbData == sizeof(encodedCommonName),
2319 "Expected subject of %d bytes, got %ld\n", sizeof(encodedCommonName),
2320 info->Subject.cbData);
2321 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2322 info->Subject.cbData), "Unexpected subject\n");
2327 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2330 static const BYTE signedBigCert[] = {
2331 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2332 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2333 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2334 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2335 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2336 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2337 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2338 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2339 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2340 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2341 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2342 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2344 static void test_encodeCert(DWORD dwEncoding)
2346 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2347 * also that bigCert is a NULL-terminated string, so don't count its
2348 * last byte (otherwise the signed cert won't decode.)
2350 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2351 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2356 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2357 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2358 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2361 ok(bufSize == sizeof(signedBigCert), "Expected size %d, got %ld\n",
2362 sizeof(signedBigCert), bufSize);
2363 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2368 static void test_decodeCert(DWORD dwEncoding)
2374 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2375 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2376 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2379 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2381 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2382 "Expected cert to be %d bytes, got %ld\n", sizeof(bigCert),
2383 info->ToBeSigned.cbData);
2384 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2385 "Unexpected cert\n");
2386 ok(info->Signature.cbData == sizeof(hash),
2387 "Expected signature size %d, got %ld\n", sizeof(hash),
2388 info->Signature.cbData);
2389 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2390 "Unexpected signature\n");
2395 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2396 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2397 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2398 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2399 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2401 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2402 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2403 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2404 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2405 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2406 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2407 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2408 0x2e, 0x6f, 0x72, 0x67 };
2409 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2410 CRL_REASON_AFFILIATION_CHANGED;
2412 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2414 CRL_DIST_POINTS_INFO info = { 0 };
2415 CRL_DIST_POINT point = { { 0 } };
2416 CERT_ALT_NAME_ENTRY entry = { 0 };
2421 /* Test with an empty info */
2422 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2423 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2424 ok(!ret && GetLastError() == E_INVALIDARG,
2425 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2426 /* Test with one empty dist point */
2427 info.cDistPoint = 1;
2428 info.rgDistPoint = &point;
2429 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2430 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2433 ok(size == sizeof(emptyDistPoint), "Expected size %d, got %ld\n",
2434 sizeof(emptyDistPoint), size);
2435 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2438 /* A dist point with an invalid name */
2439 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2440 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2441 U(entry).pwszURL = (LPWSTR)nihongoURL;
2442 U(point.DistPointName).FullName.cAltEntry = 1;
2443 U(point.DistPointName).FullName.rgAltEntry = &entry;
2444 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2445 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2446 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2447 "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
2448 /* The first invalid character is at index 7 */
2449 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2450 "Expected invalid char at index 7, got %ld\n",
2451 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2452 /* A dist point with (just) a valid name */
2453 U(entry).pwszURL = (LPWSTR)url;
2454 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2455 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2458 ok(size == sizeof(distPointWithUrl), "Expected size %d, got %ld\n",
2459 sizeof(distPointWithUrl), size);
2460 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2463 /* A dist point with (just) reason flags */
2464 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2465 point.ReasonFlags.cbData = sizeof(crlReason);
2466 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2467 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2468 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2471 ok(size == sizeof(distPointWithReason), "Expected size %d, got %ld\n",
2472 sizeof(distPointWithReason), size);
2473 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2476 /* A dist point with just an issuer */
2477 point.ReasonFlags.cbData = 0;
2478 point.CRLIssuer.cAltEntry = 1;
2479 point.CRLIssuer.rgAltEntry = &entry;
2480 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2481 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2484 ok(size == sizeof(distPointWithIssuer), "Expected size %d, got %ld\n",
2485 sizeof(distPointWithIssuer), size);
2486 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2489 /* A dist point with both a name and an issuer */
2490 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2491 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2492 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2495 ok(size == sizeof(distPointWithUrlAndIssuer),
2496 "Expected size %d, got %ld\n", sizeof(distPointWithUrlAndIssuer),
2498 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2503 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2508 PCRL_DIST_POINTS_INFO info;
2509 PCRL_DIST_POINT point;
2510 PCERT_ALT_NAME_ENTRY entry;
2512 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2513 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2514 (BYTE *)&buf, &size);
2517 info = (PCRL_DIST_POINTS_INFO)buf;
2518 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2519 "Expected size at least %d, got %ld\n",
2520 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2521 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2523 point = info->rgDistPoint;
2524 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2525 "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2526 point->DistPointName.dwDistPointNameChoice);
2527 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2528 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2531 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2532 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2533 (BYTE *)&buf, &size);
2536 info = (PCRL_DIST_POINTS_INFO)buf;
2537 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2538 "Expected size at least %d, got %ld\n",
2539 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2540 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2542 point = info->rgDistPoint;
2543 ok(point->DistPointName.dwDistPointNameChoice ==
2544 CRL_DIST_POINT_FULL_NAME,
2545 "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2546 point->DistPointName.dwDistPointNameChoice);
2547 ok(U(point->DistPointName).FullName.cAltEntry == 1,
2548 "Expected 1 name entry, got %ld\n",
2549 U(point->DistPointName).FullName.cAltEntry);
2550 entry = U(point->DistPointName).FullName.rgAltEntry;
2551 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2552 "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2553 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2554 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2555 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2558 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2559 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2560 NULL, (BYTE *)&buf, &size);
2563 info = (PCRL_DIST_POINTS_INFO)buf;
2564 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2565 "Expected size at least %d, got %ld\n",
2566 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2567 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2569 point = info->rgDistPoint;
2570 ok(point->DistPointName.dwDistPointNameChoice ==
2571 CRL_DIST_POINT_NO_NAME,
2572 "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2573 point->DistPointName.dwDistPointNameChoice);
2574 ok(point->ReasonFlags.cbData == sizeof(crlReason),
2575 "Expected reason length\n");
2576 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
2577 "Unexpected reason\n");
2578 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2581 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2582 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
2583 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2586 info = (PCRL_DIST_POINTS_INFO)buf;
2587 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2588 "Expected size at least %d, got %ld\n",
2589 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2590 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2592 point = info->rgDistPoint;
2593 ok(point->DistPointName.dwDistPointNameChoice ==
2594 CRL_DIST_POINT_FULL_NAME,
2595 "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2596 point->DistPointName.dwDistPointNameChoice);
2597 ok(U(point->DistPointName).FullName.cAltEntry == 1,
2598 "Expected 1 name entry, got %ld\n",
2599 U(point->DistPointName).FullName.cAltEntry);
2600 entry = U(point->DistPointName).FullName.rgAltEntry;
2601 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2602 "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2603 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2604 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2605 ok(point->CRLIssuer.cAltEntry == 1,
2606 "Expected 1 issuer entry, got %ld\n", point->CRLIssuer.cAltEntry);
2607 entry = point->CRLIssuer.rgAltEntry;
2608 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2609 "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2610 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2615 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
2616 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2618 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2619 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
2620 0x30, 0x30, 0x30, 0x30, 0x5a };
2621 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
2622 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
2623 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
2624 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
2626 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
2627 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2628 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
2629 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
2630 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
2631 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2632 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
2633 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2634 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
2635 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2636 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
2637 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2638 static const BYTE v1CRLWithExt[] = { 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x30,
2639 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2640 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31, 0x36,
2641 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2642 0x30, 0x2c, 0x30, 0x2a, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2643 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14,
2644 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2645 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2646 static const BYTE v2CRLWithExt[] = { 0x30, 0x5a, 0x02, 0x01, 0x01, 0x30, 0x02,
2647 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2648 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
2649 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
2650 0x30, 0x30, 0x5a, 0x30, 0x29, 0x30, 0x27, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31,
2651 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
2652 0x5a, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30,
2653 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2656 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
2661 CRL_INFO info = { 0 };
2662 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
2664 /* Test with a V1 CRL */
2665 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2666 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2667 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2670 ok(size == sizeof(v1CRL), "Expected size %d, got %ld\n",
2671 sizeof(v1CRL), size);
2672 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
2676 info.dwVersion = CRL_V2;
2677 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2678 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2679 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2682 ok(size == v2CRL[1] + 2, "Expected size %d, got %ld\n",
2683 v2CRL[1] + 2, size);
2684 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
2687 /* v1 CRL with a name */
2688 info.dwVersion = CRL_V1;
2689 info.Issuer.cbData = sizeof(encodedCommonName);
2690 info.Issuer.pbData = (BYTE *)encodedCommonName;
2691 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2692 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2693 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2696 ok(size == sizeof(v1CRLWithIssuer), "Expected size %d, got %ld\n",
2697 sizeof(v1CRLWithIssuer), size);
2698 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
2701 /* v1 CRL with a name and a NULL entry pointer */
2703 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2704 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2705 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2706 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2707 /* now set an empty entry */
2708 info.rgCRLEntry = &entry;
2709 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2710 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2713 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
2714 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEmptyEntry),
2716 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
2717 "Got unexpected value\n");
2720 /* an entry with a serial number */
2721 entry.SerialNumber.cbData = sizeof(serialNum);
2722 entry.SerialNumber.pbData = (BYTE *)serialNum;
2723 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2724 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2727 ok(size == sizeof(v1CRLWithIssuerAndEntry),
2728 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEntry), size);
2729 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
2730 "Got unexpected value\n");
2733 /* an entry with an extension */
2734 entry.cExtension = 1;
2735 entry.rgExtension = &criticalExt;
2736 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2737 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2738 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2741 ok(size == sizeof(v1CRLWithExt), "Expected size %d, got %ld\n",
2742 sizeof(v1CRLWithExt), size);
2743 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
2746 /* a v2 CRL with an extension, this time non-critical */
2747 info.dwVersion = CRL_V2;
2748 entry.rgExtension = &nonCriticalExt;
2749 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2750 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2751 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2754 ok(size == sizeof(v2CRLWithExt), "Expected size %d, got %ld\n",
2755 sizeof(v2CRLWithExt), size);
2756 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
2761 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
2762 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
2763 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
2764 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
2765 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
2766 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
2767 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
2768 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
2769 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
2770 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
2771 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
2772 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
2773 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
2774 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
2775 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
2776 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
2777 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
2778 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
2779 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
2780 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
2781 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
2782 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
2783 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
2784 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
2785 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
2786 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
2787 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
2788 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
2789 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
2790 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
2791 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
2792 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
2793 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
2794 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
2797 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
2799 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
2804 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
2806 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2807 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2808 (BYTE *)&buf, &size);
2809 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2810 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2812 /* at a minimum, a CRL must contain an issuer: */
2813 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2814 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2815 (BYTE *)&buf, &size);
2816 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2819 CRL_INFO *info = (CRL_INFO *)buf;
2821 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2822 sizeof(CRL_INFO), size);
2823 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %ld\n",
2825 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2826 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2827 info->Issuer.cbData);
2828 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2829 "Unexpected issuer\n");
2832 /* check decoding with an empty CRL entry */
2833 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2834 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
2835 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2836 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2837 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2838 /* with a real CRL entry */
2839 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2840 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
2841 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2842 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2845 CRL_INFO *info = (CRL_INFO *)buf;
2848 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2849 sizeof(CRL_INFO), size);
2850 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2852 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2853 entry = info->rgCRLEntry;
2854 ok(entry->SerialNumber.cbData == 1,
2855 "Expected serial number size 1, got %ld\n",
2856 entry->SerialNumber.cbData);
2857 ok(*entry->SerialNumber.pbData == *serialNum,
2858 "Expected serial number %d, got %d\n", *serialNum,
2859 *entry->SerialNumber.pbData);
2860 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2861 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2862 info->Issuer.cbData);
2863 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2864 "Unexpected issuer\n");
2866 /* a real CRL from verisign that has extensions */
2867 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2868 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
2869 NULL, (BYTE *)&buf, &size);
2870 todo_wine ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2873 CRL_INFO *info = (CRL_INFO *)buf;
2876 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2877 sizeof(CRL_INFO), size);
2878 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %ld\n",
2880 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2881 entry = info->rgCRLEntry;
2882 ok(info->cExtension == 2, "Expected 2 extensions, got %ld\n",
2885 /* and finally, with an extension */
2886 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2887 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
2888 NULL, (BYTE *)&buf, &size);
2889 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2892 CRL_INFO *info = (CRL_INFO *)buf;
2895 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2896 sizeof(CRL_INFO), size);
2897 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2899 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2900 entry = info->rgCRLEntry;
2901 ok(entry->SerialNumber.cbData == 1,
2902 "Expected serial number size 1, got %ld\n",
2903 entry->SerialNumber.cbData);
2904 ok(*entry->SerialNumber.pbData == *serialNum,
2905 "Expected serial number %d, got %d\n", *serialNum,
2906 *entry->SerialNumber.pbData);
2907 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2908 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2909 info->Issuer.cbData);
2910 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2911 "Unexpected issuer\n");
2912 /* Oddly, the extensions don't seem to be decoded. Is this just an MS
2913 * bug, or am I missing something?
2915 ok(info->cExtension == 0, "Expected 0 extensions, got %ld\n",
2918 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2919 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
2920 NULL, (BYTE *)&buf, &size);
2923 CRL_INFO *info = (CRL_INFO *)buf;
2926 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2927 sizeof(CRL_INFO), size);
2928 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2930 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2931 entry = info->rgCRLEntry;
2932 ok(entry->SerialNumber.cbData == 1,
2933 "Expected serial number size 1, got %ld\n",
2934 entry->SerialNumber.cbData);
2935 ok(*entry->SerialNumber.pbData == *serialNum,
2936 "Expected serial number %d, got %d\n", *serialNum,
2937 *entry->SerialNumber.pbData);
2938 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2939 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2940 info->Issuer.cbData);
2941 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2942 "Unexpected issuer\n");
2943 /* Oddly, the extensions don't seem to be decoded. Is this just an MS
2944 * bug, or am I missing something?
2946 ok(info->cExtension == 0, "Expected 0 extensions, got %ld\n",
2952 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
2953 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
2954 static const BYTE encodedUsage[] = {
2955 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
2956 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
2957 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
2959 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
2964 CERT_ENHKEY_USAGE usage;
2966 /* Test with empty usage */
2967 usage.cUsageIdentifier = 0;
2968 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
2969 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2970 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2973 ok(size == sizeof(emptySequence), "Expected size %d, got %ld\n",
2974 sizeof(emptySequence), size);
2975 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
2978 /* Test with a few usages */
2979 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
2980 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
2981 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
2982 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2983 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2986 ok(size == sizeof(encodedUsage), "Expected size %d, got %ld\n",
2987 sizeof(encodedUsage), size);
2988 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
2993 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
2999 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
3000 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
3001 (BYTE *)&buf, &size);
3002 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3005 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
3007 ok(size >= sizeof(CERT_ENHKEY_USAGE),
3008 "Expected size at least %d, got %ld\n", sizeof(CERT_ENHKEY_USAGE),
3010 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %ld\n",
3011 usage->cUsageIdentifier);
3014 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
3015 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
3016 (BYTE *)&buf, &size);
3017 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3020 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
3023 ok(size >= sizeof(CERT_ENHKEY_USAGE),
3024 "Expected size at least %d, got %ld\n", sizeof(CERT_ENHKEY_USAGE),
3026 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
3027 "Expected %d CRL entries, got %ld\n",
3028 sizeof(keyUsages) / sizeof(keyUsages[0]),
3029 usage->cUsageIdentifier);
3030 for (i = 0; i < usage->cUsageIdentifier; i++)
3031 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
3032 "Expected OID %s, got %s\n", keyUsages[i],
3033 usage->rgpszUsageIdentifier[i]);
3038 /* Free *pInfo with HeapFree */
3039 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
3046 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
3048 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
3049 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3050 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3051 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
3053 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3054 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3055 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
3057 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3058 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3059 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
3060 0, NULL, NULL, &size);
3061 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3062 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3063 /* Test with no key */
3064 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
3065 0, NULL, NULL, &size);
3066 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08lx\n",
3068 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
3069 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
3072 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3073 NULL, 0, NULL, NULL, &size);
3074 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3075 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
3078 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
3079 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
3080 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n",
3084 /* By default (we passed NULL as the OID) the OID is
3087 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
3088 "Expected %s, got %s\n", szOID_RSA_RSA,
3089 (*pInfo)->Algorithm.pszObjId);
3095 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
3096 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
3097 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
3098 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
3099 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
3100 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
3101 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
3102 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
3103 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
3104 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
3105 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
3106 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3107 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
3108 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
3109 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
3110 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
3111 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
3112 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
3113 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
3114 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
3115 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
3116 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
3117 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
3118 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
3119 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
3121 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
3125 PCCERT_CONTEXT context;
3128 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
3129 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
3130 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
3131 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
3134 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
3135 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3136 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
3137 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
3138 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3139 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
3140 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
3142 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3143 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3144 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
3146 ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3147 CryptDestroyKey(key);
3149 /* Test importing a public key from a certificate context */
3150 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
3151 sizeof(expiredCert));
3152 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
3156 ok(!strcmp(szOID_RSA_RSA,
3157 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
3158 "Expected %s, got %s\n", szOID_RSA_RSA,
3159 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
3160 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
3161 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
3162 ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3163 CryptDestroyKey(key);
3164 CertFreeCertificateContext(context);
3168 static const char cspName[] = "WineCryptTemp";
3170 static void testPortPublicKeyInfo(void)
3174 PCERT_PUBLIC_KEY_INFO info = NULL;
3176 /* Just in case a previous run failed, delete this thing */
3177 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3178 CRYPT_DELETEKEYSET);
3179 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3182 testExportPublicKey(csp, &info);
3183 testImportPublicKey(csp, info);
3185 HeapFree(GetProcessHeap(), 0, info);
3186 CryptReleaseContext(csp, 0);
3187 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3188 CRYPT_DELETEKEYSET);
3193 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
3194 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
3197 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
3199 test_encodeInt(encodings[i]);
3200 test_decodeInt(encodings[i]);
3201 test_encodeEnumerated(encodings[i]);
3202 test_decodeEnumerated(encodings[i]);
3203 test_encodeFiletime(encodings[i]);
3204 test_decodeFiletime(encodings[i]);
3205 test_encodeName(encodings[i]);
3206 test_decodeName(encodings[i]);
3207 test_encodeNameValue(encodings[i]);
3208 test_decodeNameValue(encodings[i]);
3209 test_encodeAltName(encodings[i]);
3210 test_decodeAltName(encodings[i]);
3211 test_encodeOctets(encodings[i]);
3212 test_decodeOctets(encodings[i]);
3213 test_encodeBits(encodings[i]);
3214 test_decodeBits(encodings[i]);
3215 test_encodeBasicConstraints(encodings[i]);
3216 test_decodeBasicConstraints(encodings[i]);
3217 test_encodeRsaPublicKey(encodings[i]);
3218 test_decodeRsaPublicKey(encodings[i]);
3219 test_encodeSequenceOfAny(encodings[i]);
3220 test_decodeSequenceOfAny(encodings[i]);
3221 test_encodeExtensions(encodings[i]);
3222 test_decodeExtensions(encodings[i]);
3223 test_encodePublicKeyInfo(encodings[i]);
3224 test_decodePublicKeyInfo(encodings[i]);
3225 test_encodeCertToBeSigned(encodings[i]);
3226 test_decodeCertToBeSigned(encodings[i]);
3227 test_encodeCert(encodings[i]);
3228 test_decodeCert(encodings[i]);
3229 test_encodeCRLDistPoints(encodings[i]);
3230 test_decodeCRLDistPoints(encodings[i]);
3231 test_encodeCRLToBeSigned(encodings[i]);
3232 test_decodeCRLToBeSigned(encodings[i]);
3233 test_encodeEnhancedKeyUsage(encodings[i]);
3234 test_decodeEnhancedKeyUsage(encodings[i]);
3236 testPortPublicKeyInfo();