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 %d\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 %08x\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 %d\n", GetLastError());
114 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
115 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
116 ok(ret, "CryptEncodeObjectEx failed: %d\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 %d\n", GetLastError());
133 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
134 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
135 ok(ret, "CryptEncodeObjectEx failed: %d\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 %d\n", GetLastError());
157 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
158 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
159 ok(ret, "CryptEncodeObjectEx failed: %d\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 %d\n", GetLastError());
180 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
181 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
182 ok(ret, "CryptEncodeObjectEx failed: %d\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 %d\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 %08x\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 %d\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 %d\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 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
239 ok(ret && GetLastError() == NOERROR,
240 "Expected success and NOERROR, got %d\n", GetLastError());
241 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242 ints[i].encoded, ints[i].encoded[1] + 2,
243 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
244 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
245 ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
246 ok(buf != NULL, "Expected allocated buffer\n");
249 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
250 ints[i].val, *(int *)buf);
254 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
256 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
257 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
259 ok(ret && GetLastError() == NOERROR,
260 "Expected success and NOERROR, got %d\n", GetLastError());
261 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
262 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
263 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
264 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
265 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
266 ok(buf != NULL, "Expected allocated buffer\n");
269 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
271 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
272 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
274 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
275 "Unexpected value\n");
279 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
281 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
282 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
284 ok(ret && GetLastError() == NOERROR,
285 "Expected success and NOERROR, got %d\n", GetLastError());
286 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
287 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
288 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
289 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
290 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
291 ok(buf != NULL, "Expected allocated buffer\n");
294 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
296 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
297 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
299 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
300 "Unexpected value\n");
304 /* Decode the value 1 with long-form length */
305 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
306 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
307 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
310 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
313 /* Try to decode some bogus large items */
314 /* The buffer size is smaller than the encoded length, so this should fail
315 * with CRYPT_E_ASN1_EOD if it's being decoded.
316 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
317 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
318 * So this test unfortunately isn't useful.
319 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
320 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
321 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
322 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
324 /* This will try to decode the buffer and overflow it, check that it's
329 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
330 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
331 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
332 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
333 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
337 static const BYTE bin18[] = {0x0a,0x01,0x01};
338 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
340 /* These are always encoded unsigned, and aren't constrained to be any
343 static const struct encodedInt enums[] = {
348 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
351 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
352 szOID_CRL_REASON_CODE };
354 static void test_encodeEnumerated(DWORD dwEncoding)
358 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
360 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
366 ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
367 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
369 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
373 "Got unexpected type %d for enumerated (expected 0xa)\n",
375 ok(buf[1] == enums[j].encoded[1],
376 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
377 ok(!memcmp(buf + 1, enums[j].encoded + 1,
378 enums[j].encoded[1] + 1),
379 "Encoded value of 0x%08x didn't match expected\n",
387 static void test_decodeEnumerated(DWORD dwEncoding)
391 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
393 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
396 DWORD bufSize = sizeof(int);
399 ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
400 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
401 (BYTE *)&val, &bufSize);
402 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
403 ok(bufSize == sizeof(int),
404 "Got unexpected size %d for enumerated\n", bufSize);
405 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
411 struct encodedFiletime
414 const BYTE *encodedTime;
417 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
418 const struct encodedFiletime *time)
425 ret = SystemTimeToFileTime(&time->sysTime, &ft);
426 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
427 ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
428 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
429 /* years other than 1950-2050 are not allowed for encodings other than
430 * X509_CHOICE_OF_TIME.
432 if (structType == X509_CHOICE_OF_TIME ||
433 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
435 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
437 ok(buf != NULL, "Expected an allocated buffer\n");
440 ok(buf[0] == time->encodedTime[0],
441 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
443 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
444 time->encodedTime[1], bufSize);
445 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
446 "Got unexpected value for time encoding\n");
451 ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
452 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
455 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
456 const struct encodedFiletime *time)
458 FILETIME ft1 = { 0 }, ft2 = { 0 };
459 DWORD size = sizeof(ft2);
462 ret = SystemTimeToFileTime(&time->sysTime, &ft1);
463 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
464 ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
465 time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
466 /* years other than 1950-2050 are not allowed for encodings other than
467 * X509_CHOICE_OF_TIME.
469 if (structType == X509_CHOICE_OF_TIME ||
470 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
472 ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
474 ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
475 "Got unexpected value for time decoding\n");
478 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
479 "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
482 static const BYTE bin20[] = {
483 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
484 static const BYTE bin21[] = {
485 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
486 static const BYTE bin22[] = {
487 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
489 static const struct encodedFiletime times[] = {
490 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
491 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
492 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
495 static void test_encodeFiletime(DWORD dwEncoding)
499 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
501 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
502 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
503 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
507 static const BYTE bin23[] = {
508 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
509 static const BYTE bin24[] = {
510 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
511 static const BYTE bin25[] = {
512 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
513 static const BYTE bin26[] = {
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 bin27[] = {
516 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
517 static const BYTE bin28[] = {
518 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
519 static const BYTE bin29[] = {
520 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
521 static const BYTE bin30[] = {
522 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
523 static const BYTE bin31[] = {
524 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
525 static const BYTE bin32[] = {
526 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
527 static const BYTE bin33[] = {
528 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
529 static const BYTE bin34[] = {
530 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
531 static const BYTE bin35[] = {
532 0x17,0x08, '4','5','0','6','0','6','1','6'};
533 static const BYTE bin36[] = {
534 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
535 static const BYTE bin37[] = {
536 0x18,0x04, '2','1','4','5'};
537 static const BYTE bin38[] = {
538 0x18,0x08, '2','1','4','5','0','6','0','6'};
540 static void test_decodeFiletime(DWORD dwEncoding)
542 static const struct encodedFiletime otherTimes[] = {
543 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
544 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
545 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
546 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
547 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
548 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
549 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
550 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
551 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
552 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
553 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
554 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
556 /* An oddball case that succeeds in Windows, but doesn't seem correct
557 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
559 static const unsigned char *bogusTimes[] = {
560 /* oddly, this succeeds on Windows, with year 2765
561 "\x18" "\x0f" "21r50606161000Z",
569 FILETIME ft1 = { 0 }, ft2 = { 0 };
572 /* Check bogus length with non-NULL buffer */
573 ret = SystemTimeToFileTime(×[0].sysTime, &ft1);
574 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
576 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
577 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
578 ok(!ret && GetLastError() == ERROR_MORE_DATA,
579 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
581 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
583 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
584 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
585 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
587 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
589 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
590 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
591 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
593 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
596 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
597 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
598 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
599 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
603 static const char commonName[] = "Juan Lang";
604 static const char surName[] = "Lang";
606 static const BYTE emptySequence[] = { 0x30, 0 };
607 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
608 static const BYTE twoRDNs[] = {
609 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
610 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
611 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
612 static const BYTE encodedTwoRDNs[] = {
613 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
614 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
615 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
619 static const BYTE us[] = { 0x55, 0x53 };
620 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
622 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
623 0x6f, 0x6c, 0x69, 0x73 };
624 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
625 0x76, 0x65, 0x72, 0x73 };
626 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
627 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
628 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
630 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
631 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
633 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
634 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
636 static CHAR oid_us[] = "2.5.4.6",
637 oid_minnesota[] = "2.5.4.8",
638 oid_minneapolis[] = "2.5.4.7",
639 oid_codeweavers[] = "2.5.4.10",
640 oid_wine[] = "2.5.4.11",
641 oid_localhostAttr[] = "2.5.4.3",
642 oid_aric[] = "1.2.840.113549.1.9.1";
643 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
645 { RDNA(minneapolis) },
646 { RDNA(codeweavers) },
648 { RDNA(localhostAttr) },
650 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
651 { RDNA(localhostAttr) },
653 { RDNA(minneapolis) },
654 { RDNA(codeweavers) },
661 static const BYTE encodedRDNAttrs[] = {
662 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
663 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
664 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
665 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
666 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
667 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
668 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
669 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
670 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
671 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
674 static void test_encodeName(DWORD dwEncoding)
676 CERT_RDN_ATTR attrs[2];
679 static CHAR oid_common_name[] = szOID_COMMON_NAME,
680 oid_sur_name[] = szOID_SUR_NAME;
685 /* Test with NULL pvStructInfo */
686 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
687 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
688 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
689 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
690 /* Test with empty CERT_NAME_INFO */
693 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
694 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
695 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
698 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
699 "Got unexpected encoding for empty name\n");
702 /* Test with bogus CERT_RDN */
704 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
705 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
706 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
707 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
708 /* Test with empty CERT_RDN */
710 rdn.rgRDNAttr = NULL;
713 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
714 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
715 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
718 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
719 "Got unexpected encoding for empty RDN array\n");
722 /* Test with bogus attr array */
724 rdn.rgRDNAttr = NULL;
725 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
726 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
727 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
728 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
729 /* oddly, a bogus OID is accepted by Windows XP; not testing.
730 attrs[0].pszObjId = "bogus";
731 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
732 attrs[0].Value.cbData = sizeof(commonName);
733 attrs[0].Value.pbData = (BYTE *)commonName;
735 rdn.rgRDNAttr = attrs;
736 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
737 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
738 ok(!ret, "Expected failure, got success\n");
740 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
741 * the encoded attributes to be swapped.
743 attrs[0].pszObjId = oid_common_name;
744 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
745 attrs[0].Value.cbData = sizeof(commonName);
746 attrs[0].Value.pbData = (BYTE *)commonName;
747 attrs[1].pszObjId = oid_sur_name;
748 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
749 attrs[1].Value.cbData = sizeof(surName);
750 attrs[1].Value.pbData = (BYTE *)surName;
752 rdn.rgRDNAttr = attrs;
753 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
754 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
755 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
758 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
759 "Got unexpected encoding for two RDN array\n");
762 /* A name can be "encoded" with previously encoded RDN attrs. */
763 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
764 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
765 attrs[0].Value.cbData = sizeof(twoRDNs);
767 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
768 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
769 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
772 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
773 ok(!memcmp(buf, encodedTwoRDNs, size),
774 "Unexpected value for re-endoded two RDN array\n");
777 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
779 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
780 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
781 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
782 ok(!ret && GetLastError() == E_INVALIDARG,
783 "Expected E_INVALIDARG, got %08x\n", GetLastError());
784 /* Test a more complex name */
785 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
786 rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
791 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
792 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
793 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
796 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
797 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
802 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
803 static WCHAR surNameW[] = { 'L','a','n','g',0 };
805 static const BYTE twoRDNsNoNull[] = {
806 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
807 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
808 0x20,0x4c,0x61,0x6e,0x67 };
809 static const BYTE anyType[] = {
810 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
811 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
812 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
813 0x61,0x4c,0x67,0x6e };
815 static void test_encodeUnicodeName(DWORD dwEncoding)
817 CERT_RDN_ATTR attrs[2];
820 static CHAR oid_common_name[] = szOID_COMMON_NAME,
821 oid_sur_name[] = szOID_SUR_NAME;
826 /* Test with NULL pvStructInfo */
827 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
828 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
829 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
830 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
831 /* Test with empty CERT_NAME_INFO */
834 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
835 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
836 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
839 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
840 "Got unexpected encoding for empty name\n");
843 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
844 * encoding (the NULL).
846 attrs[0].pszObjId = oid_common_name;
847 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
848 attrs[0].Value.cbData = sizeof(commonNameW);
849 attrs[0].Value.pbData = (BYTE *)commonNameW;
851 rdn.rgRDNAttr = attrs;
854 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
855 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
856 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
857 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
858 ok(size == 9, "Unexpected error index %08x\n", size);
859 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding
860 * forces the order of the encoded attributes to be swapped.
862 attrs[0].pszObjId = oid_common_name;
863 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
864 attrs[0].Value.cbData = 0;
865 attrs[0].Value.pbData = (BYTE *)commonNameW;
866 attrs[1].pszObjId = oid_sur_name;
867 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
868 attrs[1].Value.cbData = 0;
869 attrs[1].Value.pbData = (BYTE *)surNameW;
871 rdn.rgRDNAttr = attrs;
874 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
875 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
876 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
879 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
880 "Got unexpected encoding for two RDN array\n");
883 /* A name can be "encoded" with previously encoded RDN attrs. */
884 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
885 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
886 attrs[0].Value.cbData = sizeof(twoRDNs);
888 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
889 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
890 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
893 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
894 ok(!memcmp(buf, encodedTwoRDNs, size),
895 "Unexpected value for re-endoded two RDN array\n");
898 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
900 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
901 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
902 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
903 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
906 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
907 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
912 static void compareNameValues(const CERT_NAME_VALUE *expected,
913 const CERT_NAME_VALUE *got)
915 ok(got->dwValueType == expected->dwValueType,
916 "Expected string type %d, got %d\n", expected->dwValueType,
918 ok(got->Value.cbData == expected->Value.cbData,
919 "String type %d: unexpected data size, got %d, expected %d\n",
920 expected->dwValueType, got->Value.cbData, expected->Value.cbData);
921 if (got->Value.cbData && got->Value.pbData)
922 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
923 min(got->Value.cbData, expected->Value.cbData)),
924 "String type %d: unexpected value\n", expected->dwValueType);
927 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
928 const CERT_RDN_ATTR *got)
930 if (expected->pszObjId && strlen(expected->pszObjId))
932 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
936 ok(!strcmp(got->pszObjId, expected->pszObjId),
937 "Got unexpected OID %s, expected %s\n", got->pszObjId,
941 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
942 (const CERT_NAME_VALUE *)&got->dwValueType);
945 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
947 ok(got->cRDNAttr == expected->cRDNAttr,
948 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
953 for (i = 0; i < got->cRDNAttr; i++)
954 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
958 static void compareNames(const CERT_NAME_INFO *expected,
959 const CERT_NAME_INFO *got)
961 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
962 expected->cRDN, got->cRDN);
967 for (i = 0; i < got->cRDN; i++)
968 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
972 static void test_decodeName(DWORD dwEncoding)
978 CERT_NAME_INFO info = { 1, &rdn };
980 /* test empty name */
982 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
983 emptySequence[1] + 2,
984 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
985 (BYTE *)&buf, &bufSize);
986 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
987 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
988 * decoder works the same way, so only test the count.
992 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
993 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
994 "Expected 0 RDNs in empty info, got %d\n",
995 ((CERT_NAME_INFO *)buf)->cRDN);
1000 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1002 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1003 (BYTE *)&buf, &bufSize);
1004 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1007 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1009 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1010 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1011 "Got unexpected value for empty RDN\n");
1014 /* test two RDN attrs */
1016 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1018 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1019 (BYTE *)&buf, &bufSize);
1020 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1023 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1024 oid_common_name[] = szOID_COMMON_NAME;
1026 CERT_RDN_ATTR attrs[] = {
1027 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1028 (BYTE *)surName } },
1029 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1030 (BYTE *)commonName } },
1033 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1034 rdn.rgRDNAttr = attrs;
1035 compareNames(&info, (CERT_NAME_INFO *)buf);
1038 /* And, a slightly more complicated name */
1041 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1042 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1043 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1046 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1047 rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1048 compareNames(&info, (CERT_NAME_INFO *)buf);
1053 static void test_decodeUnicodeName(DWORD dwEncoding)
1059 CERT_NAME_INFO info = { 1, &rdn };
1061 /* test empty name */
1063 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1064 emptySequence[1] + 2,
1065 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1066 (BYTE *)&buf, &bufSize);
1067 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1070 ok(bufSize == sizeof(CERT_NAME_INFO),
1071 "Got wrong bufSize %d\n", bufSize);
1072 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1073 "Expected 0 RDNs in empty info, got %d\n",
1074 ((CERT_NAME_INFO *)buf)->cRDN);
1077 /* test empty RDN */
1079 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1081 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1082 (BYTE *)&buf, &bufSize);
1083 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1086 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1088 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1089 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1090 "Got unexpected value for empty RDN\n");
1093 /* test two RDN attrs */
1095 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1096 sizeof(twoRDNsNoNull),
1097 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1098 (BYTE *)&buf, &bufSize);
1099 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1102 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1103 oid_common_name[] = szOID_COMMON_NAME;
1105 CERT_RDN_ATTR attrs[] = {
1106 { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1107 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1108 { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1109 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1112 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1113 rdn.rgRDNAttr = attrs;
1114 compareNames(&info, (CERT_NAME_INFO *)buf);
1119 struct EncodedNameValue
1121 CERT_NAME_VALUE value;
1122 const BYTE *encoded;
1126 static const char bogusIA5[] = "\x80";
1127 static const char bogusPrintable[] = "~";
1128 static const char bogusNumeric[] = "A";
1129 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1130 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1131 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1132 static BYTE octetCommonNameValue[] = {
1133 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1134 static BYTE numericCommonNameValue[] = {
1135 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1136 static BYTE printableCommonNameValue[] = {
1137 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1138 static BYTE t61CommonNameValue[] = {
1139 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1140 static BYTE videotexCommonNameValue[] = {
1141 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1142 static BYTE ia5CommonNameValue[] = {
1143 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1144 static BYTE graphicCommonNameValue[] = {
1145 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1146 static BYTE visibleCommonNameValue[] = {
1147 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1148 static BYTE generalCommonNameValue[] = {
1149 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1150 static BYTE bmpCommonNameValue[] = {
1151 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1152 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1153 static BYTE utf8CommonNameValue[] = {
1154 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1156 static struct EncodedNameValue nameValues[] = {
1157 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1158 octetCommonNameValue, sizeof(octetCommonNameValue) },
1159 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1160 numericCommonNameValue, sizeof(numericCommonNameValue) },
1161 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1162 printableCommonNameValue, sizeof(printableCommonNameValue) },
1163 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1164 t61CommonNameValue, sizeof(t61CommonNameValue) },
1165 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1166 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1167 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1168 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1169 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1170 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1171 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1172 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1173 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1174 generalCommonNameValue, sizeof(generalCommonNameValue) },
1175 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1176 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1177 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1178 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1179 /* The following tests succeed under Windows, but really should fail,
1180 * they contain characters that are illegal for the encoding. I'm
1181 * including them to justify my lazy encoding.
1183 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1185 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1186 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1187 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1188 bin44, sizeof(bin44) },
1191 static void test_encodeNameValue(DWORD dwEncoding)
1196 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1198 value.dwValueType = 14;
1199 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1200 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1201 ok(!ret && GetLastError() == CRYPT_E_ASN1_CHOICE,
1202 "Expected CRYPT_E_ASN1_CHOICE, got %08x\n", GetLastError());
1203 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1204 value.Value.pbData = printableCommonNameValue;
1205 value.Value.cbData = sizeof(printableCommonNameValue);
1206 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1207 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1208 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1211 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1213 ok(!memcmp(buf, printableCommonNameValue, size),
1214 "Unexpected encoding\n");
1217 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1219 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1220 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1222 ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1223 nameValues[i].value.dwValueType, GetLastError());
1226 ok(size == nameValues[i].encodedSize,
1227 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1228 ok(!memcmp(buf, nameValues[i].encoded, size),
1229 "Got unexpected encoding\n");
1235 static void test_decodeNameValue(DWORD dwEncoding)
1242 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1244 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1245 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1246 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1247 (BYTE *)&buf, &bufSize);
1248 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1249 nameValues[i].value.dwValueType, GetLastError());
1252 compareNameValues(&nameValues[i].value,
1253 (const CERT_NAME_VALUE *)buf);
1259 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1260 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1261 'h','q','.','o','r','g',0 };
1262 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1263 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1265 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1267 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1268 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1269 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1270 static const BYTE localhost[] = { 127, 0, 0, 1 };
1271 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1274 static void test_encodeAltName(DWORD dwEncoding)
1276 CERT_ALT_NAME_INFO info = { 0 };
1277 CERT_ALT_NAME_ENTRY entry = { 0 };
1282 /* Test with empty info */
1283 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1284 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1287 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1288 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1291 /* Test with an empty entry */
1293 info.rgAltEntry = &entry;
1294 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1295 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1296 ok(!ret && GetLastError() == E_INVALIDARG,
1297 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1298 /* Test with an empty pointer */
1299 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1300 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1301 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1304 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1305 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1308 /* Test with a real URL */
1309 U(entry).pwszURL = (LPWSTR)url;
1310 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1311 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1314 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1315 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1318 /* Now with the URL containing an invalid IA5 char */
1319 U(entry).pwszURL = (LPWSTR)nihongoURL;
1320 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1321 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1322 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1323 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1324 /* The first invalid character is at index 7 */
1325 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1326 "Expected invalid char at index 7, got %d\n",
1327 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1328 /* Now with the URL missing a scheme */
1329 U(entry).pwszURL = (LPWSTR)dnsName;
1330 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1331 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1332 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1335 /* This succeeds, but it shouldn't, so don't worry about conforming */
1338 /* Now with a DNS name */
1339 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1340 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1341 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1342 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1345 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1346 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1349 /* Test with an IP address */
1350 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1351 U(entry).IPAddress.cbData = sizeof(localhost);
1352 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1353 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1354 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1357 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1358 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1363 static void test_decodeAltName(DWORD dwEncoding)
1365 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1367 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1372 CERT_ALT_NAME_INFO *info;
1374 /* Test some bogus ones first */
1375 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1376 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1377 NULL, (BYTE *)&buf, &bufSize);
1378 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1379 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1380 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1381 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1383 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1384 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1385 /* Now expected cases */
1386 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1387 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1389 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1392 info = (CERT_ALT_NAME_INFO *)buf;
1394 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1398 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1399 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1401 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1404 info = (CERT_ALT_NAME_INFO *)buf;
1406 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1408 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1409 "Expected CERT_ALT_NAME_URL, got %d\n",
1410 info->rgAltEntry[0].dwAltNameChoice);
1411 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1412 "Expected empty URL\n");
1415 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1416 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1418 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1421 info = (CERT_ALT_NAME_INFO *)buf;
1423 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1425 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1426 "Expected CERT_ALT_NAME_URL, got %d\n",
1427 info->rgAltEntry[0].dwAltNameChoice);
1428 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1431 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1432 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1434 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1437 info = (CERT_ALT_NAME_INFO *)buf;
1439 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1441 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1442 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1443 info->rgAltEntry[0].dwAltNameChoice);
1444 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1445 "Unexpected DNS name\n");
1448 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1449 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1451 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1454 info = (CERT_ALT_NAME_INFO *)buf;
1456 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1458 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1459 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1460 info->rgAltEntry[0].dwAltNameChoice);
1461 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1462 "Unexpected IP address length %d\n",
1463 U(info->rgAltEntry[0]).IPAddress.cbData);
1464 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1465 sizeof(localhost)), "Unexpected IP address value\n");
1470 struct UnicodeExpectedError
1478 static const WCHAR oneW[] = { '1',0 };
1479 static const WCHAR aW[] = { 'a',0 };
1480 static const WCHAR quoteW[] = { '"', 0 };
1482 static struct UnicodeExpectedError unicodeErrors[] = {
1483 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1484 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1485 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1486 { 14, oneW, 0, CRYPT_E_ASN1_CHOICE },
1487 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1488 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1489 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1492 struct UnicodeExpectedResult
1496 CRYPT_DATA_BLOB encoded;
1499 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1500 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1501 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1502 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1503 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1504 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1505 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1506 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1507 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1508 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1509 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1510 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1512 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1514 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1515 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1516 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1517 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1519 static struct UnicodeExpectedResult unicodeResults[] = {
1520 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1521 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1522 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1523 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1524 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1525 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1526 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1527 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1528 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1529 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1530 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1531 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1532 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1535 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1536 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1537 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1540 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1545 CERT_NAME_VALUE value;
1547 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1548 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1549 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1550 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1551 /* Have to have a string of some sort */
1552 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1553 value.Value.pbData = NULL;
1554 value.Value.cbData = 0;
1555 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1556 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1557 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1558 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1559 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1560 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1561 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1562 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1563 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1564 value.dwValueType = CERT_RDN_ANY_TYPE;
1565 value.Value.pbData = (LPBYTE)oneW;
1566 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1567 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1568 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1569 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1570 value.Value.cbData = sizeof(oneW);
1571 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1572 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1573 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1574 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1575 /* An encoded string with specified length isn't good enough either */
1576 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1577 value.Value.pbData = oneUniversal;
1578 value.Value.cbData = sizeof(oneUniversal);
1579 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1580 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1581 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1582 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1583 /* More failure checking */
1584 value.Value.cbData = 0;
1585 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1587 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1588 value.dwValueType = unicodeErrors[i].valueType;
1589 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1590 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1591 ok(!ret && GetLastError() == unicodeErrors[i].error,
1592 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1593 unicodeErrors[i].error, GetLastError());
1594 ok(size == unicodeErrors[i].errorIndex,
1595 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1598 /* cbData can be zero if the string is NULL-terminated */
1599 value.Value.cbData = 0;
1600 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1602 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1603 value.dwValueType = unicodeResults[i].valueType;
1604 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1605 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1606 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1609 ok(size == unicodeResults[i].encoded.cbData,
1610 "Value type %d: expected size %d, got %d\n",
1611 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1612 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1613 "Value type %d: unexpected value\n", value.dwValueType);
1617 /* These "encode," but they do so by truncating each unicode character
1618 * rather than properly encoding it. Kept separate from the proper results,
1619 * because the encoded forms won't decode to their original strings.
1621 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1623 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1624 value.dwValueType = unicodeWeirdness[i].valueType;
1625 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1626 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1627 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1630 ok(size == unicodeWeirdness[i].encoded.cbData,
1631 "Value type %d: expected size %d, got %d\n",
1632 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1633 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1634 "Value type %d: unexpected value\n", value.dwValueType);
1640 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1642 if (n <= 0) return 0;
1643 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1644 return *str1 - *str2;
1647 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1651 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1657 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1658 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1659 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1660 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1663 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1665 ok(value->dwValueType == unicodeResults[i].valueType,
1666 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1667 value->dwValueType);
1668 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1669 value->Value.cbData / sizeof(WCHAR)),
1670 "Unexpected decoded value for index %d (value type %d)\n", i,
1671 unicodeResults[i].valueType);
1677 struct encodedOctets
1680 const BYTE *encoded;
1683 static const unsigned char bin46[] = { 'h','i',0 };
1684 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1685 static const unsigned char bin48[] = {
1686 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1687 static const unsigned char bin49[] = {
1688 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1689 static const unsigned char bin50[] = { 0 };
1690 static const unsigned char bin51[] = { 0x04,0x00,0 };
1692 static const struct encodedOctets octets[] = {
1698 static void test_encodeOctets(DWORD dwEncoding)
1700 CRYPT_DATA_BLOB blob;
1703 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1709 blob.cbData = strlen((const char*)octets[i].val);
1710 blob.pbData = (BYTE*)octets[i].val;
1711 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1712 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1713 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1717 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1718 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1719 buf[1], octets[i].encoded[1]);
1720 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1721 octets[i].encoded[1] + 1), "Got unexpected value\n");
1727 static void test_decodeOctets(DWORD dwEncoding)
1731 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1737 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1738 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1739 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1740 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1741 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1742 "Expected size >= %d, got %d\n",
1743 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1744 ok(buf != NULL, "Expected allocated buffer\n");
1747 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1750 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1751 "Unexpected value\n");
1757 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1762 const BYTE *encoded;
1764 const BYTE *decoded;
1767 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1768 static const unsigned char bin53[] = { 0xff,0xff };
1769 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1770 static const unsigned char bin55[] = { 0xff,0xfe };
1771 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1772 static const unsigned char bin57[] = { 0xfe };
1773 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1775 static const struct encodedBits bits[] = {
1776 /* normal test cases */
1777 { 0, bin52, 2, bin53 },
1778 { 1, bin54, 2, bin55 },
1779 /* strange test case, showing cUnusedBits >= 8 is allowed */
1780 { 9, bin56, 1, bin57 },
1781 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1782 { 17, bin58, 0, NULL },
1785 static void test_encodeBits(DWORD dwEncoding)
1789 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1791 CRYPT_BIT_BLOB blob;
1796 blob.cbData = sizeof(bytesToEncode);
1797 blob.pbData = (BYTE *)bytesToEncode;
1798 blob.cUnusedBits = bits[i].cUnusedBits;
1799 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1800 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1801 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1804 ok(bufSize == bits[i].encoded[1] + 2,
1805 "Got unexpected size %d, expected %d\n", bufSize,
1806 bits[i].encoded[1] + 2);
1807 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1808 "Unexpected value\n");
1814 static void test_decodeBits(DWORD dwEncoding)
1816 static const BYTE ber[] = "\x03\x02\x01\xff";
1817 static const BYTE berDecoded = 0xfe;
1824 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1826 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1827 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1829 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1832 CRYPT_BIT_BLOB *blob;
1834 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1835 "Got unexpected size %d\n", bufSize);
1836 blob = (CRYPT_BIT_BLOB *)buf;
1837 ok(blob->cbData == bits[i].cbDecoded,
1838 "Got unexpected length %d, expected %d\n", blob->cbData,
1840 if (blob->cbData && bits[i].cbDecoded)
1841 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1842 "Unexpected value\n");
1846 /* special case: check that something that's valid in BER but not in DER
1847 * decodes successfully
1849 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1850 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1851 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1854 CRYPT_BIT_BLOB *blob;
1856 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1857 "Got unexpected size %d\n", bufSize);
1858 blob = (CRYPT_BIT_BLOB *)buf;
1859 ok(blob->cbData == sizeof(berDecoded),
1860 "Got unexpected length %d\n", blob->cbData);
1862 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1869 CERT_BASIC_CONSTRAINTS2_INFO info;
1870 const BYTE *encoded;
1873 static const unsigned char bin59[] = { 0x30,0x00 };
1874 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1875 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1876 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1877 static const struct Constraints2 constraints2[] = {
1878 /* empty constraints */
1879 { { FALSE, FALSE, 0}, bin59 },
1881 { { TRUE, FALSE, 0}, bin60 },
1882 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1883 * but that's not the case
1885 { { FALSE, TRUE, 0}, bin61 },
1886 /* can be a CA and has path length constraints set */
1887 { { TRUE, TRUE, 1}, bin62 },
1890 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1891 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1892 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1893 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1894 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1895 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1896 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1897 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1898 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1899 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1901 static void test_encodeBasicConstraints(DWORD dwEncoding)
1903 DWORD i, bufSize = 0;
1904 CERT_BASIC_CONSTRAINTS_INFO info;
1905 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1906 (LPBYTE)encodedDomainName };
1910 /* First test with the simpler info2 */
1911 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1913 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1914 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1916 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1919 ok(bufSize == constraints2[i].encoded[1] + 2,
1920 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
1922 ok(!memcmp(buf, constraints2[i].encoded,
1923 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1927 /* Now test with more complex basic constraints */
1928 info.SubjectType.cbData = 0;
1929 info.fPathLenConstraint = FALSE;
1930 info.cSubtreesConstraint = 0;
1931 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1932 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1933 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1936 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
1937 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1938 "Unexpected value\n");
1941 /* None of the certs I examined had any subtree constraint, but I test one
1942 * anyway just in case.
1944 info.cSubtreesConstraint = 1;
1945 info.rgSubtreesConstraint = &nameBlob;
1946 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1947 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1948 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1951 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
1952 ok(!memcmp(buf, constraintWithDomainName,
1953 sizeof(constraintWithDomainName)), "Unexpected value\n");
1956 /* FIXME: test encoding with subject type. */
1959 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1960 static const unsigned char encodedCommonName[] = {
1961 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1963 static void test_decodeBasicConstraints(DWORD dwEncoding)
1965 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1967 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1973 /* First test with simpler info2 */
1974 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1976 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1977 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1978 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1979 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
1983 CERT_BASIC_CONSTRAINTS2_INFO *info =
1984 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1986 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1987 "Unexpected value for item %d\n", i);
1991 /* Check with the order of encoded elements inverted */
1993 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1994 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1996 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1997 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1998 ok(!buf, "Expected buf to be set to NULL\n");
1999 /* Check with a non-DER bool */
2000 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2001 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2002 (BYTE *)&buf, &bufSize);
2003 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2006 CERT_BASIC_CONSTRAINTS2_INFO *info =
2007 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2009 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2012 /* Check with a non-basic constraints value */
2013 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2014 (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2015 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2016 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2017 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2018 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2019 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2020 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2021 (BYTE *)&buf, &bufSize);
2022 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2025 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2027 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2028 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2029 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2032 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2033 constraintWithDomainName, sizeof(constraintWithDomainName),
2034 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2035 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2038 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2040 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2041 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2042 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2043 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2045 ok(info->rgSubtreesConstraint[0].cbData ==
2046 sizeof(encodedDomainName), "Wrong size %d\n",
2047 info->rgSubtreesConstraint[0].cbData);
2048 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2049 sizeof(encodedDomainName)), "Unexpected value\n");
2055 /* These are terrible public keys of course, I'm just testing encoding */
2056 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2057 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2058 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2059 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2060 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2061 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2062 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2063 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2065 struct EncodedRSAPubKey
2067 const BYTE *modulus;
2069 const BYTE *encoded;
2070 size_t decodedModulusLen;
2073 struct EncodedRSAPubKey rsaPubKeys[] = {
2074 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2075 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2076 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2077 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2080 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2082 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2083 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2084 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2087 DWORD bufSize = 0, i;
2089 /* Try with a bogus blob type */
2091 hdr->bVersion = CUR_BLOB_VERSION;
2093 hdr->aiKeyAlg = CALG_RSA_KEYX;
2094 rsaPubKey->magic = 0x31415352;
2095 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2096 rsaPubKey->pubexp = 65537;
2097 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2100 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2101 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2103 ok(!ret && GetLastError() == E_INVALIDARG,
2104 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2105 /* Now with a bogus reserved field */
2106 hdr->bType = PUBLICKEYBLOB;
2108 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2109 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2113 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2114 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2115 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2118 /* Now with a bogus blob version */
2121 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2122 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2126 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2127 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2128 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2131 /* And with a bogus alg ID */
2132 hdr->bVersion = CUR_BLOB_VERSION;
2133 hdr->aiKeyAlg = CALG_DES;
2134 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2135 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2139 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2140 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2141 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2144 /* Check a couple of RSA-related OIDs */
2145 hdr->aiKeyAlg = CALG_RSA_KEYX;
2146 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2147 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2148 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2149 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2150 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2151 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2152 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2153 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2154 /* Finally, all valid */
2155 hdr->aiKeyAlg = CALG_RSA_KEYX;
2156 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2158 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2159 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2160 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2161 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2162 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2165 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2166 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2168 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2169 "Unexpected value\n");
2175 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2182 /* Try with a bad length */
2183 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2184 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2185 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2186 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2187 "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2188 /* Try with a couple of RSA-related OIDs */
2189 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2190 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2191 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2192 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2193 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2194 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2195 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2196 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2197 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2198 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2199 /* Now try success cases */
2200 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2203 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2204 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2205 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2206 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2209 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2210 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2212 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2213 rsaPubKeys[i].decodedModulusLen,
2214 "Wrong size %d\n", bufSize);
2215 ok(hdr->bType == PUBLICKEYBLOB,
2216 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2218 ok(hdr->bVersion == CUR_BLOB_VERSION,
2219 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2220 CUR_BLOB_VERSION, hdr->bVersion);
2221 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2223 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2224 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2225 ok(rsaPubKey->magic == 0x31415352,
2226 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2227 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2228 "Wrong bit len %d\n", rsaPubKey->bitlen);
2229 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2231 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2232 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2233 "Unexpected modulus\n");
2239 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2240 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2241 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2243 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2244 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2245 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2246 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2248 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2250 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2251 CRYPT_SEQUENCE_OF_ANY seq;
2257 /* Encode a homogenous sequence */
2258 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2260 blobs[i].cbData = ints[i].encoded[1] + 2;
2261 blobs[i].pbData = (BYTE *)ints[i].encoded;
2263 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2264 seq.rgValue = blobs;
2266 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2267 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2268 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2271 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2272 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2275 /* Change the type of the first element in the sequence, and give it
2278 blobs[0].cbData = times[0].encodedTime[1] + 2;
2279 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2280 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2281 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2282 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2285 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2286 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2287 "Unexpected value\n");
2292 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2298 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2299 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2300 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2303 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2306 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2307 "Wrong elements %d\n", seq->cValue);
2308 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2310 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2311 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2312 seq->rgValue[i].cbData);
2313 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2314 ints[i].encoded[1] + 2), "Unexpected value\n");
2318 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2319 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2321 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2324 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2326 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2327 "Wrong elements %d\n", seq->cValue);
2328 /* Just check the first element since it's all that changed */
2329 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2330 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2331 seq->rgValue[0].cbData);
2332 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2333 times[0].encodedTime[1] + 2), "Unexpected value\n");
2338 struct encodedExtensions
2340 CERT_EXTENSIONS exts;
2341 const BYTE *encoded;
2344 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2345 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2346 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2347 static CERT_EXTENSION criticalExt =
2348 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2349 static CERT_EXTENSION nonCriticalExt =
2350 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2352 static const BYTE ext0[] = { 0x30,0x00 };
2353 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2354 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2355 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2356 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2358 static const struct encodedExtensions exts[] = {
2359 { { 0, NULL }, ext0 },
2360 { { 1, &criticalExt }, ext1 },
2361 { { 1, &nonCriticalExt }, ext2 },
2364 static void test_encodeExtensions(DWORD dwEncoding)
2368 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2374 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2375 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2376 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2379 ok(bufSize == exts[i].encoded[1] + 2,
2380 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2381 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2382 "Unexpected value\n");
2388 static void test_decodeExtensions(DWORD dwEncoding)
2392 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2398 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2399 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2400 NULL, (BYTE *)&buf, &bufSize);
2401 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2404 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2407 ok(ext->cExtension == exts[i].exts.cExtension,
2408 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2410 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2412 ok(!strcmp(ext->rgExtension[j].pszObjId,
2413 exts[i].exts.rgExtension[j].pszObjId),
2414 "Expected OID %s, got %s\n",
2415 exts[i].exts.rgExtension[j].pszObjId,
2416 ext->rgExtension[j].pszObjId);
2417 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2418 exts[i].exts.rgExtension[j].Value.pbData,
2419 exts[i].exts.rgExtension[j].Value.cbData),
2420 "Unexpected value\n");
2427 /* MS encodes public key info with a NULL if the algorithm identifier's
2428 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2429 * it encodes them by omitting the algorithm parameters. This latter approach
2430 * seems more correct, so accept either form.
2432 struct encodedPublicKey
2434 CERT_PUBLIC_KEY_INFO info;
2435 const BYTE *encoded;
2436 const BYTE *encodedNoNull;
2437 CERT_PUBLIC_KEY_INFO decoded;
2440 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2442 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2444 static const unsigned char bin64[] = {
2445 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2446 static const unsigned char bin65[] = {
2447 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2448 static const unsigned char bin66[] = {
2449 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2450 static const unsigned char bin67[] = {
2451 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2452 static const unsigned char bin68[] = {
2453 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2454 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2455 static const unsigned char bin69[] = {
2456 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2457 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2458 static const unsigned char bin70[] = {
2459 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2460 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2462 static const unsigned char bin71[] = {
2463 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2464 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2466 static unsigned char bin72[] = { 0x05,0x00};
2468 static CHAR oid_bogus[] = "1.2.3",
2469 oid_rsa[] = szOID_RSA;
2471 static const struct encodedPublicKey pubKeys[] = {
2472 /* with a bogus OID */
2473 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2475 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2476 /* some normal keys */
2477 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2479 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2480 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2482 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2483 /* with add'l parameters--note they must be DER-encoded */
2484 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2485 (BYTE *)aKey, 0 } },
2487 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2488 (BYTE *)aKey, 0 } } },
2491 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2495 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2501 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2502 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2504 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2507 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2508 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2509 "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2510 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2511 if (bufSize == pubKeys[i].encoded[1] + 2)
2512 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2513 "Unexpected value\n");
2514 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2515 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2516 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2522 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2523 const CERT_PUBLIC_KEY_INFO *got)
2525 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2526 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2527 got->Algorithm.pszObjId);
2528 ok(expected->Algorithm.Parameters.cbData ==
2529 got->Algorithm.Parameters.cbData,
2530 "Expected parameters of %d bytes, got %d\n",
2531 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2532 if (expected->Algorithm.Parameters.cbData)
2533 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2534 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2535 "Unexpected algorithm parameters\n");
2536 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2537 "Expected public key of %d bytes, got %d\n",
2538 expected->PublicKey.cbData, got->PublicKey.cbData);
2539 if (expected->PublicKey.cbData)
2540 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2541 got->PublicKey.cbData), "Unexpected public key value\n");
2544 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2546 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2547 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2548 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2549 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2555 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2557 /* The NULL form decodes to the decoded member */
2558 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2559 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2560 NULL, (BYTE *)&buf, &bufSize);
2561 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2564 comparePublicKeyInfo(&pubKeys[i].decoded,
2565 (CERT_PUBLIC_KEY_INFO *)buf);
2568 /* The non-NULL form decodes to the original */
2569 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2570 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2571 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2572 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2575 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2579 /* Test with bogus (not valid DER) parameters */
2580 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2581 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2582 NULL, (BYTE *)&buf, &bufSize);
2583 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2584 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2587 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2588 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2589 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2590 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2591 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2592 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2593 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2594 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2595 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2596 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2597 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2598 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2599 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2600 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2601 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2602 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2603 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2604 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2605 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2606 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2607 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2608 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2609 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2610 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2611 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2612 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2613 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2614 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2615 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2616 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2617 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2618 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2619 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2620 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2621 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2622 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2623 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2624 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2625 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2627 static const BYTE serialNum[] = { 0x01 };
2629 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2634 CERT_INFO info = { 0 };
2636 /* Test with NULL pvStructInfo */
2637 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2638 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2639 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2640 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2641 /* Test with a V1 cert */
2642 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2643 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2644 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2647 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2648 v1Cert[1] + 2, size);
2649 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2653 info.dwVersion = CERT_V2;
2654 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2655 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2656 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2659 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2660 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2664 info.dwVersion = CERT_V3;
2665 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2666 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2667 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2670 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2671 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2674 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2675 * API doesn't prevent it)
2677 info.dwVersion = CERT_V1;
2678 info.cExtension = 1;
2679 info.rgExtension = &criticalExt;
2680 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2681 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2682 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2685 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2686 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2689 /* test v1 cert with a serial number */
2690 info.SerialNumber.cbData = sizeof(serialNum);
2691 info.SerialNumber.pbData = (BYTE *)serialNum;
2692 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2693 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2696 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2697 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2700 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2701 info.Issuer.cbData = sizeof(encodedCommonName);
2702 info.Issuer.pbData = (BYTE *)encodedCommonName;
2703 info.Subject.cbData = sizeof(encodedCommonName);
2704 info.Subject.pbData = (BYTE *)encodedCommonName;
2705 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2706 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2709 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2710 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2713 /* for now, I let more interesting tests be done for each subcomponent,
2714 * rather than retesting them all here.
2718 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2720 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2721 v1CertWithConstraints, v1CertWithSerial };
2726 /* Test with NULL pbEncoded */
2727 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2728 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2729 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2730 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2731 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2732 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2733 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2734 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2735 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2736 * minimum a cert must have a non-zero serial number, an issuer, and a
2739 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2741 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2742 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2743 (BYTE *)&buf, &size);
2744 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2745 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2747 /* Now check with serial number, subject and issuer specified */
2748 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2749 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2750 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2753 CERT_INFO *info = (CERT_INFO *)buf;
2755 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2756 ok(info->SerialNumber.cbData == 1,
2757 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2758 ok(*info->SerialNumber.pbData == *serialNum,
2759 "Expected serial number %d, got %d\n", *serialNum,
2760 *info->SerialNumber.pbData);
2761 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2762 "Wrong size %d\n", info->Issuer.cbData);
2763 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2764 "Unexpected issuer\n");
2765 ok(info->Subject.cbData == sizeof(encodedCommonName),
2766 "Wrong size %d\n", info->Subject.cbData);
2767 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2768 info->Subject.cbData), "Unexpected subject\n");
2773 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2776 static const BYTE signedBigCert[] = {
2777 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2778 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2779 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2780 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2781 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2782 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2783 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2784 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2785 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2786 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2787 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2788 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2790 static void test_encodeCert(DWORD dwEncoding)
2792 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2793 * also that bigCert is a NULL-terminated string, so don't count its
2794 * last byte (otherwise the signed cert won't decode.)
2796 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2797 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2802 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2803 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2804 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2807 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
2808 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2813 static void test_decodeCert(DWORD dwEncoding)
2819 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2820 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2821 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2824 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2826 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2827 "Wrong cert size %d\n", info->ToBeSigned.cbData);
2828 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2829 "Unexpected cert\n");
2830 ok(info->Signature.cbData == sizeof(hash),
2831 "Wrong signature size %d\n", info->Signature.cbData);
2832 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2833 "Unexpected signature\n");
2836 /* A signed cert decodes as a CERT_INFO too */
2837 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2838 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2839 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2842 CERT_INFO *info = (CERT_INFO *)buf;
2844 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2845 ok(info->SerialNumber.cbData == 1,
2846 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2847 ok(*info->SerialNumber.pbData == *serialNum,
2848 "Expected serial number %d, got %d\n", *serialNum,
2849 *info->SerialNumber.pbData);
2850 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2851 "Wrong size %d\n", info->Issuer.cbData);
2852 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2853 "Unexpected issuer\n");
2854 ok(info->Subject.cbData == sizeof(encodedCommonName),
2855 "Wrong size %d\n", info->Subject.cbData);
2856 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2857 info->Subject.cbData), "Unexpected subject\n");
2862 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2863 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2864 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2865 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2866 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2868 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2869 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2870 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2871 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2872 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2873 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2874 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2875 0x2e, 0x6f, 0x72, 0x67 };
2876 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2877 CRL_REASON_AFFILIATION_CHANGED;
2879 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2881 CRL_DIST_POINTS_INFO info = { 0 };
2882 CRL_DIST_POINT point = { { 0 } };
2883 CERT_ALT_NAME_ENTRY entry = { 0 };
2888 /* Test with an empty info */
2889 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2890 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2891 ok(!ret && GetLastError() == E_INVALIDARG,
2892 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2893 /* Test with one empty dist point */
2894 info.cDistPoint = 1;
2895 info.rgDistPoint = &point;
2896 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2897 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2900 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
2901 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2904 /* A dist point with an invalid name */
2905 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2906 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2907 U(entry).pwszURL = (LPWSTR)nihongoURL;
2908 U(point.DistPointName).FullName.cAltEntry = 1;
2909 U(point.DistPointName).FullName.rgAltEntry = &entry;
2910 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2911 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2912 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2913 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
2914 /* The first invalid character is at index 7 */
2915 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2916 "Expected invalid char at index 7, got %d\n",
2917 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2918 /* A dist point with (just) a valid name */
2919 U(entry).pwszURL = (LPWSTR)url;
2920 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2921 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2924 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
2925 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2928 /* A dist point with (just) reason flags */
2929 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2930 point.ReasonFlags.cbData = sizeof(crlReason);
2931 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2932 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2933 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2936 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
2937 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2940 /* A dist point with just an issuer */
2941 point.ReasonFlags.cbData = 0;
2942 point.CRLIssuer.cAltEntry = 1;
2943 point.CRLIssuer.rgAltEntry = &entry;
2944 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2945 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2948 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
2949 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2952 /* A dist point with both a name and an issuer */
2953 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2954 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2955 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2958 ok(size == sizeof(distPointWithUrlAndIssuer),
2959 "Wrong size %d\n", size);
2960 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2965 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2970 PCRL_DIST_POINTS_INFO info;
2971 PCRL_DIST_POINT point;
2972 PCERT_ALT_NAME_ENTRY entry;
2974 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2975 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2976 (BYTE *)&buf, &size);
2979 info = (PCRL_DIST_POINTS_INFO)buf;
2980 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2981 "Wrong size %d\n", size);
2982 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
2984 point = info->rgDistPoint;
2985 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2986 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
2987 point->DistPointName.dwDistPointNameChoice);
2988 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2989 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2992 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2993 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2994 (BYTE *)&buf, &size);
2997 info = (PCRL_DIST_POINTS_INFO)buf;
2998 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2999 "Wrong size %d\n", size);
3000 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3002 point = info->rgDistPoint;
3003 ok(point->DistPointName.dwDistPointNameChoice ==
3004 CRL_DIST_POINT_FULL_NAME,
3005 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3006 point->DistPointName.dwDistPointNameChoice);
3007 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3008 "Expected 1 name entry, got %d\n",
3009 U(point->DistPointName).FullName.cAltEntry);
3010 entry = U(point->DistPointName).FullName.rgAltEntry;
3011 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3012 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3013 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3014 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3015 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3018 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3019 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3020 NULL, (BYTE *)&buf, &size);
3023 info = (PCRL_DIST_POINTS_INFO)buf;
3024 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3025 "Wrong size %d\n", size);
3026 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3028 point = info->rgDistPoint;
3029 ok(point->DistPointName.dwDistPointNameChoice ==
3030 CRL_DIST_POINT_NO_NAME,
3031 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3032 point->DistPointName.dwDistPointNameChoice);
3033 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3034 "Expected reason length\n");
3035 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3036 "Unexpected reason\n");
3037 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3040 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3041 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3042 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3045 info = (PCRL_DIST_POINTS_INFO)buf;
3046 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3047 "Wrong size %d\n", size);
3048 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3050 point = info->rgDistPoint;
3051 ok(point->DistPointName.dwDistPointNameChoice ==
3052 CRL_DIST_POINT_FULL_NAME,
3053 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3054 point->DistPointName.dwDistPointNameChoice);
3055 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3056 "Expected 1 name entry, got %d\n",
3057 U(point->DistPointName).FullName.cAltEntry);
3058 entry = U(point->DistPointName).FullName.rgAltEntry;
3059 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3060 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3061 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3062 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3063 ok(point->CRLIssuer.cAltEntry == 1,
3064 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3065 entry = point->CRLIssuer.rgAltEntry;
3066 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3067 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3068 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3073 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3074 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3075 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3076 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3079 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3084 CRL_ISSUING_DIST_POINT point = { { 0 } };
3085 CERT_ALT_NAME_ENTRY entry;
3087 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3088 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3089 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3091 skip("no X509_ISSUING_DIST_POINT encode support\n");
3094 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3095 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3096 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3097 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3098 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3101 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3102 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3105 /* nonsensical flags */
3106 point.fOnlyContainsUserCerts = TRUE;
3107 point.fOnlyContainsCACerts = TRUE;
3108 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3109 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3110 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3113 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3114 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3117 /* unimplemented name type */
3118 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3119 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3120 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3121 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3122 ok(!ret && GetLastError() == E_INVALIDARG,
3123 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3125 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3126 U(point.DistPointName).FullName.cAltEntry = 0;
3127 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3128 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3129 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3132 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3133 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3136 /* name with URL entry */
3137 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3138 U(entry).pwszURL = (LPWSTR)url;
3139 U(point.DistPointName).FullName.cAltEntry = 1;
3140 U(point.DistPointName).FullName.rgAltEntry = &entry;
3141 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3142 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3143 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3146 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3147 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3152 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3153 const CERT_ALT_NAME_ENTRY *got)
3155 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3156 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3157 got->dwAltNameChoice);
3158 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3160 switch (got->dwAltNameChoice)
3162 case CERT_ALT_NAME_RFC822_NAME:
3163 case CERT_ALT_NAME_DNS_NAME:
3164 case CERT_ALT_NAME_EDI_PARTY_NAME:
3165 case CERT_ALT_NAME_URL:
3166 case CERT_ALT_NAME_REGISTERED_ID:
3167 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3168 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
3170 case CERT_ALT_NAME_X400_ADDRESS:
3171 case CERT_ALT_NAME_DIRECTORY_NAME:
3172 case CERT_ALT_NAME_IP_ADDRESS:
3173 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3174 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3175 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3176 U(*got).IPAddress.cbData), "Unexpected value\n");
3182 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3183 const CERT_ALT_NAME_INFO *got)
3187 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3188 expected->cAltEntry, got->cAltEntry);
3189 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3190 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3193 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3194 const CRL_DIST_POINT_NAME *got)
3196 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3197 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3198 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3199 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3202 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3203 const CRL_ISSUING_DIST_POINT *got)
3205 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3206 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3207 "Unexpected fOnlyContainsUserCerts\n");
3208 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3209 "Unexpected fOnlyContainsCACerts\n");
3210 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3211 "Unexpected reason flags\n");
3212 ok(got->fIndirectCRL == expected->fIndirectCRL,
3213 "Unexpected fIndirectCRL\n");
3216 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3221 CRL_ISSUING_DIST_POINT point = { { 0 } };
3223 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3224 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3225 (BYTE *)&buf, &size);
3226 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3228 skip("no X509_ISSUING_DIST_POINT decode support\n");
3231 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3234 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3237 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3238 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3239 (BYTE *)&buf, &size);
3240 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3243 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3244 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3247 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3248 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3249 (BYTE *)&buf, &size);
3250 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3253 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3254 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3255 U(point.DistPointName).FullName.cAltEntry = 0;
3256 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3259 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3260 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3261 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3264 CERT_ALT_NAME_ENTRY entry;
3266 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3267 U(entry).pwszURL = (LPWSTR)url;
3268 U(point.DistPointName).FullName.cAltEntry = 1;
3269 U(point.DistPointName).FullName.rgAltEntry = &entry;
3270 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3275 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3276 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3278 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3279 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3280 0x30, 0x30, 0x30, 0x30, 0x5a };
3281 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3282 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3283 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3284 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3286 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3287 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3288 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3289 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3290 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3291 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3292 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3293 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3294 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3295 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3296 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3297 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3298 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3299 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3300 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3301 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3302 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3303 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3304 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3305 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3306 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3307 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3308 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3309 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3310 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3311 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3312 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3313 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3314 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3315 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3316 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3317 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3318 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3319 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3320 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3321 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3322 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3323 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3324 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3325 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3327 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3331 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3333 CRL_INFO info = { 0 };
3334 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3337 /* Test with a V1 CRL */
3338 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3339 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3340 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3343 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3344 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3348 info.dwVersion = CRL_V2;
3349 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3350 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3351 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3354 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3355 v2CRL[1] + 2, size);
3356 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3359 /* v1 CRL with a name */
3360 info.dwVersion = CRL_V1;
3361 info.Issuer.cbData = sizeof(encodedCommonName);
3362 info.Issuer.pbData = (BYTE *)encodedCommonName;
3363 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3364 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3365 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3368 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3369 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3372 /* v1 CRL with a name and a NULL entry pointer */
3374 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3375 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3376 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3377 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3378 /* now set an empty entry */
3379 info.rgCRLEntry = &entry;
3380 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3381 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3384 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3385 "Wrong size %d\n", size);
3386 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3387 "Got unexpected value\n");
3390 /* an entry with a serial number */
3391 entry.SerialNumber.cbData = sizeof(serialNum);
3392 entry.SerialNumber.pbData = (BYTE *)serialNum;
3393 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3394 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3397 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3398 "Wrong size %d\n", size);
3399 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3400 "Got unexpected value\n");
3403 /* an entry with an extension */
3404 entry.cExtension = 1;
3405 entry.rgExtension = &criticalExt;
3406 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3407 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3408 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3411 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3412 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3415 /* a CRL with an extension */
3416 entry.cExtension = 0;
3417 info.cExtension = 1;
3418 info.rgExtension = &criticalExt;
3419 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3420 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3421 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3424 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3425 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3428 /* a v2 CRL with an extension, this time non-critical */
3429 info.dwVersion = CRL_V2;
3430 info.rgExtension = &nonCriticalExt;
3431 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3432 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3433 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3436 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3437 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3440 /* a v2 CRL with an issuing dist point extension */
3441 ext.pszObjId = oid_issuing_dist_point;
3442 ext.fCritical = TRUE;
3443 ext.Value.cbData = sizeof(urlIDP);
3444 ext.Value.pbData = (LPBYTE)urlIDP;
3445 entry.rgExtension = &ext;
3446 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3447 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3448 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3451 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3452 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3457 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3458 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3459 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3460 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3461 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3462 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3463 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3464 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3465 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3466 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3467 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3468 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3469 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3470 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3471 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3472 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3473 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3474 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3475 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3476 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3477 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3478 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3479 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3480 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3481 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3482 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3483 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3484 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3485 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3486 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3487 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3488 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3489 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3490 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3492 static const BYTE verisignCRLWithLotsOfEntries[] = {
3493 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3494 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3495 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3496 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3497 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3498 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3499 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3500 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3501 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3502 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3503 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3504 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3505 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3506 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3507 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3508 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3509 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3510 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3511 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3512 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3513 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3514 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3515 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3516 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3517 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3518 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3519 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3520 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3521 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3522 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3523 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3524 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3525 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3526 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3527 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3528 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3529 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3530 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3531 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3532 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3533 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3534 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3535 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3536 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3537 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3538 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3539 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3540 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3541 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3542 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3543 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3544 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3545 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3546 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3547 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3548 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3549 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3550 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3551 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3552 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3553 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3554 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3555 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3556 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3557 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3558 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3559 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3560 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3561 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3562 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3563 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3564 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3565 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3566 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3567 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3568 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3569 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3570 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3571 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3572 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3573 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3574 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3575 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3576 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3577 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3578 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3579 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3580 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3581 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3582 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3583 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3584 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3585 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3586 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3587 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3588 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3589 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3590 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3591 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3592 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3593 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3594 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3595 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3596 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3597 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3598 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3599 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3600 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3601 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3602 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3603 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3604 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3605 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3606 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3607 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3608 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3609 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3610 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3611 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3612 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3613 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3614 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3615 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3616 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3617 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3618 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3619 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3620 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3621 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3622 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3623 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3624 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3625 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3626 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3627 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3628 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3629 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3630 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3631 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3632 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3633 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3634 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3635 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3636 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3637 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3638 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3639 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3640 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3641 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3642 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3643 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3644 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3645 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3646 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3647 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3648 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3649 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3650 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3651 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3652 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3653 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3654 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3655 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3656 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3657 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3658 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3659 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3660 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3661 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3662 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3663 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3664 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3665 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3666 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3667 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3668 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3669 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3670 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3671 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3672 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3673 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3674 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3675 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3676 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3677 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3678 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3679 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3680 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3681 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3682 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3683 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3684 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3685 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3686 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3687 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3688 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3689 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3690 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3691 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3692 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3693 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3694 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3695 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3696 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3697 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3698 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3699 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3700 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3701 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3702 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3703 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3704 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3705 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3706 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3707 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3708 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3709 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3710 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3711 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3712 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3713 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3714 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3715 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3716 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3717 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3718 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3719 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3720 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3721 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3722 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3723 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3724 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3725 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3726 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3727 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3728 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3729 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3730 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3731 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3732 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3733 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3734 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3735 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3736 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3737 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3738 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3739 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3740 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3741 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3742 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3743 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3744 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3745 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3746 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3747 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3748 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3749 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3750 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3751 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3752 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3753 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3754 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3755 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3756 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3757 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3758 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3759 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3760 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3761 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3762 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3763 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3764 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3765 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3766 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
3767 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
3768 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
3769 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
3770 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
3771 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
3772 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
3773 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
3774 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
3775 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
3776 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
3777 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
3778 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
3779 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
3780 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
3781 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
3782 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
3783 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
3784 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
3785 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
3786 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
3787 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
3788 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
3789 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
3790 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
3791 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
3792 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
3793 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
3794 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
3795 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
3796 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
3797 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
3798 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
3799 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
3800 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
3801 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
3802 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
3803 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
3804 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
3805 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
3806 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
3807 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
3808 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
3809 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
3810 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
3811 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
3812 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
3813 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
3814 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
3815 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
3816 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
3817 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
3818 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
3819 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
3820 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
3821 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
3822 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
3823 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
3824 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
3825 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
3826 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
3827 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
3828 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
3829 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
3830 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
3831 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
3832 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
3833 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
3834 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
3835 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
3836 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
3837 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
3838 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
3839 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
3840 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
3841 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
3842 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
3843 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
3844 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
3845 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
3846 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
3847 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
3848 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
3849 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
3850 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
3851 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
3852 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
3853 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
3854 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
3855 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
3856 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
3857 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
3858 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
3859 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
3860 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
3861 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
3862 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
3863 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
3864 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
3865 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
3866 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
3867 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
3868 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
3869 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
3870 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
3871 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
3872 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
3873 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
3874 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
3875 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
3876 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
3877 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
3878 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
3879 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
3880 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
3881 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
3882 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
3883 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
3884 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
3885 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
3886 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
3887 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
3888 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
3889 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
3890 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
3891 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
3892 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
3893 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
3894 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
3895 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
3896 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
3897 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
3898 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
3899 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
3900 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
3901 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
3902 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
3903 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
3904 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
3905 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
3906 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
3907 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
3908 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
3909 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
3910 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
3911 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
3912 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
3913 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
3914 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
3915 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
3916 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
3917 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
3918 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
3919 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
3920 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
3921 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
3922 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
3923 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
3924 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
3925 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
3926 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
3927 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
3928 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
3929 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
3930 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
3931 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
3932 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
3933 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
3934 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
3935 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
3936 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
3937 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
3938 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
3939 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
3940 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
3941 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
3942 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
3943 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
3944 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
3945 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
3946 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
3947 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
3948 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
3949 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
3950 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
3951 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
3952 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
3953 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
3954 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
3955 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3956 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
3957 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
3958 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
3959 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
3960 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
3961 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
3962 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
3963 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
3964 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
3965 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
3966 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
3967 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
3968 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
3969 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
3970 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
3971 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
3972 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
3973 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
3974 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
3975 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
3976 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
3977 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
3978 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
3979 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
3980 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
3981 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
3982 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
3983 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
3984 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
3985 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
3986 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
3987 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
3988 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
3989 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
3990 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
3991 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
3992 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
3993 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
3994 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
3995 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
3996 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
3997 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
3998 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
3999 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4000 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4002 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4004 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4009 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4011 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4012 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4013 (BYTE *)&buf, &size);
4014 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4015 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4017 /* at a minimum, a CRL must contain an issuer: */
4018 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4019 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4020 (BYTE *)&buf, &size);
4021 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4024 CRL_INFO *info = (CRL_INFO *)buf;
4026 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4027 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4029 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4030 "Wrong issuer size %d\n", info->Issuer.cbData);
4031 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4032 "Unexpected issuer\n");
4035 /* check decoding with an empty CRL entry */
4036 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4037 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4038 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4039 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4040 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4041 /* with a real CRL entry */
4042 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4043 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4044 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4045 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4048 CRL_INFO *info = (CRL_INFO *)buf;
4051 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4052 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4054 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4055 entry = info->rgCRLEntry;
4056 ok(entry->SerialNumber.cbData == 1,
4057 "Expected serial number size 1, got %d\n",
4058 entry->SerialNumber.cbData);
4059 ok(*entry->SerialNumber.pbData == *serialNum,
4060 "Expected serial number %d, got %d\n", *serialNum,
4061 *entry->SerialNumber.pbData);
4062 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4063 "Wrong issuer size %d\n", info->Issuer.cbData);
4064 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4065 "Unexpected issuer\n");
4067 /* a real CRL from verisign that has extensions */
4068 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4069 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4070 NULL, (BYTE *)&buf, &size);
4071 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4074 CRL_INFO *info = (CRL_INFO *)buf;
4077 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4078 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4080 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4081 entry = info->rgCRLEntry;
4082 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4086 /* another real CRL from verisign that has lots of entries */
4087 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4088 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4089 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4090 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4093 CRL_INFO *info = (CRL_INFO *)buf;
4095 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4096 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4098 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4102 /* and finally, with an extension */
4103 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4104 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4105 NULL, (BYTE *)&buf, &size);
4106 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4109 CRL_INFO *info = (CRL_INFO *)buf;
4112 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4113 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4115 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4116 entry = info->rgCRLEntry;
4117 ok(entry->SerialNumber.cbData == 1,
4118 "Expected serial number size 1, got %d\n",
4119 entry->SerialNumber.cbData);
4120 ok(*entry->SerialNumber.pbData == *serialNum,
4121 "Expected serial number %d, got %d\n", *serialNum,
4122 *entry->SerialNumber.pbData);
4123 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4124 "Wrong issuer size %d\n", info->Issuer.cbData);
4125 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4126 "Unexpected issuer\n");
4127 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4130 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4131 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4132 NULL, (BYTE *)&buf, &size);
4133 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4136 CRL_INFO *info = (CRL_INFO *)buf;
4138 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4142 /* And again, with an issuing dist point */
4143 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4144 v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4145 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4146 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4149 CRL_INFO *info = (CRL_INFO *)buf;
4151 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4157 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4158 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4159 static const BYTE encodedUsage[] = {
4160 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4161 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4162 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4164 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4169 CERT_ENHKEY_USAGE usage;
4171 /* Test with empty usage */
4172 usage.cUsageIdentifier = 0;
4173 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4174 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4175 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4178 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4179 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4182 /* Test with a few usages */
4183 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4184 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4185 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4186 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4187 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4190 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4191 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4196 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4202 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4203 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4204 (BYTE *)&buf, &size);
4205 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4208 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4210 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4211 "Wrong size %d\n", size);
4212 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4213 usage->cUsageIdentifier);
4216 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4217 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4218 (BYTE *)&buf, &size);
4219 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4222 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4225 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4226 "Wrong size %d\n", size);
4227 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4228 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4229 for (i = 0; i < usage->cUsageIdentifier; i++)
4230 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4231 "Expected OID %s, got %s\n", keyUsages[i],
4232 usage->rgpszUsageIdentifier[i]);
4237 static const BYTE authorityKeyIdWithId[] = { 0x30,0x03,0x80,0x01,0x01 };
4238 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4239 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4240 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4241 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4243 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4245 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4250 /* Test with empty id */
4251 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4252 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4253 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4256 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4257 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4260 /* With just a key id */
4261 info.KeyId.cbData = sizeof(serialNum);
4262 info.KeyId.pbData = (BYTE *)serialNum;
4263 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4264 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4265 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4268 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4269 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4272 /* With just an issuer */
4273 info.KeyId.cbData = 0;
4274 info.CertIssuer.cbData = sizeof(encodedCommonName);
4275 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4276 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4277 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4278 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4281 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4283 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4286 /* With just a serial number */
4287 info.CertIssuer.cbData = 0;
4288 info.CertSerialNumber.cbData = sizeof(serialNum);
4289 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4290 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4291 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4292 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4295 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4297 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4302 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4308 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4309 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4310 (BYTE *)&buf, &size);
4311 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4314 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4316 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4318 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4319 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4320 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4323 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4324 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4325 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4326 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4329 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4331 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4333 ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4334 ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4335 "Unexpected key id\n");
4336 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4337 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4340 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4341 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4342 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4343 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4346 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4348 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4350 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4351 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4352 "Unexpected issuer len\n");
4353 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4354 sizeof(encodedCommonName)), "Unexpected issuer\n");
4355 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4358 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4359 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4360 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4361 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4364 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4366 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4368 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4369 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4370 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4371 "Unexpected serial number len\n");
4372 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4373 "Unexpected serial number\n");
4378 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4379 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4382 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4384 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4385 CERT_ALT_NAME_ENTRY entry = { 0 };
4390 /* Test with empty id */
4391 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4392 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4393 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4396 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4397 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4400 /* With just a key id */
4401 info.KeyId.cbData = sizeof(serialNum);
4402 info.KeyId.pbData = (BYTE *)serialNum;
4403 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4404 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4405 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4408 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4410 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4413 /* With a bogus issuer name */
4414 info.KeyId.cbData = 0;
4415 info.AuthorityCertIssuer.cAltEntry = 1;
4416 info.AuthorityCertIssuer.rgAltEntry = &entry;
4417 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4418 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4419 ok(!ret && GetLastError() == E_INVALIDARG,
4420 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4421 /* With an issuer name */
4422 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4423 U(entry).pwszURL = (LPWSTR)url;
4424 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4425 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4426 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4429 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4431 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4432 "Unexpected value\n");
4435 /* With just a serial number */
4436 info.AuthorityCertIssuer.cAltEntry = 0;
4437 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4438 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4439 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4440 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4441 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4444 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4446 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4451 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4457 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4458 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4459 (BYTE *)&buf, &size);
4460 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4463 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4465 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4467 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4468 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4469 "Expected no issuer name entries\n");
4470 ok(info->AuthorityCertSerialNumber.cbData == 0,
4471 "Expected no serial number\n");
4474 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4475 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4476 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4477 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4480 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4482 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4484 ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4485 ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4486 "Unexpected key id\n");
4487 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4488 "Expected no issuer name entries\n");
4489 ok(info->AuthorityCertSerialNumber.cbData == 0,
4490 "Expected no serial number\n");
4493 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4494 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4495 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4496 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4499 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4501 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4503 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4504 ok(info->AuthorityCertIssuer.cAltEntry == 1,
4505 "Expected 1 issuer entry, got %d\n",
4506 info->AuthorityCertIssuer.cAltEntry);
4507 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4508 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4509 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4510 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4511 url), "Unexpected URL\n");
4512 ok(info->AuthorityCertSerialNumber.cbData == 0,
4513 "Expected no serial number\n");
4516 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4517 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4518 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4519 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4522 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4524 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4526 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4527 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4528 "Expected no issuer name entries\n");
4529 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4530 "Unexpected serial number len\n");
4531 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4532 sizeof(serialNum)), "Unexpected serial number\n");
4537 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
4538 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
4540 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
4541 0x03,0x02,0x01,0x01 };
4542 static BYTE bogusDER[] = { 1 };
4544 static void test_encodePKCSContentInfo(DWORD dwEncoding)
4549 CRYPT_CONTENT_INFO info = { 0 };
4550 char oid1[] = "1.2.3";
4552 SetLastError(0xdeadbeef);
4553 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
4554 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4555 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4556 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4557 SetLastError(0xdeadbeef);
4558 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4559 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4560 ok(!ret && GetLastError() == E_INVALIDARG,
4561 "Expected E_INVALIDARG, got %x\n", GetLastError());
4562 info.pszObjId = oid1;
4563 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4564 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4565 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4568 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
4569 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
4572 info.Content.pbData = bogusDER;
4573 info.Content.cbData = sizeof(bogusDER);
4574 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4575 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4576 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
4579 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
4580 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
4583 info.Content.pbData = (BYTE *)ints[0].encoded;
4584 info.Content.cbData = ints[0].encoded[1] + 2;
4585 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4586 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4589 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
4590 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
4595 static void test_decodePKCSContentInfo(DWORD dwEncoding)
4600 CRYPT_CONTENT_INFO *info;
4602 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4603 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
4604 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4605 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4608 info = (CRYPT_CONTENT_INFO *)buf;
4610 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4612 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
4613 info->Content.cbData);
4616 SetLastError(0xdeadbeef);
4617 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4618 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
4619 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4620 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4621 * I doubt an app depends on that.
4623 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4624 GetLastError() == CRYPT_E_ASN1_CORRUPT),
4625 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4627 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4628 intPKCSContentInfo, sizeof(intPKCSContentInfo),
4629 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4630 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4633 info = (CRYPT_CONTENT_INFO *)buf;
4635 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4637 ok(info->Content.cbData == ints[0].encoded[1] + 2,
4638 "Unexpected size %d\n", info->Content.cbData);
4639 ok(!memcmp(info->Content.pbData, ints[0].encoded,
4640 info->Content.cbData), "Unexpected value\n");
4644 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
4646 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
4648 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
4651 static void test_encodePKCSAttribute(DWORD dwEncoding)
4653 CRYPT_ATTRIBUTE attr = { 0 };
4657 CRYPT_ATTR_BLOB blob;
4658 char oid[] = "1.2.3";
4660 SetLastError(0xdeadbeef);
4661 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
4662 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4663 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4664 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4665 SetLastError(0xdeadbeef);
4666 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4667 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4668 ok(!ret && GetLastError() == E_INVALIDARG,
4669 "Expected E_INVALIDARG, got %x\n", GetLastError());
4670 attr.pszObjId = oid;
4671 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4672 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4673 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4676 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
4677 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
4680 blob.cbData = sizeof(bogusDER);
4681 blob.pbData = bogusDER;
4683 attr.rgValue = &blob;
4684 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4685 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4686 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4689 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
4690 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
4693 blob.pbData = (BYTE *)ints[0].encoded;
4694 blob.cbData = ints[0].encoded[1] + 2;
4695 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4696 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4699 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
4700 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
4705 static void test_decodePKCSAttribute(DWORD dwEncoding)
4710 CRYPT_ATTRIBUTE *attr;
4712 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4713 emptyPKCSAttr, sizeof(emptyPKCSAttr),
4714 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4715 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4718 attr = (CRYPT_ATTRIBUTE *)buf;
4720 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4722 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
4725 SetLastError(0xdeadbeef);
4726 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4727 bogusPKCSAttr, sizeof(bogusPKCSAttr),
4728 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4729 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4730 * I doubt an app depends on that.
4732 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4733 GetLastError() == CRYPT_E_ASN1_CORRUPT),
4734 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4736 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4737 intPKCSAttr, sizeof(intPKCSAttr),
4738 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4739 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4742 attr = (CRYPT_ATTRIBUTE *)buf;
4744 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4746 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
4747 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
4748 "Unexpected size %d\n", attr->rgValue[0].cbData);
4749 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
4750 attr->rgValue[0].cbData), "Unexpected value\n");
4754 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
4755 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
4756 0x2a,0x03,0x31,0x00 };
4757 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
4758 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
4760 static void test_encodePKCSAttributes(DWORD dwEncoding)
4762 CRYPT_ATTRIBUTES attributes = { 0 };
4763 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
4764 CRYPT_ATTR_BLOB blob;
4768 char oid1[] = "1.2.3", oid2[] = "1.5.6";
4770 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4771 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4772 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4775 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
4776 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
4779 attributes.cAttr = 1;
4780 attributes.rgAttr = attr;
4781 SetLastError(0xdeadbeef);
4782 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4783 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4784 ok(!ret && GetLastError() == E_INVALIDARG,
4785 "Expected E_INVALIDARG, got %x\n", GetLastError());
4786 attr[0].pszObjId = oid1;
4787 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4788 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4791 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
4792 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
4795 attr[1].pszObjId = oid2;
4797 attr[1].rgValue = &blob;
4798 blob.pbData = (BYTE *)ints[0].encoded;
4799 blob.cbData = ints[0].encoded[1] + 2;
4800 attributes.cAttr = 2;
4801 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4802 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4803 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4806 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
4807 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
4812 static void test_decodePKCSAttributes(DWORD dwEncoding)
4817 CRYPT_ATTRIBUTES *attributes;
4819 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
4820 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
4821 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4822 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4825 attributes = (CRYPT_ATTRIBUTES *)buf;
4826 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
4830 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
4831 singlePKCSAttributes, sizeof(singlePKCSAttributes),
4832 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4833 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4836 attributes = (CRYPT_ATTRIBUTES *)buf;
4837 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
4839 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
4840 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
4841 ok(attributes->rgAttr[0].cValue == 0,
4842 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
4845 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
4846 doublePKCSAttributes, sizeof(doublePKCSAttributes),
4847 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4848 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4851 attributes = (CRYPT_ATTRIBUTES *)buf;
4852 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
4854 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
4855 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
4856 ok(attributes->rgAttr[0].cValue == 0,
4857 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
4858 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
4859 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
4860 ok(attributes->rgAttr[1].cValue == 1,
4861 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
4862 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
4863 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
4864 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
4865 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
4870 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
4871 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
4873 /* As with the algorithm ID tests, accept the algorithm ID parameters either as
4874 * NULL or as nonexistent.
4876 static const BYTE minimalPKCSSigner[] = {
4877 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4878 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4879 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
4880 static const BYTE minimalPKCSSignerNoNull[] = {
4881 0x30,0x27,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4882 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4883 0x00,0x30,0x02,0x06,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
4884 static const BYTE PKCSSignerWithSerial[] = {
4885 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4886 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4887 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
4889 static const BYTE PKCSSignerWithSerialNoNull[] = {
4890 0x30,0x28,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4891 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4892 0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
4893 static const BYTE PKCSSignerWithHashAlgo[] = {
4894 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4895 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4896 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
4898 static const BYTE PKCSSignerWithHashAlgoNoNull[] = {
4899 0x30,0x2a,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4900 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4901 0x01,0x01,0x30,0x04,0x06,0x02,0x2a,0x03,0x30,0x02,0x06,0x00,0x04,0x00 };
4902 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
4903 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4904 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4905 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
4906 0x06,0x05,0x00,0x04,0x00 };
4907 static const BYTE PKCSSignerWithHashAndEncryptionAlgoNoNull[] = {
4908 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4909 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4910 0x01,0x01,0x30,0x04,0x06,0x02,0x2a,0x03,0x30,0x04,0x06,0x02,0x2d,0x06,0x04,
4912 static const BYTE PKCSSignerWithHash[] = {
4913 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4914 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4915 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
4916 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
4917 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
4918 static const BYTE PKCSSignerWithHashNoNull[] = {
4919 0x30,0x3c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4920 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4921 0x01,0x01,0x30,0x04,0x06,0x02,0x2a,0x03,0x30,0x04,0x06,0x02,0x2d,
4922 0x06,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
4923 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
4925 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
4927 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
4931 CMSG_SIGNER_INFO info = { 0 };
4933 SetLastError(0xdeadbeef);
4934 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4935 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4936 ok(!ret && GetLastError() == E_INVALIDARG,
4937 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4938 /* To be encoded, a signer must have an issuer at least, and the encoding
4939 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
4940 * see decoding tests.)
4942 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
4943 info.Issuer.pbData = encodedCommonNameNoNull;
4944 SetLastError(0xdeadbeef);
4945 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4946 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4947 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
4948 ok(!ret && GetLastError() == E_INVALIDARG,
4949 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4952 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4955 ok(size == sizeof(minimalPKCSSigner) ||
4956 size == sizeof(minimalPKCSSignerNoNull), "Unexpected size %d\n",
4958 if (size == sizeof(minimalPKCSSigner))
4959 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
4960 else if (size == sizeof(minimalPKCSSignerNoNull))
4961 ok(!memcmp(buf, minimalPKCSSignerNoNull, size),
4962 "Unexpected value\n");
4964 ok(0, "Unexpected value\n");
4968 info.SerialNumber.cbData = sizeof(serialNum);
4969 info.SerialNumber.pbData = (BYTE *)serialNum;
4970 SetLastError(0xdeadbeef);
4971 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4972 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4973 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
4974 ok(!ret && GetLastError() == E_INVALIDARG,
4975 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4978 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4981 ok(size == sizeof(PKCSSignerWithSerial) ||
4982 size == sizeof(PKCSSignerWithSerialNoNull), "Unexpected size %d\n",
4984 if (size == sizeof(PKCSSignerWithSerial))
4985 ok(!memcmp(buf, PKCSSignerWithSerial, size),
4986 "Unexpected value\n");
4987 else if (size == sizeof(PKCSSignerWithSerialNoNull))
4988 ok(!memcmp(buf, PKCSSignerWithSerialNoNull, size),
4989 "Unexpected value\n");
4991 ok(0, "Unexpected value\n");
4995 info.HashAlgorithm.pszObjId = oid1;
4996 SetLastError(0xdeadbeef);
4997 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4998 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4999 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5000 ok(!ret && GetLastError() == E_INVALIDARG,
5001 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5004 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5007 ok(size == sizeof(PKCSSignerWithHashAlgo) ||
5008 size == sizeof(PKCSSignerWithHashAlgoNoNull),
5009 "Unexpected size %d\n", size);
5010 if (size == sizeof(PKCSSignerWithHashAlgo))
5011 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
5012 "Unexpected value\n");
5013 else if (size == sizeof(PKCSSignerWithHashAlgoNoNull))
5014 ok(!memcmp(buf, PKCSSignerWithHashAlgoNoNull, size),
5015 "Unexpected value\n");
5017 ok(0, "Unexpected value\n");
5021 info.HashEncryptionAlgorithm.pszObjId = oid2;
5022 SetLastError(0xdeadbeef);
5023 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5024 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5025 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5026 ok(!ret && GetLastError() == E_INVALIDARG,
5027 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5030 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5033 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo) ||
5034 size == sizeof(PKCSSignerWithHashAndEncryptionAlgoNoNull),
5035 "Unexpected size %d\n", size);
5036 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
5037 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
5038 "Unexpected value\n");
5039 else if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgoNoNull))
5040 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgoNoNull,
5041 size), "Unexpected value\n");
5043 ok(0, "Unexpected value\n");
5047 info.EncryptedHash.cbData = sizeof(hash);
5048 info.EncryptedHash.pbData = (BYTE *)hash;
5049 SetLastError(0xdeadbeef);
5050 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5051 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5052 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5053 ok(!ret && GetLastError() == E_INVALIDARG,
5054 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5057 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5060 ok(size == sizeof(PKCSSignerWithHash) ||
5061 size == sizeof(PKCSSignerWithHashNoNull), "Unexpected size %d\n",
5063 if (size == sizeof(PKCSSignerWithHash))
5064 ok(!memcmp(buf, PKCSSignerWithHash, size),
5065 "Unexpected value\n");
5066 else if (size == sizeof(PKCSSignerWithHashNoNull))
5067 ok(!memcmp(buf, PKCSSignerWithHashNoNull, size),
5068 "Unexpected value\n");
5070 ok(0, "Unexpected value\n");
5076 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
5081 CMSG_SIGNER_INFO *info;
5083 /* A PKCS signer can't be decoded without a serial number. */
5084 SetLastError(0xdeadbeef);
5085 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5086 minimalPKCSSigner, sizeof(minimalPKCSSigner),
5087 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5088 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
5089 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
5090 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5091 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
5092 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5093 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5096 info = (CMSG_SIGNER_INFO *)buf;
5097 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5099 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5100 "Unexpected size %d\n", info->Issuer.cbData);
5101 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5102 info->Issuer.cbData), "Unexpected value\n");
5103 ok(info->SerialNumber.cbData == sizeof(serialNum),
5104 "Unexpected size %d\n", info->SerialNumber.cbData);
5105 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5106 "Unexpected value\n");
5109 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5110 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
5111 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5114 info = (CMSG_SIGNER_INFO *)buf;
5115 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5117 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5118 "Unexpected size %d\n", info->Issuer.cbData);
5119 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5120 info->Issuer.cbData), "Unexpected value\n");
5121 ok(info->SerialNumber.cbData == sizeof(serialNum),
5122 "Unexpected size %d\n", info->SerialNumber.cbData);
5123 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5124 "Unexpected value\n");
5125 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5126 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5129 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5130 PKCSSignerWithHashAndEncryptionAlgo,
5131 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
5132 NULL, (BYTE *)&buf, &size);
5135 info = (CMSG_SIGNER_INFO *)buf;
5136 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5138 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5139 "Unexpected size %d\n", info->Issuer.cbData);
5140 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5141 info->Issuer.cbData), "Unexpected value\n");
5142 ok(info->SerialNumber.cbData == sizeof(serialNum),
5143 "Unexpected size %d\n", info->SerialNumber.cbData);
5144 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5145 "Unexpected value\n");
5146 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5147 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5148 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5149 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5152 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5153 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
5154 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5157 info = (CMSG_SIGNER_INFO *)buf;
5158 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5160 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5161 "Unexpected size %d\n", info->Issuer.cbData);
5162 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5163 info->Issuer.cbData), "Unexpected value\n");
5164 ok(info->SerialNumber.cbData == sizeof(serialNum),
5165 "Unexpected size %d\n", info->SerialNumber.cbData);
5166 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5167 "Unexpected value\n");
5168 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5169 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5170 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5171 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5172 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
5173 info->EncryptedHash.cbData);
5174 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
5175 "Unexpected value\n");
5180 /* Free *pInfo with HeapFree */
5181 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
5188 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
5190 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
5191 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5192 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5193 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
5195 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5196 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5197 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
5199 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5200 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5201 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5202 0, NULL, NULL, &size);
5203 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5204 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5205 /* Test with no key */
5206 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5207 0, NULL, NULL, &size);
5208 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
5210 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
5211 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
5214 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
5215 NULL, 0, NULL, NULL, &size);
5216 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
5217 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
5220 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
5221 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
5222 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
5226 /* By default (we passed NULL as the OID) the OID is
5229 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
5230 "Expected %s, got %s\n", szOID_RSA_RSA,
5231 (*pInfo)->Algorithm.pszObjId);
5237 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
5238 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
5239 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
5240 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5241 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5242 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5243 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
5244 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
5245 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5246 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5247 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5248 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5249 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
5250 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
5251 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
5252 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
5253 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
5254 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
5255 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
5256 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
5257 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
5258 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
5259 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
5260 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
5261 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
5263 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
5267 PCCERT_CONTEXT context;
5270 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
5271 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
5272 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
5273 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5276 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
5277 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5278 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5279 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
5280 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5281 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5282 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
5284 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5285 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5286 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5288 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5289 CryptDestroyKey(key);
5291 /* Test importing a public key from a certificate context */
5292 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
5293 sizeof(expiredCert));
5294 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
5298 ok(!strcmp(szOID_RSA_RSA,
5299 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
5300 "Expected %s, got %s\n", szOID_RSA_RSA,
5301 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
5302 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
5303 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
5304 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5305 CryptDestroyKey(key);
5306 CertFreeCertificateContext(context);
5310 static const char cspName[] = "WineCryptTemp";
5312 static void testPortPublicKeyInfo(void)
5316 PCERT_PUBLIC_KEY_INFO info = NULL;
5318 /* Just in case a previous run failed, delete this thing */
5319 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5320 CRYPT_DELETEKEYSET);
5321 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5324 testExportPublicKey(csp, &info);
5325 testImportPublicKey(csp, info);
5327 HeapFree(GetProcessHeap(), 0, info);
5328 CryptReleaseContext(csp, 0);
5329 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5330 CRYPT_DELETEKEYSET);
5335 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
5336 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
5339 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
5341 test_encodeInt(encodings[i]);
5342 test_decodeInt(encodings[i]);
5343 test_encodeEnumerated(encodings[i]);
5344 test_decodeEnumerated(encodings[i]);
5345 test_encodeFiletime(encodings[i]);
5346 test_decodeFiletime(encodings[i]);
5347 test_encodeName(encodings[i]);
5348 test_decodeName(encodings[i]);
5349 test_encodeUnicodeName(encodings[i]);
5350 test_decodeUnicodeName(encodings[i]);
5351 test_encodeNameValue(encodings[i]);
5352 test_decodeNameValue(encodings[i]);
5353 test_encodeUnicodeNameValue(encodings[i]);
5354 test_decodeUnicodeNameValue(encodings[i]);
5355 test_encodeAltName(encodings[i]);
5356 test_decodeAltName(encodings[i]);
5357 test_encodeOctets(encodings[i]);
5358 test_decodeOctets(encodings[i]);
5359 test_encodeBits(encodings[i]);
5360 test_decodeBits(encodings[i]);
5361 test_encodeBasicConstraints(encodings[i]);
5362 test_decodeBasicConstraints(encodings[i]);
5363 test_encodeRsaPublicKey(encodings[i]);
5364 test_decodeRsaPublicKey(encodings[i]);
5365 test_encodeSequenceOfAny(encodings[i]);
5366 test_decodeSequenceOfAny(encodings[i]);
5367 test_encodeExtensions(encodings[i]);
5368 test_decodeExtensions(encodings[i]);
5369 test_encodePublicKeyInfo(encodings[i]);
5370 test_decodePublicKeyInfo(encodings[i]);
5371 test_encodeCertToBeSigned(encodings[i]);
5372 test_decodeCertToBeSigned(encodings[i]);
5373 test_encodeCert(encodings[i]);
5374 test_decodeCert(encodings[i]);
5375 test_encodeCRLDistPoints(encodings[i]);
5376 test_decodeCRLDistPoints(encodings[i]);
5377 test_encodeCRLIssuingDistPoint(encodings[i]);
5378 test_decodeCRLIssuingDistPoint(encodings[i]);
5379 test_encodeCRLToBeSigned(encodings[i]);
5380 test_decodeCRLToBeSigned(encodings[i]);
5381 test_encodeEnhancedKeyUsage(encodings[i]);
5382 test_decodeEnhancedKeyUsage(encodings[i]);
5383 test_encodeAuthorityKeyId(encodings[i]);
5384 test_decodeAuthorityKeyId(encodings[i]);
5385 test_encodeAuthorityKeyId2(encodings[i]);
5386 test_decodeAuthorityKeyId2(encodings[i]);
5387 test_encodePKCSContentInfo(encodings[i]);
5388 test_decodePKCSContentInfo(encodings[i]);
5389 test_encodePKCSAttribute(encodings[i]);
5390 test_decodePKCSAttribute(encodings[i]);
5391 test_encodePKCSAttributes(encodings[i]);
5392 test_decodePKCSAttributes(encodings[i]);
5393 test_encodePKCSSignerInfo(encodings[i]);
5394 test_decodePKCSSignerInfo(encodings[i]);
5396 testPortPublicKeyInfo();