crypt32: Test and fix encoding and decoding of attributes in PKCS signers.
[wine/multimedia.git] / dlls / crypt32 / tests / encode.c
blob467619a964b21ee8afb3e5a23212373ecf9a19fc
1 /*
2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
4 * Copyright 2005 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
27 #include "wine/test.h"
29 struct encodedInt
31 int val;
32 const BYTE *encoded;
35 static const BYTE bin1[] = {0x02,0x01,0x01};
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[] = {
44 { 1, bin1 },
45 { 127, bin2 },
46 { 128, bin3 },
47 { 256, bin4 },
48 { -128, bin5 },
49 { -129, bin6 },
50 { 0xbaddf00d, bin7 },
53 struct encodedBigInt
55 const BYTE *val;
56 const BYTE *encoded;
57 const BYTE *decoded;
60 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
61 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
62 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
64 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
65 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
66 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
68 static const struct encodedBigInt bigInts[] = {
69 { bin8, bin9, bin10 },
70 { bin11, bin12, bin13 },
73 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
74 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
75 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
76 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 /* Decoded is the same as original, so don't bother storing a separate copy */
79 static const struct encodedBigInt bigUInts[] = {
80 { bin14, bin15, NULL },
81 { bin16, bin17, NULL },
84 static void test_encodeInt(DWORD dwEncoding)
86 DWORD bufSize = 0;
87 int i;
88 BOOL ret;
89 CRYPT_INTEGER_BLOB blob;
90 BYTE *buf = NULL;
92 /* CryptEncodeObjectEx with NULL bufSize crashes..
93 ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
94 NULL);
96 /* check bogus encoding */
97 ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98 &bufSize);
99 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
100 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
101 /* check with NULL integer buffer. Windows XP incorrectly returns an
102 * NTSTATUS.
104 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
105 &bufSize);
106 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
107 "Expected STATUS_ACCESS_VIOLATION, got %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());
117 if (buf)
119 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
120 buf[0]);
121 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
122 buf[1], ints[i].encoded[1]);
123 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
124 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
125 LocalFree(buf);
127 /* encode as multibyte integer */
128 blob.cbData = sizeof(ints[i].val);
129 blob.pbData = (BYTE *)&ints[i].val;
130 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
131 0, NULL, NULL, &bufSize);
132 ok(ret, "Expected success, got %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());
136 if (buf)
138 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
139 buf[0]);
140 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
141 buf[1], ints[i].encoded[1]);
142 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
143 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
144 LocalFree(buf);
147 /* encode a couple bigger ints, just to show it's little-endian and leading
148 * sign bytes are dropped
150 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
152 blob.cbData = strlen((const char*)bigInts[i].val);
153 blob.pbData = (BYTE *)bigInts[i].val;
154 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
155 0, NULL, NULL, &bufSize);
156 ok(ret, "Expected success, got %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());
160 if (buf)
162 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
163 buf[0]);
164 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
165 buf[1], bigInts[i].encoded[1]);
166 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
167 bigInts[i].encoded[1] + 1),
168 "Encoded value didn't match expected\n");
169 LocalFree(buf);
172 /* and, encode some uints */
173 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
175 blob.cbData = strlen((const char*)bigUInts[i].val);
176 blob.pbData = (BYTE*)bigUInts[i].val;
177 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
178 0, NULL, NULL, &bufSize);
179 ok(ret, "Expected success, got %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());
183 if (buf)
185 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
186 buf[0]);
187 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
188 buf[1], bigUInts[i].encoded[1]);
189 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
190 bigUInts[i].encoded[1] + 1),
191 "Encoded value didn't match expected\n");
192 LocalFree(buf);
197 static void test_decodeInt(DWORD dwEncoding)
199 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
200 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
201 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
202 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
203 static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
204 BYTE *buf = NULL;
205 DWORD bufSize = 0;
206 int i;
207 BOOL ret;
209 /* CryptDecodeObjectEx with NULL bufSize crashes..
210 ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
211 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
213 /* check bogus encoding */
214 ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
215 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
216 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
217 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
218 /* check with NULL integer buffer */
219 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
220 &bufSize);
221 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
222 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
223 /* check with a valid, but too large, integer */
224 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
225 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
226 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
227 "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
228 /* check with a DER-encoded string */
229 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
230 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
231 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
232 "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError());
233 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
235 /* When the output buffer is NULL, this always succeeds */
236 SetLastError(0xdeadbeef);
237 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
238 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
239 &bufSize);
240 ok(ret && GetLastError() == NOERROR,
241 "Expected success and NOERROR, got %d\n", GetLastError());
242 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
243 ints[i].encoded, ints[i].encoded[1] + 2,
244 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
245 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
246 ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
247 ok(buf != NULL, "Expected allocated buffer\n");
248 if (buf)
250 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
251 ints[i].val, *(int *)buf);
252 LocalFree(buf);
255 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
257 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
258 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
259 &bufSize);
260 ok(ret && GetLastError() == NOERROR,
261 "Expected success and NOERROR, got %d\n", GetLastError());
262 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
263 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
264 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
265 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
266 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
267 ok(buf != NULL, "Expected allocated buffer\n");
268 if (buf)
270 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
272 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
273 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
274 blob->cbData);
275 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
276 "Unexpected value\n");
277 LocalFree(buf);
280 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
282 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
283 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
284 &bufSize);
285 ok(ret && GetLastError() == NOERROR,
286 "Expected success and NOERROR, got %d\n", GetLastError());
287 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
288 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
289 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
290 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
291 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
292 ok(buf != NULL, "Expected allocated buffer\n");
293 if (buf)
295 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
297 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
298 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
299 blob->cbData);
300 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
301 "Unexpected value\n");
302 LocalFree(buf);
305 /* Decode the value 1 with long-form length */
306 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
307 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
308 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
309 if (buf)
311 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
312 LocalFree(buf);
314 /* check with extra bytes at the end */
315 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
316 sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
317 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
318 if (buf)
320 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
321 LocalFree(buf);
323 /* Try to decode some bogus large items */
324 /* The buffer size is smaller than the encoded length, so this should fail
325 * with CRYPT_E_ASN1_EOD if it's being decoded.
326 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
327 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
328 * So this test unfortunately isn't useful.
329 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
330 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
331 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
332 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
334 /* This will try to decode the buffer and overflow it, check that it's
335 * caught.
337 if (0)
339 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
340 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
341 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
342 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
343 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
347 static const BYTE bin18[] = {0x0a,0x01,0x01};
348 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
350 /* These are always encoded unsigned, and aren't constrained to be any
351 * particular value
353 static const struct encodedInt enums[] = {
354 { 1, bin18 },
355 { -128, bin19 },
358 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
359 * X509_ENUMERATED.
361 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
362 szOID_CRL_REASON_CODE };
364 static void test_encodeEnumerated(DWORD dwEncoding)
366 DWORD i, j;
368 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
370 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
372 BOOL ret;
373 BYTE *buf = NULL;
374 DWORD bufSize = 0;
376 ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
377 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
378 &bufSize);
379 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
380 if (buf)
382 ok(buf[0] == 0xa,
383 "Got unexpected type %d for enumerated (expected 0xa)\n",
384 buf[0]);
385 ok(buf[1] == enums[j].encoded[1],
386 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
387 ok(!memcmp(buf + 1, enums[j].encoded + 1,
388 enums[j].encoded[1] + 1),
389 "Encoded value of 0x%08x didn't match expected\n",
390 enums[j].val);
391 LocalFree(buf);
397 static void test_decodeEnumerated(DWORD dwEncoding)
399 DWORD i, j;
401 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
403 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
405 BOOL ret;
406 DWORD bufSize = sizeof(int);
407 int val;
409 ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
410 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
411 (BYTE *)&val, &bufSize);
412 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
413 ok(bufSize == sizeof(int),
414 "Got unexpected size %d for enumerated\n", bufSize);
415 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
416 val, enums[j].val);
421 struct encodedFiletime
423 SYSTEMTIME sysTime;
424 const BYTE *encodedTime;
427 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
428 const struct encodedFiletime *time)
430 FILETIME ft = { 0 };
431 BYTE *buf = NULL;
432 DWORD bufSize = 0;
433 BOOL ret;
435 ret = SystemTimeToFileTime(&time->sysTime, &ft);
436 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
437 ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
438 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
439 /* years other than 1950-2050 are not allowed for encodings other than
440 * X509_CHOICE_OF_TIME.
442 if (structType == X509_CHOICE_OF_TIME ||
443 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
445 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
446 GetLastError());
447 ok(buf != NULL, "Expected an allocated buffer\n");
448 if (buf)
450 ok(buf[0] == time->encodedTime[0],
451 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
452 buf[0]);
453 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
454 time->encodedTime[1], bufSize);
455 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
456 "Got unexpected value for time encoding\n");
457 LocalFree(buf);
460 else
461 ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
462 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
465 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
466 const struct encodedFiletime *time)
468 FILETIME ft1 = { 0 }, ft2 = { 0 };
469 DWORD size = sizeof(ft2);
470 BOOL ret;
472 ret = SystemTimeToFileTime(&time->sysTime, &ft1);
473 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
474 ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
475 time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
476 /* years other than 1950-2050 are not allowed for encodings other than
477 * X509_CHOICE_OF_TIME.
479 if (structType == X509_CHOICE_OF_TIME ||
480 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
482 ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
483 GetLastError());
484 ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
485 "Got unexpected value for time decoding\n");
487 else
488 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
489 "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
492 static const BYTE bin20[] = {
493 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
494 static const BYTE bin21[] = {
495 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
496 static const BYTE bin22[] = {
497 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
499 static const struct encodedFiletime times[] = {
500 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
501 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
502 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
505 static void test_encodeFiletime(DWORD dwEncoding)
507 DWORD i;
509 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
511 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
512 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
513 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
517 static const BYTE bin23[] = {
518 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
519 static const BYTE bin24[] = {
520 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
521 static const BYTE bin25[] = {
522 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
523 static const BYTE bin26[] = {
524 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
525 static const BYTE bin27[] = {
526 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
527 static const BYTE bin28[] = {
528 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
529 static const BYTE bin29[] = {
530 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
531 static const BYTE bin30[] = {
532 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
533 static const BYTE bin31[] = {
534 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
535 static const BYTE bin32[] = {
536 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
537 static const BYTE bin33[] = {
538 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
539 static const BYTE bin34[] = {
540 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
541 static const BYTE bin35[] = {
542 0x17,0x08, '4','5','0','6','0','6','1','6'};
543 static const BYTE bin36[] = {
544 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
545 static const BYTE bin37[] = {
546 0x18,0x04, '2','1','4','5'};
547 static const BYTE bin38[] = {
548 0x18,0x08, '2','1','4','5','0','6','0','6'};
550 static void test_decodeFiletime(DWORD dwEncoding)
552 static const struct encodedFiletime otherTimes[] = {
553 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
554 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
555 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
556 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
557 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
558 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
559 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
560 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
561 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
562 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
563 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
564 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
566 /* An oddball case that succeeds in Windows, but doesn't seem correct
567 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
569 static const unsigned char *bogusTimes[] = {
570 /* oddly, this succeeds on Windows, with year 2765
571 "\x18" "\x0f" "21r50606161000Z",
573 bin35,
574 bin36,
575 bin37,
576 bin38,
578 DWORD i, size;
579 FILETIME ft1 = { 0 }, ft2 = { 0 };
580 BOOL ret;
582 /* Check bogus length with non-NULL buffer */
583 ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
584 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
585 size = 1;
586 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
587 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
588 ok(!ret && GetLastError() == ERROR_MORE_DATA,
589 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
590 /* Normal tests */
591 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
593 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
594 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
595 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
597 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
599 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
600 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
601 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
603 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
605 size = sizeof(ft1);
606 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
607 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
608 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
609 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
613 static const char commonName[] = "Juan Lang";
614 static const char surName[] = "Lang";
616 static const BYTE emptySequence[] = { 0x30, 0 };
617 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
618 static const BYTE twoRDNs[] = {
619 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
620 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
621 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
622 static const BYTE encodedTwoRDNs[] = {
623 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
624 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
625 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
626 0x6e,0x67,0x00,
629 static const BYTE us[] = { 0x55, 0x53 };
630 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
631 0x74, 0x61 };
632 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
633 0x6f, 0x6c, 0x69, 0x73 };
634 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
635 0x76, 0x65, 0x72, 0x73 };
636 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
637 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
638 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
639 0x73, 0x74 };
640 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
641 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
643 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
644 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
646 static CHAR oid_us[] = "2.5.4.6",
647 oid_minnesota[] = "2.5.4.8",
648 oid_minneapolis[] = "2.5.4.7",
649 oid_codeweavers[] = "2.5.4.10",
650 oid_wine[] = "2.5.4.11",
651 oid_localhostAttr[] = "2.5.4.3",
652 oid_aric[] = "1.2.840.113549.1.9.1";
653 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
654 { RDNA(minnesota) },
655 { RDNA(minneapolis) },
656 { RDNA(codeweavers) },
657 { RDNA(wine) },
658 { RDNA(localhostAttr) },
659 { RDNIA5(aric) } };
660 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
661 { RDNA(localhostAttr) },
662 { RDNA(minnesota) },
663 { RDNA(minneapolis) },
664 { RDNA(codeweavers) },
665 { RDNA(wine) },
666 { RDNIA5(aric) } };
668 #undef RDNIA5
669 #undef RDNA
671 static const BYTE encodedRDNAttrs[] = {
672 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
673 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
674 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
675 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
676 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
677 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
678 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
679 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
680 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
681 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
684 static void test_encodeName(DWORD dwEncoding)
686 CERT_RDN_ATTR attrs[2];
687 CERT_RDN rdn;
688 CERT_NAME_INFO info;
689 static CHAR oid_common_name[] = szOID_COMMON_NAME,
690 oid_sur_name[] = szOID_SUR_NAME;
691 BYTE *buf = NULL;
692 DWORD size = 0;
693 BOOL ret;
695 /* Test with NULL pvStructInfo */
696 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
697 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
698 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
699 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
700 /* Test with empty CERT_NAME_INFO */
701 info.cRDN = 0;
702 info.rgRDN = NULL;
703 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
704 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
705 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
706 if (buf)
708 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
709 "Got unexpected encoding for empty name\n");
710 LocalFree(buf);
712 /* Test with bogus CERT_RDN */
713 info.cRDN = 1;
714 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
715 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
716 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
717 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
718 /* Test with empty CERT_RDN */
719 rdn.cRDNAttr = 0;
720 rdn.rgRDNAttr = NULL;
721 info.cRDN = 1;
722 info.rgRDN = &rdn;
723 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
724 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
725 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
726 if (buf)
728 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
729 "Got unexpected encoding for empty RDN array\n");
730 LocalFree(buf);
732 /* Test with bogus attr array */
733 rdn.cRDNAttr = 1;
734 rdn.rgRDNAttr = NULL;
735 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
736 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
737 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
738 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
739 /* oddly, a bogus OID is accepted by Windows XP; not testing.
740 attrs[0].pszObjId = "bogus";
741 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
742 attrs[0].Value.cbData = sizeof(commonName);
743 attrs[0].Value.pbData = (BYTE *)commonName;
744 rdn.cRDNAttr = 1;
745 rdn.rgRDNAttr = attrs;
746 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
747 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
748 ok(!ret, "Expected failure, got success\n");
750 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
751 * the encoded attributes to be swapped.
753 attrs[0].pszObjId = oid_common_name;
754 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
755 attrs[0].Value.cbData = sizeof(commonName);
756 attrs[0].Value.pbData = (BYTE *)commonName;
757 attrs[1].pszObjId = oid_sur_name;
758 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
759 attrs[1].Value.cbData = sizeof(surName);
760 attrs[1].Value.pbData = (BYTE *)surName;
761 rdn.cRDNAttr = 2;
762 rdn.rgRDNAttr = attrs;
763 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
764 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
765 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
766 if (buf)
768 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
769 "Got unexpected encoding for two RDN array\n");
770 LocalFree(buf);
772 /* A name can be "encoded" with previously encoded RDN attrs. */
773 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
774 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
775 attrs[0].Value.cbData = sizeof(twoRDNs);
776 rdn.cRDNAttr = 1;
777 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
778 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
779 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
780 if (buf)
782 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
783 ok(!memcmp(buf, encodedTwoRDNs, size),
784 "Unexpected value for re-endoded two RDN array\n");
785 LocalFree(buf);
787 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
788 rdn.cRDNAttr = 1;
789 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
790 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
791 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
792 ok(!ret && GetLastError() == E_INVALIDARG,
793 "Expected E_INVALIDARG, got %08x\n", GetLastError());
794 /* Test a more complex name */
795 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
796 rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
797 info.cRDN = 1;
798 info.rgRDN = &rdn;
799 buf = NULL;
800 size = 0;
801 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
802 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
803 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
804 if (ret)
806 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
807 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
808 LocalFree(buf);
812 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
813 static WCHAR surNameW[] = { 'L','a','n','g',0 };
815 static const BYTE twoRDNsNoNull[] = {
816 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
817 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
818 0x20,0x4c,0x61,0x6e,0x67 };
819 static const BYTE anyType[] = {
820 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
821 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
822 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
823 0x61,0x4c,0x67,0x6e };
825 static void test_encodeUnicodeName(DWORD dwEncoding)
827 CERT_RDN_ATTR attrs[2];
828 CERT_RDN rdn;
829 CERT_NAME_INFO info;
830 static CHAR oid_common_name[] = szOID_COMMON_NAME,
831 oid_sur_name[] = szOID_SUR_NAME;
832 BYTE *buf = NULL;
833 DWORD size = 0;
834 BOOL ret;
836 /* Test with NULL pvStructInfo */
837 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
838 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
839 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
840 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
841 /* Test with empty CERT_NAME_INFO */
842 info.cRDN = 0;
843 info.rgRDN = NULL;
844 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
845 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
846 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
847 if (buf)
849 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
850 "Got unexpected encoding for empty name\n");
851 LocalFree(buf);
853 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
854 * encoding (the NULL).
856 attrs[0].pszObjId = oid_common_name;
857 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
858 attrs[0].Value.cbData = sizeof(commonNameW);
859 attrs[0].Value.pbData = (BYTE *)commonNameW;
860 rdn.cRDNAttr = 1;
861 rdn.rgRDNAttr = attrs;
862 info.cRDN = 1;
863 info.rgRDN = &rdn;
864 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
865 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
866 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
867 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
868 ok(size == 9, "Unexpected error index %08x\n", size);
869 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding
870 * forces the order of the encoded attributes to be swapped.
872 attrs[0].pszObjId = oid_common_name;
873 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
874 attrs[0].Value.cbData = 0;
875 attrs[0].Value.pbData = (BYTE *)commonNameW;
876 attrs[1].pszObjId = oid_sur_name;
877 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
878 attrs[1].Value.cbData = 0;
879 attrs[1].Value.pbData = (BYTE *)surNameW;
880 rdn.cRDNAttr = 2;
881 rdn.rgRDNAttr = attrs;
882 info.cRDN = 1;
883 info.rgRDN = &rdn;
884 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
885 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
886 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
887 if (buf)
889 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
890 "Got unexpected encoding for two RDN array\n");
891 LocalFree(buf);
893 /* A name can be "encoded" with previously encoded RDN attrs. */
894 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
895 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
896 attrs[0].Value.cbData = sizeof(twoRDNs);
897 rdn.cRDNAttr = 1;
898 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
899 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
900 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
901 if (buf)
903 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
904 ok(!memcmp(buf, encodedTwoRDNs, size),
905 "Unexpected value for re-endoded two RDN array\n");
906 LocalFree(buf);
908 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
909 rdn.cRDNAttr = 1;
910 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
911 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
912 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
913 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
914 if (buf)
916 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
917 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
918 LocalFree(buf);
922 static void compareNameValues(const CERT_NAME_VALUE *expected,
923 const CERT_NAME_VALUE *got)
925 ok(got->dwValueType == expected->dwValueType,
926 "Expected string type %d, got %d\n", expected->dwValueType,
927 got->dwValueType);
928 ok(got->Value.cbData == expected->Value.cbData,
929 "String type %d: unexpected data size, got %d, expected %d\n",
930 expected->dwValueType, got->Value.cbData, expected->Value.cbData);
931 if (got->Value.cbData && got->Value.pbData)
932 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
933 min(got->Value.cbData, expected->Value.cbData)),
934 "String type %d: unexpected value\n", expected->dwValueType);
937 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
938 const CERT_RDN_ATTR *got)
940 if (expected->pszObjId && strlen(expected->pszObjId))
942 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
943 expected->pszObjId);
944 if (got->pszObjId)
946 ok(!strcmp(got->pszObjId, expected->pszObjId),
947 "Got unexpected OID %s, expected %s\n", got->pszObjId,
948 expected->pszObjId);
951 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
952 (const CERT_NAME_VALUE *)&got->dwValueType);
955 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
957 ok(got->cRDNAttr == expected->cRDNAttr,
958 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
959 if (got->cRDNAttr)
961 DWORD i;
963 for (i = 0; i < got->cRDNAttr; i++)
964 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
968 static void compareNames(const CERT_NAME_INFO *expected,
969 const CERT_NAME_INFO *got)
971 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
972 expected->cRDN, got->cRDN);
973 if (got->cRDN)
975 DWORD i;
977 for (i = 0; i < got->cRDN; i++)
978 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
982 static const BYTE twoRDNsExtraBytes[] = {
983 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
984 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
985 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
987 static void test_decodeName(DWORD dwEncoding)
989 BYTE *buf = NULL;
990 DWORD bufSize = 0;
991 BOOL ret;
992 CERT_RDN rdn;
993 CERT_NAME_INFO info = { 1, &rdn };
995 /* test empty name */
996 bufSize = 0;
997 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
998 emptySequence[1] + 2,
999 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1000 (BYTE *)&buf, &bufSize);
1001 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1002 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
1003 * decoder works the same way, so only test the count.
1005 if (buf)
1007 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1008 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1009 "Expected 0 RDNs in empty info, got %d\n",
1010 ((CERT_NAME_INFO *)buf)->cRDN);
1011 LocalFree(buf);
1013 /* test empty RDN */
1014 bufSize = 0;
1015 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1016 emptyRDNs[1] + 2,
1017 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1018 (BYTE *)&buf, &bufSize);
1019 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1020 if (buf)
1022 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1024 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1025 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1026 "Got unexpected value for empty RDN\n");
1027 LocalFree(buf);
1029 /* test two RDN attrs */
1030 bufSize = 0;
1031 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1032 twoRDNs[1] + 2,
1033 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1034 (BYTE *)&buf, &bufSize);
1035 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1036 if (buf)
1038 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1039 oid_common_name[] = szOID_COMMON_NAME;
1041 CERT_RDN_ATTR attrs[] = {
1042 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1043 (BYTE *)surName } },
1044 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1045 (BYTE *)commonName } },
1048 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1049 rdn.rgRDNAttr = attrs;
1050 compareNames(&info, (CERT_NAME_INFO *)buf);
1051 LocalFree(buf);
1053 /* test that two RDN attrs with extra bytes succeeds */
1054 bufSize = 0;
1055 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1056 sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1057 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1058 /* And, a slightly more complicated name */
1059 buf = NULL;
1060 bufSize = 0;
1061 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1062 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1063 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1064 if (ret)
1066 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1067 rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1068 compareNames(&info, (CERT_NAME_INFO *)buf);
1069 LocalFree(buf);
1073 static void test_decodeUnicodeName(DWORD dwEncoding)
1075 BYTE *buf = NULL;
1076 DWORD bufSize = 0;
1077 BOOL ret;
1078 CERT_RDN rdn;
1079 CERT_NAME_INFO info = { 1, &rdn };
1081 /* test empty name */
1082 bufSize = 0;
1083 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1084 emptySequence[1] + 2,
1085 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1086 (BYTE *)&buf, &bufSize);
1087 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1088 if (buf)
1090 ok(bufSize == sizeof(CERT_NAME_INFO),
1091 "Got wrong bufSize %d\n", bufSize);
1092 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1093 "Expected 0 RDNs in empty info, got %d\n",
1094 ((CERT_NAME_INFO *)buf)->cRDN);
1095 LocalFree(buf);
1097 /* test empty RDN */
1098 bufSize = 0;
1099 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1100 emptyRDNs[1] + 2,
1101 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1102 (BYTE *)&buf, &bufSize);
1103 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1104 if (buf)
1106 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1108 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1109 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1110 "Got unexpected value for empty RDN\n");
1111 LocalFree(buf);
1113 /* test two RDN attrs */
1114 bufSize = 0;
1115 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1116 sizeof(twoRDNsNoNull),
1117 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1118 (BYTE *)&buf, &bufSize);
1119 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1120 if (buf)
1122 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1123 oid_common_name[] = szOID_COMMON_NAME;
1125 CERT_RDN_ATTR attrs[] = {
1126 { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1127 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1128 { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1129 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1132 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1133 rdn.rgRDNAttr = attrs;
1134 compareNames(&info, (CERT_NAME_INFO *)buf);
1135 LocalFree(buf);
1139 struct EncodedNameValue
1141 CERT_NAME_VALUE value;
1142 const BYTE *encoded;
1143 DWORD encodedSize;
1146 static const char bogusIA5[] = "\x80";
1147 static const char bogusPrintable[] = "~";
1148 static const char bogusNumeric[] = "A";
1149 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1150 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1151 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1152 static BYTE octetCommonNameValue[] = {
1153 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1154 static BYTE numericCommonNameValue[] = {
1155 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1156 static BYTE printableCommonNameValue[] = {
1157 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1158 static BYTE t61CommonNameValue[] = {
1159 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1160 static BYTE videotexCommonNameValue[] = {
1161 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1162 static BYTE ia5CommonNameValue[] = {
1163 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1164 static BYTE graphicCommonNameValue[] = {
1165 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1166 static BYTE visibleCommonNameValue[] = {
1167 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1168 static BYTE generalCommonNameValue[] = {
1169 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1170 static BYTE bmpCommonNameValue[] = {
1171 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1172 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1173 static BYTE utf8CommonNameValue[] = {
1174 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1176 static struct EncodedNameValue nameValues[] = {
1177 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1178 octetCommonNameValue, sizeof(octetCommonNameValue) },
1179 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1180 numericCommonNameValue, sizeof(numericCommonNameValue) },
1181 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1182 printableCommonNameValue, sizeof(printableCommonNameValue) },
1183 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1184 t61CommonNameValue, sizeof(t61CommonNameValue) },
1185 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1186 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1187 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1188 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1189 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1190 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1191 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1192 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1193 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1194 generalCommonNameValue, sizeof(generalCommonNameValue) },
1195 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1196 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1197 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1198 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1199 /* The following tests succeed under Windows, but really should fail,
1200 * they contain characters that are illegal for the encoding. I'm
1201 * including them to justify my lazy encoding.
1203 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1204 sizeof(bin42) },
1205 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1206 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1207 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1208 bin44, sizeof(bin44) },
1211 static void test_encodeNameValue(DWORD dwEncoding)
1213 BYTE *buf = NULL;
1214 DWORD size = 0, i;
1215 BOOL ret;
1216 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1218 value.dwValueType = 14;
1219 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1220 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1221 ok(!ret && GetLastError() == CRYPT_E_ASN1_CHOICE,
1222 "Expected CRYPT_E_ASN1_CHOICE, got %08x\n", GetLastError());
1223 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1224 value.Value.pbData = printableCommonNameValue;
1225 value.Value.cbData = sizeof(printableCommonNameValue);
1226 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1227 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1228 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1229 if (buf)
1231 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1232 size);
1233 ok(!memcmp(buf, printableCommonNameValue, size),
1234 "Unexpected encoding\n");
1235 LocalFree(buf);
1237 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1239 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1240 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1241 &size);
1242 ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1243 nameValues[i].value.dwValueType, GetLastError());
1244 if (buf)
1246 ok(size == nameValues[i].encodedSize,
1247 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1248 ok(!memcmp(buf, nameValues[i].encoded, size),
1249 "Got unexpected encoding\n");
1250 LocalFree(buf);
1255 static void test_decodeNameValue(DWORD dwEncoding)
1257 int i;
1258 BYTE *buf = NULL;
1259 DWORD bufSize = 0;
1260 BOOL ret;
1262 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1264 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1265 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1266 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1267 (BYTE *)&buf, &bufSize);
1268 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1269 nameValues[i].value.dwValueType, GetLastError());
1270 if (buf)
1272 compareNameValues(&nameValues[i].value,
1273 (const CERT_NAME_VALUE *)buf);
1274 LocalFree(buf);
1279 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1280 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1281 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1282 'h','q','.','o','r','g',0 };
1283 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1284 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1285 0x6f, 0x72, 0x67 };
1286 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1287 0x575b, 0 };
1288 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1289 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1290 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1291 static const BYTE localhost[] = { 127, 0, 0, 1 };
1292 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1293 0x01 };
1295 static void test_encodeAltName(DWORD dwEncoding)
1297 CERT_ALT_NAME_INFO info = { 0 };
1298 CERT_ALT_NAME_ENTRY entry = { 0 };
1299 BYTE *buf = NULL;
1300 DWORD size = 0;
1301 BOOL ret;
1303 /* Test with empty info */
1304 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1305 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1306 if (buf)
1308 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1309 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1310 LocalFree(buf);
1312 /* Test with an empty entry */
1313 info.cAltEntry = 1;
1314 info.rgAltEntry = &entry;
1315 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1316 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1317 ok(!ret && GetLastError() == E_INVALIDARG,
1318 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1319 /* Test with an empty pointer */
1320 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1321 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1322 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1323 if (buf)
1325 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1326 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1327 LocalFree(buf);
1329 /* Test with a real URL */
1330 U(entry).pwszURL = (LPWSTR)url;
1331 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1332 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1333 if (buf)
1335 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1336 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1337 LocalFree(buf);
1339 /* Now with the URL containing an invalid IA5 char */
1340 U(entry).pwszURL = (LPWSTR)nihongoURL;
1341 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1342 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1343 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1344 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1345 /* The first invalid character is at index 7 */
1346 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1347 "Expected invalid char at index 7, got %d\n",
1348 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1349 /* Now with the URL missing a scheme */
1350 U(entry).pwszURL = (LPWSTR)dnsName;
1351 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1352 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1353 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1354 if (buf)
1356 /* This succeeds, but it shouldn't, so don't worry about conforming */
1357 LocalFree(buf);
1359 /* Now with a DNS name */
1360 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1361 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1362 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1363 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1364 if (buf)
1366 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1367 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1368 LocalFree(buf);
1370 /* Test with an IP address */
1371 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1372 U(entry).IPAddress.cbData = sizeof(localhost);
1373 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1374 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1375 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1376 if (buf)
1378 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1379 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1380 LocalFree(buf);
1384 static void test_decodeAltName(DWORD dwEncoding)
1386 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1387 0x00, 0x00, 0x01 };
1388 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1389 0x01 };
1390 BOOL ret;
1391 BYTE *buf = NULL;
1392 DWORD bufSize = 0;
1393 CERT_ALT_NAME_INFO *info;
1395 /* Test some bogus ones first */
1396 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1397 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1398 NULL, (BYTE *)&buf, &bufSize);
1399 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1400 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1401 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1402 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1403 &bufSize);
1404 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1405 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1406 /* Now expected cases */
1407 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1408 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1409 &bufSize);
1410 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1411 if (buf)
1413 info = (CERT_ALT_NAME_INFO *)buf;
1415 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1416 info->cAltEntry);
1417 LocalFree(buf);
1419 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1420 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1421 &bufSize);
1422 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1423 if (buf)
1425 info = (CERT_ALT_NAME_INFO *)buf;
1427 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1428 info->cAltEntry);
1429 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1430 "Expected CERT_ALT_NAME_URL, got %d\n",
1431 info->rgAltEntry[0].dwAltNameChoice);
1432 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1433 "Expected empty URL\n");
1434 LocalFree(buf);
1436 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1437 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1438 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1439 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1440 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1441 &bufSize);
1442 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1443 if (buf)
1445 info = (CERT_ALT_NAME_INFO *)buf;
1447 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1448 info->cAltEntry);
1449 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1450 "Expected CERT_ALT_NAME_URL, got %d\n",
1451 info->rgAltEntry[0].dwAltNameChoice);
1452 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1453 LocalFree(buf);
1455 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1456 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1457 &bufSize);
1458 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1459 if (buf)
1461 info = (CERT_ALT_NAME_INFO *)buf;
1463 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1464 info->cAltEntry);
1465 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1466 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1467 info->rgAltEntry[0].dwAltNameChoice);
1468 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1469 "Unexpected DNS name\n");
1470 LocalFree(buf);
1472 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1473 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1474 &bufSize);
1475 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1476 if (buf)
1478 info = (CERT_ALT_NAME_INFO *)buf;
1480 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1481 info->cAltEntry);
1482 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1483 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1484 info->rgAltEntry[0].dwAltNameChoice);
1485 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1486 "Unexpected IP address length %d\n",
1487 U(info->rgAltEntry[0]).IPAddress.cbData);
1488 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1489 sizeof(localhost)), "Unexpected IP address value\n");
1490 LocalFree(buf);
1494 struct UnicodeExpectedError
1496 DWORD valueType;
1497 LPCWSTR str;
1498 DWORD errorIndex;
1499 DWORD error;
1502 static const WCHAR oneW[] = { '1',0 };
1503 static const WCHAR aW[] = { 'a',0 };
1504 static const WCHAR quoteW[] = { '"', 0 };
1506 static struct UnicodeExpectedError unicodeErrors[] = {
1507 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1508 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1509 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1510 { 14, oneW, 0, CRYPT_E_ASN1_CHOICE },
1511 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1512 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1513 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1516 struct UnicodeExpectedResult
1518 DWORD valueType;
1519 LPCWSTR str;
1520 CRYPT_DATA_BLOB encoded;
1523 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1524 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1525 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1526 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1527 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1528 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1529 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1530 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1531 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1532 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1533 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1534 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1535 0x5b };
1536 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1537 0x6f,0x5b };
1538 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1539 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1540 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1541 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1543 static struct UnicodeExpectedResult unicodeResults[] = {
1544 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1545 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1546 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1547 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1548 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1549 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1550 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1551 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1552 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1553 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1554 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1555 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1556 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1559 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1560 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1561 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1564 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1566 BYTE *buf = NULL;
1567 DWORD size = 0, i;
1568 BOOL ret;
1569 CERT_NAME_VALUE value;
1571 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1572 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1573 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1574 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1575 /* Have to have a string of some sort */
1576 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1577 value.Value.pbData = NULL;
1578 value.Value.cbData = 0;
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 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1584 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1585 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1586 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1587 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1588 value.dwValueType = CERT_RDN_ANY_TYPE;
1589 value.Value.pbData = (LPBYTE)oneW;
1590 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1591 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1592 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1593 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1594 value.Value.cbData = sizeof(oneW);
1595 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1596 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1597 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1598 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1599 /* An encoded string with specified length isn't good enough either */
1600 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1601 value.Value.pbData = oneUniversal;
1602 value.Value.cbData = sizeof(oneUniversal);
1603 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1604 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1605 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1606 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1607 /* More failure checking */
1608 value.Value.cbData = 0;
1609 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1611 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1612 value.dwValueType = unicodeErrors[i].valueType;
1613 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1614 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1615 ok(!ret && GetLastError() == unicodeErrors[i].error,
1616 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1617 unicodeErrors[i].error, GetLastError());
1618 ok(size == unicodeErrors[i].errorIndex,
1619 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1620 size);
1622 /* cbData can be zero if the string is NULL-terminated */
1623 value.Value.cbData = 0;
1624 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1626 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1627 value.dwValueType = unicodeResults[i].valueType;
1628 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1629 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1630 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1631 if (buf)
1633 ok(size == unicodeResults[i].encoded.cbData,
1634 "Value type %d: expected size %d, got %d\n",
1635 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1636 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1637 "Value type %d: unexpected value\n", value.dwValueType);
1638 LocalFree(buf);
1641 /* These "encode," but they do so by truncating each unicode character
1642 * rather than properly encoding it. Kept separate from the proper results,
1643 * because the encoded forms won't decode to their original strings.
1645 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1647 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1648 value.dwValueType = unicodeWeirdness[i].valueType;
1649 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1650 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1651 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1652 if (buf)
1654 ok(size == unicodeWeirdness[i].encoded.cbData,
1655 "Value type %d: expected size %d, got %d\n",
1656 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1657 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1658 "Value type %d: unexpected value\n", value.dwValueType);
1659 LocalFree(buf);
1664 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1666 if (n <= 0) return 0;
1667 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1668 return *str1 - *str2;
1671 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1673 DWORD i;
1675 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1677 BYTE *buf = NULL;
1678 BOOL ret;
1679 DWORD size = 0;
1681 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1682 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1683 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1684 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1685 if (ret && buf)
1687 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1689 ok(value->dwValueType == unicodeResults[i].valueType,
1690 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1691 value->dwValueType);
1692 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1693 value->Value.cbData / sizeof(WCHAR)),
1694 "Unexpected decoded value for index %d (value type %d)\n", i,
1695 unicodeResults[i].valueType);
1696 LocalFree(buf);
1701 struct encodedOctets
1703 const BYTE *val;
1704 const BYTE *encoded;
1707 static const unsigned char bin46[] = { 'h','i',0 };
1708 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1709 static const unsigned char bin48[] = {
1710 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1711 static const unsigned char bin49[] = {
1712 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1713 static const unsigned char bin50[] = { 0 };
1714 static const unsigned char bin51[] = { 0x04,0x00,0 };
1716 static const struct encodedOctets octets[] = {
1717 { bin46, bin47 },
1718 { bin48, bin49 },
1719 { bin50, bin51 },
1722 static void test_encodeOctets(DWORD dwEncoding)
1724 CRYPT_DATA_BLOB blob;
1725 DWORD i;
1727 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1729 BYTE *buf = NULL;
1730 BOOL ret;
1731 DWORD bufSize = 0;
1733 blob.cbData = strlen((const char*)octets[i].val);
1734 blob.pbData = (BYTE*)octets[i].val;
1735 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1736 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1737 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1738 if (buf)
1740 ok(buf[0] == 4,
1741 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1742 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1743 buf[1], octets[i].encoded[1]);
1744 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1745 octets[i].encoded[1] + 1), "Got unexpected value\n");
1746 LocalFree(buf);
1751 static void test_decodeOctets(DWORD dwEncoding)
1753 DWORD i;
1755 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1757 BYTE *buf = NULL;
1758 BOOL ret;
1759 DWORD bufSize = 0;
1761 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1762 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1763 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1764 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1765 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1766 "Expected size >= %d, got %d\n",
1767 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1768 ok(buf != NULL, "Expected allocated buffer\n");
1769 if (buf)
1771 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1773 if (blob->cbData)
1774 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1775 "Unexpected value\n");
1776 LocalFree(buf);
1781 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1783 struct encodedBits
1785 DWORD cUnusedBits;
1786 const BYTE *encoded;
1787 DWORD cbDecoded;
1788 const BYTE *decoded;
1791 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1792 static const unsigned char bin53[] = { 0xff,0xff };
1793 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1794 static const unsigned char bin55[] = { 0xff,0xfe };
1795 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1796 static const unsigned char bin57[] = { 0xfe };
1797 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1799 static const struct encodedBits bits[] = {
1800 /* normal test cases */
1801 { 0, bin52, 2, bin53 },
1802 { 1, bin54, 2, bin55 },
1803 /* strange test case, showing cUnusedBits >= 8 is allowed */
1804 { 9, bin56, 1, bin57 },
1805 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1806 { 17, bin58, 0, NULL },
1809 static void test_encodeBits(DWORD dwEncoding)
1811 DWORD i;
1813 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1815 CRYPT_BIT_BLOB blob;
1816 BOOL ret;
1817 BYTE *buf = NULL;
1818 DWORD bufSize = 0;
1820 blob.cbData = sizeof(bytesToEncode);
1821 blob.pbData = (BYTE *)bytesToEncode;
1822 blob.cUnusedBits = bits[i].cUnusedBits;
1823 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1824 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1825 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1826 if (buf)
1828 ok(bufSize == bits[i].encoded[1] + 2,
1829 "Got unexpected size %d, expected %d\n", bufSize,
1830 bits[i].encoded[1] + 2);
1831 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1832 "Unexpected value\n");
1833 LocalFree(buf);
1838 static void test_decodeBits(DWORD dwEncoding)
1840 static const BYTE ber[] = "\x03\x02\x01\xff";
1841 static const BYTE berDecoded = 0xfe;
1842 DWORD i;
1843 BOOL ret;
1844 BYTE *buf = NULL;
1845 DWORD bufSize = 0;
1847 /* normal cases */
1848 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1850 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1851 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1852 &bufSize);
1853 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1854 if (buf)
1856 CRYPT_BIT_BLOB *blob;
1858 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1859 "Got unexpected size %d\n", bufSize);
1860 blob = (CRYPT_BIT_BLOB *)buf;
1861 ok(blob->cbData == bits[i].cbDecoded,
1862 "Got unexpected length %d, expected %d\n", blob->cbData,
1863 bits[i].cbDecoded);
1864 if (blob->cbData && bits[i].cbDecoded)
1865 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1866 "Unexpected value\n");
1867 LocalFree(buf);
1870 /* special case: check that something that's valid in BER but not in DER
1871 * decodes successfully
1873 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1874 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1875 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1876 if (buf)
1878 CRYPT_BIT_BLOB *blob;
1880 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1881 "Got unexpected size %d\n", bufSize);
1882 blob = (CRYPT_BIT_BLOB *)buf;
1883 ok(blob->cbData == sizeof(berDecoded),
1884 "Got unexpected length %d\n", blob->cbData);
1885 if (blob->cbData)
1886 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1887 LocalFree(buf);
1891 struct Constraints2
1893 CERT_BASIC_CONSTRAINTS2_INFO info;
1894 const BYTE *encoded;
1897 static const unsigned char bin59[] = { 0x30,0x00 };
1898 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1899 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1900 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1901 static const struct Constraints2 constraints2[] = {
1902 /* empty constraints */
1903 { { FALSE, FALSE, 0}, bin59 },
1904 /* can be a CA */
1905 { { TRUE, FALSE, 0}, bin60 },
1906 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1907 * but that's not the case
1909 { { FALSE, TRUE, 0}, bin61 },
1910 /* can be a CA and has path length constraints set */
1911 { { TRUE, TRUE, 1}, bin62 },
1914 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1915 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1916 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1917 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1918 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1919 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1920 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1921 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1922 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1923 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1925 static void test_encodeBasicConstraints(DWORD dwEncoding)
1927 DWORD i, bufSize = 0;
1928 CERT_BASIC_CONSTRAINTS_INFO info;
1929 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1930 (LPBYTE)encodedDomainName };
1931 BOOL ret;
1932 BYTE *buf = NULL;
1934 /* First test with the simpler info2 */
1935 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1937 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1938 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1939 &bufSize);
1940 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1941 if (buf)
1943 ok(bufSize == constraints2[i].encoded[1] + 2,
1944 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
1945 bufSize);
1946 ok(!memcmp(buf, constraints2[i].encoded,
1947 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1948 LocalFree(buf);
1951 /* Now test with more complex basic constraints */
1952 info.SubjectType.cbData = 0;
1953 info.fPathLenConstraint = FALSE;
1954 info.cSubtreesConstraint = 0;
1955 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1956 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1957 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1958 if (buf)
1960 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
1961 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1962 "Unexpected value\n");
1963 LocalFree(buf);
1965 /* None of the certs I examined had any subtree constraint, but I test one
1966 * anyway just in case.
1968 info.cSubtreesConstraint = 1;
1969 info.rgSubtreesConstraint = &nameBlob;
1970 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1971 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1972 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1973 if (buf)
1975 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
1976 ok(!memcmp(buf, constraintWithDomainName,
1977 sizeof(constraintWithDomainName)), "Unexpected value\n");
1978 LocalFree(buf);
1980 /* FIXME: test encoding with subject type. */
1983 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1984 static const unsigned char encodedCommonName[] = {
1985 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1987 static void test_decodeBasicConstraints(DWORD dwEncoding)
1989 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1990 0xff };
1991 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1992 DWORD i;
1993 BOOL ret;
1994 BYTE *buf = NULL;
1995 DWORD bufSize = 0;
1997 /* First test with simpler info2 */
1998 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2000 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2001 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2002 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2003 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2004 GetLastError());
2005 if (buf)
2007 CERT_BASIC_CONSTRAINTS2_INFO *info =
2008 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2010 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2011 "Unexpected value for item %d\n", i);
2012 LocalFree(buf);
2015 /* Check with the order of encoded elements inverted */
2016 buf = (PBYTE)1;
2017 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2018 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2019 &bufSize);
2020 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2021 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2022 ok(!buf, "Expected buf to be set to NULL\n");
2023 /* Check with a non-DER bool */
2024 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2025 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2026 (BYTE *)&buf, &bufSize);
2027 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2028 if (buf)
2030 CERT_BASIC_CONSTRAINTS2_INFO *info =
2031 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2033 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2034 LocalFree(buf);
2036 /* Check with a non-basic constraints value */
2037 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2038 (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2039 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2040 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2041 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2042 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2043 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2044 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2045 (BYTE *)&buf, &bufSize);
2046 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2047 if (buf)
2049 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2051 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2052 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2053 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2054 LocalFree(buf);
2056 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2057 constraintWithDomainName, sizeof(constraintWithDomainName),
2058 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2059 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2060 if (buf)
2062 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2064 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2065 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2066 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2067 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2069 ok(info->rgSubtreesConstraint[0].cbData ==
2070 sizeof(encodedDomainName), "Wrong size %d\n",
2071 info->rgSubtreesConstraint[0].cbData);
2072 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2073 sizeof(encodedDomainName)), "Unexpected value\n");
2075 LocalFree(buf);
2079 /* These are terrible public keys of course, I'm just testing encoding */
2080 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2081 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2082 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2083 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2084 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2085 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2086 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2087 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2089 struct EncodedRSAPubKey
2091 const BYTE *modulus;
2092 size_t modulusLen;
2093 const BYTE *encoded;
2094 size_t decodedModulusLen;
2097 struct EncodedRSAPubKey rsaPubKeys[] = {
2098 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2099 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2100 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2101 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2104 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2106 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2107 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2108 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2109 BOOL ret;
2110 BYTE *buf = NULL;
2111 DWORD bufSize = 0, i;
2113 /* Try with a bogus blob type */
2114 hdr->bType = 2;
2115 hdr->bVersion = CUR_BLOB_VERSION;
2116 hdr->reserved = 0;
2117 hdr->aiKeyAlg = CALG_RSA_KEYX;
2118 rsaPubKey->magic = 0x31415352;
2119 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2120 rsaPubKey->pubexp = 65537;
2121 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2122 sizeof(modulus1));
2124 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2125 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2126 &bufSize);
2127 ok(!ret && GetLastError() == E_INVALIDARG,
2128 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2129 /* Now with a bogus reserved field */
2130 hdr->bType = PUBLICKEYBLOB;
2131 hdr->reserved = 1;
2132 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2133 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2134 &bufSize);
2135 if (buf)
2137 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2138 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2139 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2140 LocalFree(buf);
2142 /* Now with a bogus blob version */
2143 hdr->reserved = 0;
2144 hdr->bVersion = 0;
2145 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2146 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2147 &bufSize);
2148 if (buf)
2150 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2151 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2152 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2153 LocalFree(buf);
2155 /* And with a bogus alg ID */
2156 hdr->bVersion = CUR_BLOB_VERSION;
2157 hdr->aiKeyAlg = CALG_DES;
2158 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2159 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2160 &bufSize);
2161 if (buf)
2163 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2164 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2165 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2166 LocalFree(buf);
2168 /* Check a couple of RSA-related OIDs */
2169 hdr->aiKeyAlg = CALG_RSA_KEYX;
2170 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2171 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2172 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2173 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2174 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2175 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2176 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2177 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2178 /* Finally, all valid */
2179 hdr->aiKeyAlg = CALG_RSA_KEYX;
2180 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2182 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2183 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2184 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2185 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2186 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2187 if (buf)
2189 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2190 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2191 bufSize);
2192 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2193 "Unexpected value\n");
2194 LocalFree(buf);
2199 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2201 DWORD i;
2202 LPBYTE buf = NULL;
2203 DWORD bufSize = 0;
2204 BOOL ret;
2206 /* Try with a bad length */
2207 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2208 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2209 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2210 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2211 "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2212 /* Try with a couple of RSA-related OIDs */
2213 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2214 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2215 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2216 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2217 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2218 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2219 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2220 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2221 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2222 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2223 /* Now try success cases */
2224 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2226 bufSize = 0;
2227 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2228 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2229 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2230 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2231 if (buf)
2233 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2234 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2236 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2237 rsaPubKeys[i].decodedModulusLen,
2238 "Wrong size %d\n", bufSize);
2239 ok(hdr->bType == PUBLICKEYBLOB,
2240 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2241 hdr->bType);
2242 ok(hdr->bVersion == CUR_BLOB_VERSION,
2243 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2244 CUR_BLOB_VERSION, hdr->bVersion);
2245 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2246 hdr->reserved);
2247 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2248 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2249 ok(rsaPubKey->magic == 0x31415352,
2250 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2251 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2252 "Wrong bit len %d\n", rsaPubKey->bitlen);
2253 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2254 rsaPubKey->pubexp);
2255 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2256 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2257 "Unexpected modulus\n");
2258 LocalFree(buf);
2263 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2264 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2265 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2267 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2268 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2269 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2270 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2272 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2274 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2275 CRYPT_SEQUENCE_OF_ANY seq;
2276 DWORD i;
2277 BOOL ret;
2278 BYTE *buf = NULL;
2279 DWORD bufSize = 0;
2281 /* Encode a homogenous sequence */
2282 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2284 blobs[i].cbData = ints[i].encoded[1] + 2;
2285 blobs[i].pbData = (BYTE *)ints[i].encoded;
2287 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2288 seq.rgValue = blobs;
2290 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2291 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2292 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2293 if (buf)
2295 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2296 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2297 LocalFree(buf);
2299 /* Change the type of the first element in the sequence, and give it
2300 * another go
2302 blobs[0].cbData = times[0].encodedTime[1] + 2;
2303 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2304 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2305 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2306 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2307 if (buf)
2309 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2310 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2311 "Unexpected value\n");
2312 LocalFree(buf);
2316 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2318 BOOL ret;
2319 BYTE *buf = NULL;
2320 DWORD bufSize = 0;
2322 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2323 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2324 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2325 if (buf)
2327 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2328 DWORD i;
2330 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2331 "Wrong elements %d\n", seq->cValue);
2332 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2334 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2335 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2336 seq->rgValue[i].cbData);
2337 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2338 ints[i].encoded[1] + 2), "Unexpected value\n");
2340 LocalFree(buf);
2342 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2343 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2344 &bufSize);
2345 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2346 if (buf)
2348 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2350 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2351 "Wrong elements %d\n", seq->cValue);
2352 /* Just check the first element since it's all that changed */
2353 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2354 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2355 seq->rgValue[0].cbData);
2356 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2357 times[0].encodedTime[1] + 2), "Unexpected value\n");
2358 LocalFree(buf);
2362 struct encodedExtensions
2364 CERT_EXTENSIONS exts;
2365 const BYTE *encoded;
2368 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2369 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2370 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2371 static CERT_EXTENSION criticalExt =
2372 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2373 static CERT_EXTENSION nonCriticalExt =
2374 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2376 static const BYTE ext0[] = { 0x30,0x00 };
2377 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2378 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2379 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2380 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2382 static const struct encodedExtensions exts[] = {
2383 { { 0, NULL }, ext0 },
2384 { { 1, &criticalExt }, ext1 },
2385 { { 1, &nonCriticalExt }, ext2 },
2388 static void test_encodeExtensions(DWORD dwEncoding)
2390 DWORD i;
2392 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2394 BOOL ret;
2395 BYTE *buf = NULL;
2396 DWORD bufSize = 0;
2398 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2399 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2400 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2401 if (buf)
2403 ok(bufSize == exts[i].encoded[1] + 2,
2404 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2405 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2406 "Unexpected value\n");
2407 LocalFree(buf);
2412 static void test_decodeExtensions(DWORD dwEncoding)
2414 DWORD i;
2416 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2418 BOOL ret;
2419 BYTE *buf = NULL;
2420 DWORD bufSize = 0;
2422 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2423 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2424 NULL, (BYTE *)&buf, &bufSize);
2425 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2426 if (buf)
2428 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2429 DWORD j;
2431 ok(ext->cExtension == exts[i].exts.cExtension,
2432 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2433 ext->cExtension);
2434 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2436 ok(!strcmp(ext->rgExtension[j].pszObjId,
2437 exts[i].exts.rgExtension[j].pszObjId),
2438 "Expected OID %s, got %s\n",
2439 exts[i].exts.rgExtension[j].pszObjId,
2440 ext->rgExtension[j].pszObjId);
2441 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2442 exts[i].exts.rgExtension[j].Value.pbData,
2443 exts[i].exts.rgExtension[j].Value.cbData),
2444 "Unexpected value\n");
2446 LocalFree(buf);
2451 /* MS encodes public key info with a NULL if the algorithm identifier's
2452 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2453 * it encodes them by omitting the algorithm parameters. This latter approach
2454 * seems more correct, so accept either form.
2456 struct encodedPublicKey
2458 CERT_PUBLIC_KEY_INFO info;
2459 const BYTE *encoded;
2460 const BYTE *encodedNoNull;
2461 CERT_PUBLIC_KEY_INFO decoded;
2464 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2465 0xe, 0xf };
2466 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2468 static const unsigned char bin64[] = {
2469 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2470 static const unsigned char bin65[] = {
2471 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2472 static const unsigned char bin66[] = {
2473 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2474 static const unsigned char bin67[] = {
2475 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2476 static const unsigned char bin68[] = {
2477 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2478 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2479 static const unsigned char bin69[] = {
2480 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2481 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2482 static const unsigned char bin70[] = {
2483 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2484 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2485 0x0f};
2486 static const unsigned char bin71[] = {
2487 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2488 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2489 0x0f};
2490 static unsigned char bin72[] = { 0x05,0x00};
2492 static CHAR oid_bogus[] = "1.2.3",
2493 oid_rsa[] = szOID_RSA;
2495 static const struct encodedPublicKey pubKeys[] = {
2496 /* with a bogus OID */
2497 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2498 bin64, bin65,
2499 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2500 /* some normal keys */
2501 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2502 bin66, bin67,
2503 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2504 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2505 bin68, bin69,
2506 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2507 /* with add'l parameters--note they must be DER-encoded */
2508 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2509 (BYTE *)aKey, 0 } },
2510 bin70, bin71,
2511 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2512 (BYTE *)aKey, 0 } } },
2515 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2517 DWORD i;
2519 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2521 BOOL ret;
2522 BYTE *buf = NULL;
2523 DWORD bufSize = 0;
2525 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2526 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2527 &bufSize);
2528 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2529 if (buf)
2531 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2532 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2533 "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2534 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2535 if (bufSize == pubKeys[i].encoded[1] + 2)
2536 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2537 "Unexpected value\n");
2538 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2539 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2540 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2541 LocalFree(buf);
2546 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2547 const CERT_PUBLIC_KEY_INFO *got)
2549 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2550 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2551 got->Algorithm.pszObjId);
2552 ok(expected->Algorithm.Parameters.cbData ==
2553 got->Algorithm.Parameters.cbData,
2554 "Expected parameters of %d bytes, got %d\n",
2555 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2556 if (expected->Algorithm.Parameters.cbData)
2557 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2558 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2559 "Unexpected algorithm parameters\n");
2560 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2561 "Expected public key of %d bytes, got %d\n",
2562 expected->PublicKey.cbData, got->PublicKey.cbData);
2563 if (expected->PublicKey.cbData)
2564 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2565 got->PublicKey.cbData), "Unexpected public key value\n");
2568 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2570 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2571 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2572 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2573 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2574 DWORD i;
2575 BOOL ret;
2576 BYTE *buf = NULL;
2577 DWORD bufSize = 0;
2579 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2581 /* The NULL form decodes to the decoded member */
2582 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2583 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2584 NULL, (BYTE *)&buf, &bufSize);
2585 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2586 if (buf)
2588 comparePublicKeyInfo(&pubKeys[i].decoded,
2589 (CERT_PUBLIC_KEY_INFO *)buf);
2590 LocalFree(buf);
2592 /* The non-NULL form decodes to the original */
2593 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2594 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2595 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2596 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2597 if (buf)
2599 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2600 LocalFree(buf);
2603 /* Test with bogus (not valid DER) parameters */
2604 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2605 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2606 NULL, (BYTE *)&buf, &bufSize);
2607 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2608 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2611 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2612 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2613 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2614 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2615 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2616 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2617 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2618 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2619 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2620 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2621 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2622 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2623 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2624 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2625 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2626 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2627 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2628 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2629 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2630 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2631 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2632 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2633 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2634 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2635 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2636 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2637 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2638 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2639 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2640 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2641 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2642 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2643 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2644 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2645 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2646 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2647 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2648 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2649 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2651 static const BYTE serialNum[] = { 0x01 };
2653 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2655 BOOL ret;
2656 BYTE *buf = NULL;
2657 DWORD size = 0;
2658 CERT_INFO info = { 0 };
2660 /* Test with NULL pvStructInfo */
2661 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2662 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2663 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2664 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2665 /* Test with a V1 cert */
2666 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2667 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2668 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2669 if (buf)
2671 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2672 v1Cert[1] + 2, size);
2673 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2674 LocalFree(buf);
2676 /* Test v2 cert */
2677 info.dwVersion = CERT_V2;
2678 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2679 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2680 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2681 if (buf)
2683 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2684 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2685 LocalFree(buf);
2687 /* Test v3 cert */
2688 info.dwVersion = CERT_V3;
2689 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2690 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2691 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2692 if (buf)
2694 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2695 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2696 LocalFree(buf);
2698 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2699 * API doesn't prevent it)
2701 info.dwVersion = CERT_V1;
2702 info.cExtension = 1;
2703 info.rgExtension = &criticalExt;
2704 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2705 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2706 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2707 if (buf)
2709 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2710 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2711 LocalFree(buf);
2713 /* test v1 cert with a serial number */
2714 info.SerialNumber.cbData = sizeof(serialNum);
2715 info.SerialNumber.pbData = (BYTE *)serialNum;
2716 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2717 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2718 if (buf)
2720 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2721 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2722 LocalFree(buf);
2724 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2725 info.Issuer.cbData = sizeof(encodedCommonName);
2726 info.Issuer.pbData = (BYTE *)encodedCommonName;
2727 info.Subject.cbData = sizeof(encodedCommonName);
2728 info.Subject.pbData = (BYTE *)encodedCommonName;
2729 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2730 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2731 if (buf)
2733 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2734 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2735 LocalFree(buf);
2737 /* for now, I let more interesting tests be done for each subcomponent,
2738 * rather than retesting them all here.
2742 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2744 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2745 v1CertWithConstraints, v1CertWithSerial };
2746 BOOL ret;
2747 BYTE *buf = NULL;
2748 DWORD size = 0, i;
2750 /* Test with NULL pbEncoded */
2751 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2752 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2753 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2754 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2755 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2756 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2757 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2758 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2759 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2760 * minimum a cert must have a non-zero serial number, an issuer, and a
2761 * subject.
2763 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2765 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2766 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2767 (BYTE *)&buf, &size);
2768 ok(!ret, "Expected failure\n");
2770 /* Now check with serial number, subject and issuer specified */
2771 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2772 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2773 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2774 if (buf)
2776 CERT_INFO *info = (CERT_INFO *)buf;
2778 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2779 ok(info->SerialNumber.cbData == 1,
2780 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2781 ok(*info->SerialNumber.pbData == *serialNum,
2782 "Expected serial number %d, got %d\n", *serialNum,
2783 *info->SerialNumber.pbData);
2784 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2785 "Wrong size %d\n", info->Issuer.cbData);
2786 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2787 "Unexpected issuer\n");
2788 ok(info->Subject.cbData == sizeof(encodedCommonName),
2789 "Wrong size %d\n", info->Subject.cbData);
2790 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2791 info->Subject.cbData), "Unexpected subject\n");
2792 LocalFree(buf);
2796 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2797 0xe, 0xf };
2799 static const BYTE signedBigCert[] = {
2800 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2801 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2802 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2803 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2804 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2805 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2806 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2807 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2808 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2809 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2810 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2811 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2813 static void test_encodeCert(DWORD dwEncoding)
2815 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2816 * also that bigCert is a NULL-terminated string, so don't count its
2817 * last byte (otherwise the signed cert won't decode.)
2819 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2820 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2821 BOOL ret;
2822 BYTE *buf = NULL;
2823 DWORD bufSize = 0;
2825 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2826 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2827 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2828 if (buf)
2830 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
2831 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2832 LocalFree(buf);
2836 static void test_decodeCert(DWORD dwEncoding)
2838 BOOL ret;
2839 BYTE *buf = NULL;
2840 DWORD size = 0;
2842 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2843 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2844 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2845 if (buf)
2847 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2849 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2850 "Wrong cert size %d\n", info->ToBeSigned.cbData);
2851 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2852 "Unexpected cert\n");
2853 ok(info->Signature.cbData == sizeof(hash),
2854 "Wrong signature size %d\n", info->Signature.cbData);
2855 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2856 "Unexpected signature\n");
2857 LocalFree(buf);
2859 /* A signed cert decodes as a CERT_INFO too */
2860 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2861 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2862 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2863 if (buf)
2865 CERT_INFO *info = (CERT_INFO *)buf;
2867 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2868 ok(info->SerialNumber.cbData == 1,
2869 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2870 ok(*info->SerialNumber.pbData == *serialNum,
2871 "Expected serial number %d, got %d\n", *serialNum,
2872 *info->SerialNumber.pbData);
2873 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2874 "Wrong size %d\n", info->Issuer.cbData);
2875 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2876 "Unexpected issuer\n");
2877 ok(info->Subject.cbData == sizeof(encodedCommonName),
2878 "Wrong size %d\n", info->Subject.cbData);
2879 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2880 info->Subject.cbData), "Unexpected subject\n");
2881 LocalFree(buf);
2885 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2886 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2887 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2888 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2889 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2890 0x00, 0x03 };
2891 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2892 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2893 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2894 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2895 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2896 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2897 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2898 0x2e, 0x6f, 0x72, 0x67 };
2899 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2900 CRL_REASON_AFFILIATION_CHANGED;
2902 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2904 CRL_DIST_POINTS_INFO info = { 0 };
2905 CRL_DIST_POINT point = { { 0 } };
2906 CERT_ALT_NAME_ENTRY entry = { 0 };
2907 BOOL ret;
2908 BYTE *buf = NULL;
2909 DWORD size = 0;
2911 /* Test with an empty info */
2912 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2913 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2914 ok(!ret && GetLastError() == E_INVALIDARG,
2915 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2916 /* Test with one empty dist point */
2917 info.cDistPoint = 1;
2918 info.rgDistPoint = &point;
2919 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2920 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2921 if (buf)
2923 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
2924 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2925 LocalFree(buf);
2927 /* A dist point with an invalid name */
2928 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2929 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2930 U(entry).pwszURL = (LPWSTR)nihongoURL;
2931 U(point.DistPointName).FullName.cAltEntry = 1;
2932 U(point.DistPointName).FullName.rgAltEntry = &entry;
2933 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2934 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2935 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2936 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
2937 /* The first invalid character is at index 7 */
2938 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2939 "Expected invalid char at index 7, got %d\n",
2940 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2941 /* A dist point with (just) a valid name */
2942 U(entry).pwszURL = (LPWSTR)url;
2943 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2944 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2945 if (buf)
2947 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
2948 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2949 LocalFree(buf);
2951 /* A dist point with (just) reason flags */
2952 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2953 point.ReasonFlags.cbData = sizeof(crlReason);
2954 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2955 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2956 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2957 if (buf)
2959 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
2960 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2961 LocalFree(buf);
2963 /* A dist point with just an issuer */
2964 point.ReasonFlags.cbData = 0;
2965 point.CRLIssuer.cAltEntry = 1;
2966 point.CRLIssuer.rgAltEntry = &entry;
2967 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2968 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2969 if (buf)
2971 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
2972 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2973 LocalFree(buf);
2975 /* A dist point with both a name and an issuer */
2976 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2977 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2978 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2979 if (buf)
2981 ok(size == sizeof(distPointWithUrlAndIssuer),
2982 "Wrong size %d\n", size);
2983 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2984 LocalFree(buf);
2988 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2990 BOOL ret;
2991 BYTE *buf = NULL;
2992 DWORD size = 0;
2993 PCRL_DIST_POINTS_INFO info;
2994 PCRL_DIST_POINT point;
2995 PCERT_ALT_NAME_ENTRY entry;
2997 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2998 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2999 (BYTE *)&buf, &size);
3000 if (ret)
3002 info = (PCRL_DIST_POINTS_INFO)buf;
3003 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3004 "Wrong size %d\n", size);
3005 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3006 info->cDistPoint);
3007 point = info->rgDistPoint;
3008 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3009 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3010 point->DistPointName.dwDistPointNameChoice);
3011 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3012 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3013 LocalFree(buf);
3015 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3016 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3017 (BYTE *)&buf, &size);
3018 if (ret)
3020 info = (PCRL_DIST_POINTS_INFO)buf;
3021 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3022 "Wrong size %d\n", size);
3023 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3024 info->cDistPoint);
3025 point = info->rgDistPoint;
3026 ok(point->DistPointName.dwDistPointNameChoice ==
3027 CRL_DIST_POINT_FULL_NAME,
3028 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3029 point->DistPointName.dwDistPointNameChoice);
3030 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3031 "Expected 1 name entry, got %d\n",
3032 U(point->DistPointName).FullName.cAltEntry);
3033 entry = U(point->DistPointName).FullName.rgAltEntry;
3034 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3035 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3036 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3037 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3038 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3039 LocalFree(buf);
3041 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3042 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3043 NULL, (BYTE *)&buf, &size);
3044 if (ret)
3046 info = (PCRL_DIST_POINTS_INFO)buf;
3047 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3048 "Wrong size %d\n", size);
3049 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3050 info->cDistPoint);
3051 point = info->rgDistPoint;
3052 ok(point->DistPointName.dwDistPointNameChoice ==
3053 CRL_DIST_POINT_NO_NAME,
3054 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3055 point->DistPointName.dwDistPointNameChoice);
3056 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3057 "Expected reason length\n");
3058 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3059 "Unexpected reason\n");
3060 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3061 LocalFree(buf);
3063 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3064 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3065 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3066 if (ret)
3068 info = (PCRL_DIST_POINTS_INFO)buf;
3069 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3070 "Wrong size %d\n", size);
3071 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3072 info->cDistPoint);
3073 point = info->rgDistPoint;
3074 ok(point->DistPointName.dwDistPointNameChoice ==
3075 CRL_DIST_POINT_FULL_NAME,
3076 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3077 point->DistPointName.dwDistPointNameChoice);
3078 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3079 "Expected 1 name entry, got %d\n",
3080 U(point->DistPointName).FullName.cAltEntry);
3081 entry = U(point->DistPointName).FullName.rgAltEntry;
3082 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3083 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3084 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3085 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3086 ok(point->CRLIssuer.cAltEntry == 1,
3087 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3088 entry = point->CRLIssuer.rgAltEntry;
3089 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3090 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3091 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3092 LocalFree(buf);
3096 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3097 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3098 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3099 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3100 0x67 };
3102 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3104 BOOL ret;
3105 BYTE *buf = NULL;
3106 DWORD size = 0;
3107 CRL_ISSUING_DIST_POINT point = { { 0 } };
3108 CERT_ALT_NAME_ENTRY entry;
3110 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3111 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3112 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3114 skip("no X509_ISSUING_DIST_POINT encode support\n");
3115 return;
3117 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3118 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3119 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3120 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3121 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3122 if (buf)
3124 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3125 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3126 LocalFree(buf);
3128 /* nonsensical flags */
3129 point.fOnlyContainsUserCerts = TRUE;
3130 point.fOnlyContainsCACerts = TRUE;
3131 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3132 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3133 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3134 if (buf)
3136 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3137 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3138 LocalFree(buf);
3140 /* unimplemented name type */
3141 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3142 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3143 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3144 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3145 ok(!ret && GetLastError() == E_INVALIDARG,
3146 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3147 /* empty name */
3148 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3149 U(point.DistPointName).FullName.cAltEntry = 0;
3150 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3151 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3152 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3153 if (buf)
3155 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3156 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3157 LocalFree(buf);
3159 /* name with URL entry */
3160 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3161 U(entry).pwszURL = (LPWSTR)url;
3162 U(point.DistPointName).FullName.cAltEntry = 1;
3163 U(point.DistPointName).FullName.rgAltEntry = &entry;
3164 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3165 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3166 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3167 if (buf)
3169 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3170 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3171 LocalFree(buf);
3175 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3176 const CERT_ALT_NAME_ENTRY *got)
3178 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3179 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3180 got->dwAltNameChoice);
3181 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3183 switch (got->dwAltNameChoice)
3185 case CERT_ALT_NAME_RFC822_NAME:
3186 case CERT_ALT_NAME_DNS_NAME:
3187 case CERT_ALT_NAME_EDI_PARTY_NAME:
3188 case CERT_ALT_NAME_URL:
3189 case CERT_ALT_NAME_REGISTERED_ID:
3190 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3191 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
3192 break;
3193 case CERT_ALT_NAME_X400_ADDRESS:
3194 case CERT_ALT_NAME_DIRECTORY_NAME:
3195 case CERT_ALT_NAME_IP_ADDRESS:
3196 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3197 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3198 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3199 U(*got).IPAddress.cbData), "Unexpected value\n");
3200 break;
3205 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3206 const CERT_ALT_NAME_INFO *got)
3208 DWORD i;
3210 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3211 expected->cAltEntry, got->cAltEntry);
3212 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3213 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3216 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3217 const CRL_DIST_POINT_NAME *got)
3219 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3220 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3221 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3222 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3225 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3226 const CRL_ISSUING_DIST_POINT *got)
3228 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3229 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3230 "Unexpected fOnlyContainsUserCerts\n");
3231 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3232 "Unexpected fOnlyContainsCACerts\n");
3233 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3234 "Unexpected reason flags\n");
3235 ok(got->fIndirectCRL == expected->fIndirectCRL,
3236 "Unexpected fIndirectCRL\n");
3239 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3241 BOOL ret;
3242 BYTE *buf = NULL;
3243 DWORD size = 0;
3244 CRL_ISSUING_DIST_POINT point = { { 0 } };
3246 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3247 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3248 (BYTE *)&buf, &size);
3249 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3251 skip("no X509_ISSUING_DIST_POINT decode support\n");
3252 return;
3254 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3255 if (ret)
3257 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3258 LocalFree(buf);
3260 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3261 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3262 (BYTE *)&buf, &size);
3263 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3264 if (ret)
3266 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3267 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3268 LocalFree(buf);
3270 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3271 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3272 (BYTE *)&buf, &size);
3273 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3274 if (ret)
3276 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3277 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3278 U(point.DistPointName).FullName.cAltEntry = 0;
3279 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3280 LocalFree(buf);
3282 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3283 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3284 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3285 if (ret)
3287 CERT_ALT_NAME_ENTRY entry;
3289 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3290 U(entry).pwszURL = (LPWSTR)url;
3291 U(point.DistPointName).FullName.cAltEntry = 1;
3292 U(point.DistPointName).FullName.rgAltEntry = &entry;
3293 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3294 LocalFree(buf);
3298 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3299 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3300 0x30, 0x5a };
3301 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3302 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3303 0x30, 0x30, 0x30, 0x30, 0x5a };
3304 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3305 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3306 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3307 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3308 0x5a };
3309 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3310 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3311 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3312 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3313 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3314 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3315 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3316 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3317 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3318 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3319 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3320 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3321 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3322 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3323 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3324 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3325 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3326 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3327 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3328 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3329 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3330 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3331 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3332 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3333 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3334 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3335 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3336 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3337 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3338 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3339 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3340 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3341 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3342 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3343 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3344 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3345 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3346 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3347 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3348 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3350 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3352 BOOL ret;
3353 BYTE *buf = NULL;
3354 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3355 DWORD size = 0;
3356 CRL_INFO info = { 0 };
3357 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3358 CERT_EXTENSION ext;
3360 /* Test with a V1 CRL */
3361 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3362 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3363 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3364 if (buf)
3366 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3367 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3368 LocalFree(buf);
3370 /* Test v2 CRL */
3371 info.dwVersion = CRL_V2;
3372 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3373 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3374 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3375 if (buf)
3377 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3378 v2CRL[1] + 2, size);
3379 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3380 LocalFree(buf);
3382 /* v1 CRL with a name */
3383 info.dwVersion = CRL_V1;
3384 info.Issuer.cbData = sizeof(encodedCommonName);
3385 info.Issuer.pbData = (BYTE *)encodedCommonName;
3386 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3387 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3388 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3389 if (buf)
3391 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3392 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3393 LocalFree(buf);
3395 /* v1 CRL with a name and a NULL entry pointer */
3396 info.cCRLEntry = 1;
3397 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3398 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3399 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3400 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3401 /* now set an empty entry */
3402 info.rgCRLEntry = &entry;
3403 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3404 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3405 if (buf)
3407 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3408 "Wrong size %d\n", size);
3409 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3410 "Got unexpected value\n");
3411 LocalFree(buf);
3413 /* an entry with a serial number */
3414 entry.SerialNumber.cbData = sizeof(serialNum);
3415 entry.SerialNumber.pbData = (BYTE *)serialNum;
3416 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3417 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3418 if (buf)
3420 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3421 "Wrong size %d\n", size);
3422 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3423 "Got unexpected value\n");
3424 LocalFree(buf);
3426 /* an entry with an extension */
3427 entry.cExtension = 1;
3428 entry.rgExtension = &criticalExt;
3429 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3430 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3431 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3432 if (buf)
3434 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3435 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3436 LocalFree(buf);
3438 /* a CRL with an extension */
3439 entry.cExtension = 0;
3440 info.cExtension = 1;
3441 info.rgExtension = &criticalExt;
3442 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3443 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3444 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3445 if (buf)
3447 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3448 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3449 LocalFree(buf);
3451 /* a v2 CRL with an extension, this time non-critical */
3452 info.dwVersion = CRL_V2;
3453 info.rgExtension = &nonCriticalExt;
3454 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3455 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3456 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3457 if (buf)
3459 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3460 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3461 LocalFree(buf);
3463 /* a v2 CRL with an issuing dist point extension */
3464 ext.pszObjId = oid_issuing_dist_point;
3465 ext.fCritical = TRUE;
3466 ext.Value.cbData = sizeof(urlIDP);
3467 ext.Value.pbData = (LPBYTE)urlIDP;
3468 entry.rgExtension = &ext;
3469 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3470 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3471 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3472 if (buf)
3474 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3475 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3476 LocalFree(buf);
3480 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3481 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3482 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3483 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3484 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3485 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3486 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3487 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3488 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3489 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3490 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3491 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3492 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3493 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3494 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3495 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3496 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3497 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3498 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3499 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3500 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3501 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3502 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3503 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3504 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3505 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3506 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3507 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3508 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3509 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3510 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3511 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3512 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3513 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3514 0xcd };
3515 static const BYTE verisignCRLWithLotsOfEntries[] = {
3516 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3517 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3518 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3519 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3520 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3521 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3522 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3523 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3524 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3525 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3526 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3527 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3528 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3529 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3530 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3531 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3532 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3533 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3534 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3535 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3536 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3537 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3538 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3539 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3540 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3541 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3542 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3543 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3544 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3545 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3546 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3547 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3548 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3549 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3550 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3551 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3552 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3553 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3554 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3555 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3556 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3557 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3558 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3559 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3560 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3561 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3562 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3563 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3564 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3565 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3566 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3567 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3568 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3569 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3570 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3571 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3572 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3573 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3574 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3575 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3576 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3577 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3578 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3579 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3580 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3581 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3582 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3583 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3584 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3585 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3586 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3587 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3588 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3589 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3590 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3591 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3592 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3593 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3594 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3595 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3596 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3597 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3598 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3599 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3600 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3601 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3602 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3603 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3604 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3605 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3606 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3607 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3608 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3609 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3610 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3611 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3612 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3613 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3614 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3615 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3616 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3617 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3618 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3619 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3620 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3621 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3622 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3623 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3624 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3625 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3626 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3627 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3628 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3629 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3630 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3631 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3632 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3633 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3634 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3635 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3636 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3637 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3638 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3639 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3640 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3641 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3642 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3643 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3644 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3645 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3646 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3647 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3648 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3649 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3650 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3651 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3652 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3653 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3654 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3655 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3656 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3657 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3658 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3659 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3660 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3661 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3662 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3663 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3664 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3665 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3666 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3667 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3668 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3669 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3670 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3671 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3672 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3673 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3674 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3675 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3676 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3677 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3678 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3679 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3680 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3681 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3682 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3683 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3684 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3685 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3686 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3687 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3688 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3689 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3690 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3691 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3692 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3693 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3694 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3695 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3696 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3697 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3698 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3699 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3700 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3701 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3702 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3703 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3704 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3705 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3706 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3707 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3708 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3709 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3710 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3711 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3712 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3713 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3714 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3715 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3716 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3717 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3718 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3719 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3720 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3721 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3722 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3723 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3724 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3725 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3726 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3727 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3728 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3729 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3730 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3731 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3732 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3733 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3734 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3735 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3736 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3737 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3738 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3739 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3740 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3741 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3742 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3743 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3744 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3745 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3746 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3747 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3748 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3749 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3750 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3751 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3752 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3753 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3754 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3755 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3756 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3757 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3758 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3759 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3760 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3761 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3762 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3763 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3764 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3765 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3766 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3767 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3768 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3769 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3770 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3771 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3772 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3773 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3774 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3775 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3776 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3777 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3778 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3779 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3780 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3781 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3782 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3783 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3784 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3785 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3786 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3787 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3788 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3789 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
3790 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
3791 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
3792 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
3793 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
3794 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
3795 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
3796 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
3797 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
3798 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
3799 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
3800 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
3801 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
3802 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
3803 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
3804 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
3805 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
3806 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
3807 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
3808 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
3809 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
3810 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
3811 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
3812 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
3813 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
3814 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
3815 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
3816 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
3817 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
3818 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
3819 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
3820 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
3821 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
3822 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
3823 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
3824 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
3825 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
3826 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
3827 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
3828 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
3829 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
3830 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
3831 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
3832 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
3833 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
3834 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
3835 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
3836 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
3837 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
3838 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
3839 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
3840 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
3841 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
3842 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
3843 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
3844 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
3845 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
3846 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
3847 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
3848 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
3849 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
3850 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
3851 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
3852 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
3853 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
3854 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
3855 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
3856 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
3857 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
3858 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
3859 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
3860 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
3861 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
3862 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
3863 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
3864 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
3865 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
3866 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
3867 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
3868 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
3869 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
3870 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
3871 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
3872 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
3873 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
3874 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
3875 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
3876 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
3877 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
3878 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
3879 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
3880 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
3881 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
3882 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
3883 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
3884 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
3885 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
3886 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
3887 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
3888 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
3889 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
3890 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
3891 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
3892 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
3893 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
3894 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
3895 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
3896 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
3897 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
3898 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
3899 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
3900 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
3901 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
3902 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
3903 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
3904 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
3905 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
3906 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
3907 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
3908 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
3909 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
3910 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
3911 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
3912 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
3913 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
3914 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
3915 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
3916 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
3917 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
3918 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
3919 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
3920 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
3921 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
3922 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
3923 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
3924 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
3925 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
3926 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
3927 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
3928 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
3929 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
3930 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
3931 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
3932 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
3933 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
3934 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
3935 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
3936 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
3937 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
3938 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
3939 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
3940 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
3941 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
3942 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
3943 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
3944 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
3945 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
3946 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
3947 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
3948 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
3949 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
3950 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
3951 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
3952 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
3953 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
3954 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
3955 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
3956 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
3957 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
3958 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
3959 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
3960 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
3961 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
3962 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
3963 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
3964 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
3965 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
3966 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
3967 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
3968 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
3969 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
3970 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
3971 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
3972 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
3973 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
3974 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
3975 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
3976 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
3977 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
3978 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3979 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
3980 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
3981 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
3982 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
3983 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
3984 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
3985 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
3986 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
3987 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
3988 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
3989 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
3990 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
3991 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
3992 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
3993 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
3994 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
3995 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
3996 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
3997 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
3998 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
3999 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4000 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4001 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4002 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4003 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4004 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4005 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4006 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4007 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4008 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4009 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4010 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4011 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4012 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4013 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4014 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4015 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4016 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4017 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4018 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4019 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4020 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4021 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4022 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4023 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4025 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4027 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4028 BOOL ret;
4029 BYTE *buf = NULL;
4030 DWORD size = 0, i;
4032 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4034 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4035 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4036 (BYTE *)&buf, &size);
4037 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4038 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4040 /* at a minimum, a CRL must contain an issuer: */
4041 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4042 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4043 (BYTE *)&buf, &size);
4044 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4045 if (buf)
4047 CRL_INFO *info = (CRL_INFO *)buf;
4049 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4050 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4051 info->cCRLEntry);
4052 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4053 "Wrong issuer size %d\n", info->Issuer.cbData);
4054 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4055 "Unexpected issuer\n");
4056 LocalFree(buf);
4058 /* check decoding with an empty CRL entry */
4059 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4060 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4061 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4062 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4063 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4064 /* with a real CRL entry */
4065 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4066 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4067 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4068 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4069 if (buf)
4071 CRL_INFO *info = (CRL_INFO *)buf;
4072 CRL_ENTRY *entry;
4074 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4075 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4076 info->cCRLEntry);
4077 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4078 entry = info->rgCRLEntry;
4079 ok(entry->SerialNumber.cbData == 1,
4080 "Expected serial number size 1, got %d\n",
4081 entry->SerialNumber.cbData);
4082 ok(*entry->SerialNumber.pbData == *serialNum,
4083 "Expected serial number %d, got %d\n", *serialNum,
4084 *entry->SerialNumber.pbData);
4085 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4086 "Wrong issuer size %d\n", info->Issuer.cbData);
4087 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4088 "Unexpected issuer\n");
4090 /* a real CRL from verisign that has extensions */
4091 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4092 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4093 NULL, (BYTE *)&buf, &size);
4094 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4095 if (buf)
4097 CRL_INFO *info = (CRL_INFO *)buf;
4098 CRL_ENTRY *entry;
4100 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4101 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4102 info->cCRLEntry);
4103 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4104 entry = info->rgCRLEntry;
4105 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4106 info->cExtension);
4107 LocalFree(buf);
4109 /* another real CRL from verisign that has lots of entries */
4110 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4111 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4112 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4113 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4114 if (buf)
4116 CRL_INFO *info = (CRL_INFO *)buf;
4118 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4119 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4120 info->cCRLEntry);
4121 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4122 info->cExtension);
4123 LocalFree(buf);
4125 /* and finally, with an extension */
4126 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4127 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4128 NULL, (BYTE *)&buf, &size);
4129 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4130 if (buf)
4132 CRL_INFO *info = (CRL_INFO *)buf;
4133 CRL_ENTRY *entry;
4135 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4136 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4137 info->cCRLEntry);
4138 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4139 entry = info->rgCRLEntry;
4140 ok(entry->SerialNumber.cbData == 1,
4141 "Expected serial number size 1, got %d\n",
4142 entry->SerialNumber.cbData);
4143 ok(*entry->SerialNumber.pbData == *serialNum,
4144 "Expected serial number %d, got %d\n", *serialNum,
4145 *entry->SerialNumber.pbData);
4146 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4147 "Wrong issuer size %d\n", info->Issuer.cbData);
4148 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4149 "Unexpected issuer\n");
4150 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4151 info->cExtension);
4153 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4154 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4155 NULL, (BYTE *)&buf, &size);
4156 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4157 if (buf)
4159 CRL_INFO *info = (CRL_INFO *)buf;
4161 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4162 info->cExtension);
4163 LocalFree(buf);
4165 /* And again, with an issuing dist point */
4166 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4167 v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4168 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4169 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4170 if (buf)
4172 CRL_INFO *info = (CRL_INFO *)buf;
4174 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4175 info->cExtension);
4176 LocalFree(buf);
4180 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4181 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4182 static const BYTE encodedUsage[] = {
4183 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4184 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4185 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4187 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4189 BOOL ret;
4190 BYTE *buf = NULL;
4191 DWORD size = 0;
4192 CERT_ENHKEY_USAGE usage;
4194 /* Test with empty usage */
4195 usage.cUsageIdentifier = 0;
4196 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4197 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4198 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4199 if (buf)
4201 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4202 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4203 LocalFree(buf);
4205 /* Test with a few usages */
4206 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4207 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4208 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4209 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4210 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4211 if (buf)
4213 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4214 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4215 LocalFree(buf);
4219 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4221 BOOL ret;
4222 LPBYTE buf = NULL;
4223 DWORD size = 0;
4225 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4226 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4227 (BYTE *)&buf, &size);
4228 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4229 if (buf)
4231 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4233 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4234 "Wrong size %d\n", size);
4235 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4236 usage->cUsageIdentifier);
4237 LocalFree(buf);
4239 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4240 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4241 (BYTE *)&buf, &size);
4242 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4243 if (buf)
4245 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4246 DWORD i;
4248 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4249 "Wrong size %d\n", size);
4250 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4251 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4252 for (i = 0; i < usage->cUsageIdentifier; i++)
4253 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4254 "Expected OID %s, got %s\n", keyUsages[i],
4255 usage->rgpszUsageIdentifier[i]);
4256 LocalFree(buf);
4260 static const BYTE authorityKeyIdWithId[] = { 0x30,0x03,0x80,0x01,0x01 };
4261 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4262 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4263 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4264 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4266 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4268 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4269 BOOL ret;
4270 BYTE *buf = NULL;
4271 DWORD size = 0;
4273 /* Test with empty id */
4274 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4275 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4276 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4277 if (buf)
4279 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4280 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4281 LocalFree(buf);
4283 /* With just a key id */
4284 info.KeyId.cbData = sizeof(serialNum);
4285 info.KeyId.pbData = (BYTE *)serialNum;
4286 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4287 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4288 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4289 if (buf)
4291 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4292 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4293 LocalFree(buf);
4295 /* With just an issuer */
4296 info.KeyId.cbData = 0;
4297 info.CertIssuer.cbData = sizeof(encodedCommonName);
4298 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4299 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4300 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4301 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4302 if (buf)
4304 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4305 size);
4306 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4307 LocalFree(buf);
4309 /* With just a serial number */
4310 info.CertIssuer.cbData = 0;
4311 info.CertSerialNumber.cbData = sizeof(serialNum);
4312 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4313 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4314 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4315 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4316 if (buf)
4318 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4319 size);
4320 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4321 LocalFree(buf);
4325 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4327 BOOL ret;
4328 LPBYTE buf = NULL;
4329 DWORD size = 0;
4331 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4332 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4333 (BYTE *)&buf, &size);
4334 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4335 if (buf)
4337 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4339 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4340 size);
4341 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4342 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4343 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4344 LocalFree(buf);
4346 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4347 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4348 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4349 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4350 if (buf)
4352 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4354 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4355 size);
4356 ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4357 ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4358 "Unexpected key id\n");
4359 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4360 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4361 LocalFree(buf);
4363 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4364 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4365 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4366 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4367 if (buf)
4369 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4371 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4372 size);
4373 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4374 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4375 "Unexpected issuer len\n");
4376 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4377 sizeof(encodedCommonName)), "Unexpected issuer\n");
4378 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4379 LocalFree(buf);
4381 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4382 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4383 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4384 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4385 if (buf)
4387 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4389 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4390 size);
4391 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4392 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4393 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4394 "Unexpected serial number len\n");
4395 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4396 "Unexpected serial number\n");
4397 LocalFree(buf);
4401 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4402 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4403 0x6f,0x72,0x67 };
4405 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4407 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4408 CERT_ALT_NAME_ENTRY entry = { 0 };
4409 BOOL ret;
4410 BYTE *buf = NULL;
4411 DWORD size = 0;
4413 /* Test with empty id */
4414 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4415 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4416 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4417 if (buf)
4419 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4420 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4421 LocalFree(buf);
4423 /* With just a key id */
4424 info.KeyId.cbData = sizeof(serialNum);
4425 info.KeyId.pbData = (BYTE *)serialNum;
4426 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4427 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4428 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4429 if (buf)
4431 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4432 size);
4433 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4434 LocalFree(buf);
4436 /* With a bogus issuer name */
4437 info.KeyId.cbData = 0;
4438 info.AuthorityCertIssuer.cAltEntry = 1;
4439 info.AuthorityCertIssuer.rgAltEntry = &entry;
4440 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4441 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4442 ok(!ret && GetLastError() == E_INVALIDARG,
4443 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4444 /* With an issuer name */
4445 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4446 U(entry).pwszURL = (LPWSTR)url;
4447 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4448 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4449 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4450 if (buf)
4452 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4453 size);
4454 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4455 "Unexpected value\n");
4456 LocalFree(buf);
4458 /* With just a serial number */
4459 info.AuthorityCertIssuer.cAltEntry = 0;
4460 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4461 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4462 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4463 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4464 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4465 if (buf)
4467 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4468 size);
4469 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4470 LocalFree(buf);
4474 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4476 BOOL ret;
4477 LPBYTE buf = NULL;
4478 DWORD size = 0;
4480 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4481 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4482 (BYTE *)&buf, &size);
4483 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4484 if (buf)
4486 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4488 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4489 size);
4490 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4491 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4492 "Expected no issuer name entries\n");
4493 ok(info->AuthorityCertSerialNumber.cbData == 0,
4494 "Expected no serial number\n");
4495 LocalFree(buf);
4497 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4498 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4499 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4500 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4501 if (buf)
4503 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4505 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4506 size);
4507 ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4508 ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4509 "Unexpected key id\n");
4510 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4511 "Expected no issuer name entries\n");
4512 ok(info->AuthorityCertSerialNumber.cbData == 0,
4513 "Expected no serial number\n");
4514 LocalFree(buf);
4516 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4517 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4518 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4519 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4520 if (buf)
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",
4525 size);
4526 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4527 ok(info->AuthorityCertIssuer.cAltEntry == 1,
4528 "Expected 1 issuer entry, got %d\n",
4529 info->AuthorityCertIssuer.cAltEntry);
4530 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4531 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4532 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4533 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4534 url), "Unexpected URL\n");
4535 ok(info->AuthorityCertSerialNumber.cbData == 0,
4536 "Expected no serial number\n");
4537 LocalFree(buf);
4539 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4540 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4541 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4542 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4543 if (buf)
4545 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4547 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4548 size);
4549 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4550 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4551 "Expected no issuer name entries\n");
4552 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4553 "Unexpected serial number len\n");
4554 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4555 sizeof(serialNum)), "Unexpected serial number\n");
4556 LocalFree(buf);
4560 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
4561 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
4562 0x03,0,0,0,0,0,0 };
4563 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
4564 0xa0,0x01,0x01 };
4565 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
4566 0x03,0x02,0x01,0x01 };
4567 static BYTE bogusDER[] = { 1 };
4569 static void test_encodePKCSContentInfo(DWORD dwEncoding)
4571 BOOL ret;
4572 BYTE *buf = NULL;
4573 DWORD size = 0;
4574 CRYPT_CONTENT_INFO info = { 0 };
4575 char oid1[] = "1.2.3";
4577 SetLastError(0xdeadbeef);
4578 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
4579 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4580 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4581 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4582 SetLastError(0xdeadbeef);
4583 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4584 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4585 ok(!ret && GetLastError() == E_INVALIDARG,
4586 "Expected E_INVALIDARG, got %x\n", GetLastError());
4587 info.pszObjId = oid1;
4588 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4589 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4590 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4591 if (buf)
4593 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
4594 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
4595 LocalFree(buf);
4597 info.Content.pbData = bogusDER;
4598 info.Content.cbData = sizeof(bogusDER);
4599 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4600 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4601 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
4602 if (buf)
4604 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
4605 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
4606 LocalFree(buf);
4608 info.Content.pbData = (BYTE *)ints[0].encoded;
4609 info.Content.cbData = ints[0].encoded[1] + 2;
4610 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4611 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4612 if (buf)
4614 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
4615 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
4616 LocalFree(buf);
4620 static void test_decodePKCSContentInfo(DWORD dwEncoding)
4622 BOOL ret;
4623 LPBYTE buf = NULL;
4624 DWORD size = 0;
4625 CRYPT_CONTENT_INFO *info;
4627 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4628 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
4629 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4630 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4631 if (buf)
4633 info = (CRYPT_CONTENT_INFO *)buf;
4635 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4636 info->pszObjId);
4637 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
4638 info->Content.cbData);
4639 LocalFree(buf);
4641 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4642 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
4643 0, NULL, NULL, &size);
4644 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4645 SetLastError(0xdeadbeef);
4646 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4647 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
4648 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4649 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4650 * I doubt an app depends on that.
4652 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4653 GetLastError() == CRYPT_E_ASN1_CORRUPT),
4654 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4655 GetLastError());
4656 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4657 intPKCSContentInfo, sizeof(intPKCSContentInfo),
4658 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4659 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4660 if (buf)
4662 info = (CRYPT_CONTENT_INFO *)buf;
4664 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4665 info->pszObjId);
4666 ok(info->Content.cbData == ints[0].encoded[1] + 2,
4667 "Unexpected size %d\n", info->Content.cbData);
4668 ok(!memcmp(info->Content.pbData, ints[0].encoded,
4669 info->Content.cbData), "Unexpected value\n");
4673 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
4674 0x00 };
4675 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
4676 0x01 };
4677 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
4678 0x02,0x01,0x01 };
4680 static void test_encodePKCSAttribute(DWORD dwEncoding)
4682 CRYPT_ATTRIBUTE attr = { 0 };
4683 BOOL ret;
4684 LPBYTE buf = NULL;
4685 DWORD size = 0;
4686 CRYPT_ATTR_BLOB blob;
4687 char oid[] = "1.2.3";
4689 SetLastError(0xdeadbeef);
4690 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
4691 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4692 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4693 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4694 SetLastError(0xdeadbeef);
4695 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4696 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4697 ok(!ret && GetLastError() == E_INVALIDARG,
4698 "Expected E_INVALIDARG, got %x\n", GetLastError());
4699 attr.pszObjId = oid;
4700 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4701 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4702 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4703 if (buf)
4705 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
4706 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
4707 LocalFree(buf);
4709 blob.cbData = sizeof(bogusDER);
4710 blob.pbData = bogusDER;
4711 attr.cValue = 1;
4712 attr.rgValue = &blob;
4713 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4714 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4715 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4716 if (buf)
4718 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
4719 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
4720 LocalFree(buf);
4722 blob.pbData = (BYTE *)ints[0].encoded;
4723 blob.cbData = ints[0].encoded[1] + 2;
4724 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4725 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4726 if (buf)
4728 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
4729 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
4730 LocalFree(buf);
4734 static void test_decodePKCSAttribute(DWORD dwEncoding)
4736 BOOL ret;
4737 LPBYTE buf = NULL;
4738 DWORD size = 0;
4739 CRYPT_ATTRIBUTE *attr;
4741 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4742 emptyPKCSAttr, sizeof(emptyPKCSAttr),
4743 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4744 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4745 if (buf)
4747 attr = (CRYPT_ATTRIBUTE *)buf;
4749 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4750 attr->pszObjId);
4751 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
4752 LocalFree(buf);
4754 SetLastError(0xdeadbeef);
4755 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4756 bogusPKCSAttr, sizeof(bogusPKCSAttr),
4757 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4758 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4759 * I doubt an app depends on that.
4761 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4762 GetLastError() == CRYPT_E_ASN1_CORRUPT),
4763 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4764 GetLastError());
4765 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4766 intPKCSAttr, sizeof(intPKCSAttr),
4767 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4768 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4769 if (buf)
4771 attr = (CRYPT_ATTRIBUTE *)buf;
4773 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4774 attr->pszObjId);
4775 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
4776 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
4777 "Unexpected size %d\n", attr->rgValue[0].cbData);
4778 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
4779 attr->rgValue[0].cbData), "Unexpected value\n");
4783 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
4784 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
4785 0x2a,0x03,0x31,0x00 };
4786 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
4787 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
4789 static void test_encodePKCSAttributes(DWORD dwEncoding)
4791 CRYPT_ATTRIBUTES attributes = { 0 };
4792 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
4793 CRYPT_ATTR_BLOB blob;
4794 BOOL ret;
4795 LPBYTE buf = NULL;
4796 DWORD size = 0;
4797 char oid1[] = "1.2.3", oid2[] = "1.5.6";
4799 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4800 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4801 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4802 if (buf)
4804 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
4805 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
4806 LocalFree(buf);
4808 attributes.cAttr = 1;
4809 attributes.rgAttr = attr;
4810 SetLastError(0xdeadbeef);
4811 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4812 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4813 ok(!ret && GetLastError() == E_INVALIDARG,
4814 "Expected E_INVALIDARG, got %x\n", GetLastError());
4815 attr[0].pszObjId = oid1;
4816 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4817 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4818 if (buf)
4820 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
4821 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
4822 LocalFree(buf);
4824 attr[1].pszObjId = oid2;
4825 attr[1].cValue = 1;
4826 attr[1].rgValue = &blob;
4827 blob.pbData = (BYTE *)ints[0].encoded;
4828 blob.cbData = ints[0].encoded[1] + 2;
4829 attributes.cAttr = 2;
4830 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4831 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4832 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4833 if (buf)
4835 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
4836 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
4837 LocalFree(buf);
4841 static void test_decodePKCSAttributes(DWORD dwEncoding)
4843 BOOL ret;
4844 LPBYTE buf = NULL;
4845 DWORD size = 0;
4846 CRYPT_ATTRIBUTES *attributes;
4848 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
4849 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
4850 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4851 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4852 if (buf)
4854 attributes = (CRYPT_ATTRIBUTES *)buf;
4855 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
4856 attributes->cAttr);
4857 LocalFree(buf);
4859 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
4860 singlePKCSAttributes, sizeof(singlePKCSAttributes),
4861 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4862 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4863 if (buf)
4865 attributes = (CRYPT_ATTRIBUTES *)buf;
4866 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
4867 attributes->cAttr);
4868 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
4869 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
4870 ok(attributes->rgAttr[0].cValue == 0,
4871 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
4872 LocalFree(buf);
4874 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
4875 doublePKCSAttributes, sizeof(doublePKCSAttributes),
4876 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4877 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4878 if (buf)
4880 attributes = (CRYPT_ATTRIBUTES *)buf;
4881 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
4882 attributes->cAttr);
4883 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
4884 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
4885 ok(attributes->rgAttr[0].cValue == 0,
4886 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
4887 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
4888 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
4889 ok(attributes->rgAttr[1].cValue == 1,
4890 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
4891 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
4892 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
4893 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
4894 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
4895 LocalFree(buf);
4899 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
4900 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
4901 0x67 };
4902 static const BYTE minimalPKCSSigner[] = {
4903 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,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 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
4906 static const BYTE PKCSSignerWithSerial[] = {
4907 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4908 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4909 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
4910 0x00 };
4911 static const BYTE PKCSSignerWithHashAlgo[] = {
4912 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4913 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4914 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
4915 0x00,0x04,0x00 };
4916 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
4917 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4918 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4919 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
4920 0x06,0x05,0x00,0x04,0x00 };
4921 static const BYTE PKCSSignerWithHash[] = {
4922 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4923 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4924 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
4925 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
4926 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
4927 static const BYTE PKCSSignerWithAuthAttr[] = {
4928 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4929 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4930 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
4931 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
4932 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
4933 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
4934 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
4936 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
4938 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
4939 BOOL ret;
4940 LPBYTE buf = NULL;
4941 DWORD size = 0;
4942 CMSG_SIGNER_INFO info = { 0 };
4943 char oid_common_name[] = szOID_COMMON_NAME;
4944 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
4945 (LPBYTE)encodedCommonName };
4946 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
4948 SetLastError(0xdeadbeef);
4949 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4950 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4951 ok(!ret && GetLastError() == E_INVALIDARG,
4952 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4953 /* To be encoded, a signer must have an issuer at least, and the encoding
4954 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
4955 * see decoding tests.)
4957 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
4958 info.Issuer.pbData = encodedCommonNameNoNull;
4959 SetLastError(0xdeadbeef);
4960 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4961 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4962 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
4963 ok(!ret && GetLastError() == E_INVALIDARG,
4964 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4965 else
4967 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4968 if (buf)
4970 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
4971 if (size == sizeof(minimalPKCSSigner))
4972 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
4973 else
4974 ok(0, "Unexpected value\n");
4975 LocalFree(buf);
4978 info.SerialNumber.cbData = sizeof(serialNum);
4979 info.SerialNumber.pbData = (BYTE *)serialNum;
4980 SetLastError(0xdeadbeef);
4981 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4982 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4983 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
4984 ok(!ret && GetLastError() == E_INVALIDARG,
4985 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4986 else
4988 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4989 if (buf)
4991 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
4992 size);
4993 if (size == sizeof(PKCSSignerWithSerial))
4994 ok(!memcmp(buf, PKCSSignerWithSerial, size),
4995 "Unexpected value\n");
4996 else
4997 ok(0, "Unexpected value\n");
4998 LocalFree(buf);
5001 info.HashAlgorithm.pszObjId = oid1;
5002 SetLastError(0xdeadbeef);
5003 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5004 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5005 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5006 ok(!ret && GetLastError() == E_INVALIDARG,
5007 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5008 else
5010 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5011 if (buf)
5013 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
5014 size);
5015 if (size == sizeof(PKCSSignerWithHashAlgo))
5016 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
5017 "Unexpected value\n");
5018 else
5019 ok(0, "Unexpected value\n");
5020 LocalFree(buf);
5023 info.HashEncryptionAlgorithm.pszObjId = oid2;
5024 SetLastError(0xdeadbeef);
5025 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5026 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5027 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5028 ok(!ret && GetLastError() == E_INVALIDARG,
5029 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5030 else
5032 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5033 if (buf)
5035 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
5036 "Unexpected size %d\n", size);
5037 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
5038 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
5039 "Unexpected value\n");
5040 else
5041 ok(0, "Unexpected value\n");
5042 LocalFree(buf);
5045 info.EncryptedHash.cbData = sizeof(hash);
5046 info.EncryptedHash.pbData = (BYTE *)hash;
5047 SetLastError(0xdeadbeef);
5048 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5049 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5050 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5051 ok(!ret && GetLastError() == E_INVALIDARG,
5052 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5053 else
5055 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5056 if (buf)
5058 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
5059 size);
5060 if (size == sizeof(PKCSSignerWithHash))
5061 ok(!memcmp(buf, PKCSSignerWithHash, size),
5062 "Unexpected value\n");
5063 else
5064 ok(0, "Unexpected value\n");
5065 LocalFree(buf);
5068 info.AuthAttrs.cAttr = 1;
5069 info.AuthAttrs.rgAttr = &attr;
5070 SetLastError(0xdeadbeef);
5071 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5072 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5073 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5074 ok(!ret && GetLastError() == E_INVALIDARG,
5075 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5076 else
5078 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5079 if (buf)
5081 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
5082 size);
5083 if (size == sizeof(PKCSSignerWithAuthAttr))
5084 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
5085 "Unexpected value\n");
5086 else
5087 ok(0, "Unexpected value\n");
5088 LocalFree(buf);
5093 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
5095 BOOL ret;
5096 LPBYTE buf = NULL;
5097 DWORD size = 0;
5098 CMSG_SIGNER_INFO *info;
5100 /* A PKCS signer can't be decoded without a serial number. */
5101 SetLastError(0xdeadbeef);
5102 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5103 minimalPKCSSigner, sizeof(minimalPKCSSigner),
5104 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5105 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
5106 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
5107 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5108 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
5109 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5110 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5111 if (buf)
5113 info = (CMSG_SIGNER_INFO *)buf;
5114 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5115 info->dwVersion);
5116 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5117 "Unexpected size %d\n", info->Issuer.cbData);
5118 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5119 info->Issuer.cbData), "Unexpected value\n");
5120 ok(info->SerialNumber.cbData == sizeof(serialNum),
5121 "Unexpected size %d\n", info->SerialNumber.cbData);
5122 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5123 "Unexpected value\n");
5124 LocalFree(buf);
5126 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5127 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
5128 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5129 if (buf)
5131 info = (CMSG_SIGNER_INFO *)buf;
5132 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5133 info->dwVersion);
5134 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5135 "Unexpected size %d\n", info->Issuer.cbData);
5136 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5137 info->Issuer.cbData), "Unexpected value\n");
5138 ok(info->SerialNumber.cbData == sizeof(serialNum),
5139 "Unexpected size %d\n", info->SerialNumber.cbData);
5140 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5141 "Unexpected value\n");
5142 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5143 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5144 LocalFree(buf);
5146 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5147 PKCSSignerWithHashAndEncryptionAlgo,
5148 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
5149 NULL, (BYTE *)&buf, &size);
5150 if (buf)
5152 info = (CMSG_SIGNER_INFO *)buf;
5153 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5154 info->dwVersion);
5155 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5156 "Unexpected size %d\n", info->Issuer.cbData);
5157 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5158 info->Issuer.cbData), "Unexpected value\n");
5159 ok(info->SerialNumber.cbData == sizeof(serialNum),
5160 "Unexpected size %d\n", info->SerialNumber.cbData);
5161 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5162 "Unexpected value\n");
5163 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5164 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5165 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5166 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5167 LocalFree(buf);
5169 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5170 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
5171 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5172 if (buf)
5174 info = (CMSG_SIGNER_INFO *)buf;
5175 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5176 info->dwVersion);
5177 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5178 "Unexpected size %d\n", info->Issuer.cbData);
5179 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5180 info->Issuer.cbData), "Unexpected value\n");
5181 ok(info->SerialNumber.cbData == sizeof(serialNum),
5182 "Unexpected size %d\n", info->SerialNumber.cbData);
5183 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5184 "Unexpected value\n");
5185 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5186 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5187 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5188 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5189 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
5190 info->EncryptedHash.cbData);
5191 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
5192 "Unexpected value\n");
5193 LocalFree(buf);
5195 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5196 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
5197 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5198 if (buf)
5200 info = (CMSG_SIGNER_INFO *)buf;
5201 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
5202 info->AuthAttrs.cAttr);
5203 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
5204 "Expected %s, got %s\n", szOID_COMMON_NAME,
5205 info->AuthAttrs.rgAttr[0].pszObjId);
5206 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
5207 info->AuthAttrs.rgAttr[0].cValue);
5208 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
5209 sizeof(encodedCommonName), "Unexpected size %d\n",
5210 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
5211 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
5212 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
5213 LocalFree(buf);
5217 /* Free *pInfo with HeapFree */
5218 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
5220 BOOL ret;
5221 DWORD size = 0;
5222 HCRYPTKEY key;
5224 /* This crashes
5225 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
5227 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
5228 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5229 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5230 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
5231 &size);
5232 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5233 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5234 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
5235 NULL, &size);
5236 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5237 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5238 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5239 0, NULL, NULL, &size);
5240 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5241 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5242 /* Test with no key */
5243 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5244 0, NULL, NULL, &size);
5245 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
5246 GetLastError());
5247 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
5248 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
5249 if (ret)
5251 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
5252 NULL, 0, NULL, NULL, &size);
5253 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
5254 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
5255 if (*pInfo)
5257 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
5258 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
5259 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
5260 GetLastError());
5261 if (ret)
5263 /* By default (we passed NULL as the OID) the OID is
5264 * szOID_RSA_RSA.
5266 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
5267 "Expected %s, got %s\n", szOID_RSA_RSA,
5268 (*pInfo)->Algorithm.pszObjId);
5274 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
5275 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
5276 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
5277 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5278 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5279 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5280 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
5281 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
5282 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5283 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5284 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5285 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5286 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
5287 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
5288 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
5289 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
5290 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
5291 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
5292 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
5293 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
5294 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
5295 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
5296 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
5297 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
5298 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
5300 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
5302 BOOL ret;
5303 HCRYPTKEY key;
5304 PCCERT_CONTEXT context;
5306 /* These crash
5307 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
5308 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
5309 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
5310 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5311 NULL);
5313 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
5314 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5315 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5316 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
5317 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5318 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5319 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
5320 &key);
5321 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5322 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5323 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5324 &key);
5325 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5326 CryptDestroyKey(key);
5328 /* Test importing a public key from a certificate context */
5329 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
5330 sizeof(expiredCert));
5331 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
5332 GetLastError());
5333 if (context)
5335 ok(!strcmp(szOID_RSA_RSA,
5336 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
5337 "Expected %s, got %s\n", szOID_RSA_RSA,
5338 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
5339 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
5340 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
5341 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5342 CryptDestroyKey(key);
5343 CertFreeCertificateContext(context);
5347 static const char cspName[] = "WineCryptTemp";
5349 static void testPortPublicKeyInfo(void)
5351 HCRYPTPROV csp;
5352 BOOL ret;
5353 PCERT_PUBLIC_KEY_INFO info = NULL;
5355 /* Just in case a previous run failed, delete this thing */
5356 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5357 CRYPT_DELETEKEYSET);
5358 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5359 CRYPT_NEWKEYSET);
5361 testExportPublicKey(csp, &info);
5362 testImportPublicKey(csp, info);
5364 HeapFree(GetProcessHeap(), 0, info);
5365 CryptReleaseContext(csp, 0);
5366 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5367 CRYPT_DELETEKEYSET);
5370 START_TEST(encode)
5372 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
5373 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
5374 DWORD i;
5376 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
5378 test_encodeInt(encodings[i]);
5379 test_decodeInt(encodings[i]);
5380 test_encodeEnumerated(encodings[i]);
5381 test_decodeEnumerated(encodings[i]);
5382 test_encodeFiletime(encodings[i]);
5383 test_decodeFiletime(encodings[i]);
5384 test_encodeName(encodings[i]);
5385 test_decodeName(encodings[i]);
5386 test_encodeUnicodeName(encodings[i]);
5387 test_decodeUnicodeName(encodings[i]);
5388 test_encodeNameValue(encodings[i]);
5389 test_decodeNameValue(encodings[i]);
5390 test_encodeUnicodeNameValue(encodings[i]);
5391 test_decodeUnicodeNameValue(encodings[i]);
5392 test_encodeAltName(encodings[i]);
5393 test_decodeAltName(encodings[i]);
5394 test_encodeOctets(encodings[i]);
5395 test_decodeOctets(encodings[i]);
5396 test_encodeBits(encodings[i]);
5397 test_decodeBits(encodings[i]);
5398 test_encodeBasicConstraints(encodings[i]);
5399 test_decodeBasicConstraints(encodings[i]);
5400 test_encodeRsaPublicKey(encodings[i]);
5401 test_decodeRsaPublicKey(encodings[i]);
5402 test_encodeSequenceOfAny(encodings[i]);
5403 test_decodeSequenceOfAny(encodings[i]);
5404 test_encodeExtensions(encodings[i]);
5405 test_decodeExtensions(encodings[i]);
5406 test_encodePublicKeyInfo(encodings[i]);
5407 test_decodePublicKeyInfo(encodings[i]);
5408 test_encodeCertToBeSigned(encodings[i]);
5409 test_decodeCertToBeSigned(encodings[i]);
5410 test_encodeCert(encodings[i]);
5411 test_decodeCert(encodings[i]);
5412 test_encodeCRLDistPoints(encodings[i]);
5413 test_decodeCRLDistPoints(encodings[i]);
5414 test_encodeCRLIssuingDistPoint(encodings[i]);
5415 test_decodeCRLIssuingDistPoint(encodings[i]);
5416 test_encodeCRLToBeSigned(encodings[i]);
5417 test_decodeCRLToBeSigned(encodings[i]);
5418 test_encodeEnhancedKeyUsage(encodings[i]);
5419 test_decodeEnhancedKeyUsage(encodings[i]);
5420 test_encodeAuthorityKeyId(encodings[i]);
5421 test_decodeAuthorityKeyId(encodings[i]);
5422 test_encodeAuthorityKeyId2(encodings[i]);
5423 test_decodeAuthorityKeyId2(encodings[i]);
5424 test_encodePKCSContentInfo(encodings[i]);
5425 test_decodePKCSContentInfo(encodings[i]);
5426 test_encodePKCSAttribute(encodings[i]);
5427 test_decodePKCSAttribute(encodings[i]);
5428 test_encodePKCSAttributes(encodings[i]);
5429 test_decodePKCSAttributes(encodings[i]);
5430 test_encodePKCSSignerInfo(encodings[i]);
5431 test_decodePKCSSignerInfo(encodings[i]);
5433 testPortPublicKeyInfo();