push 0c258732cb75565633c2f709ca58b227c9f8ae60
[wine/hacks.git] / dlls / crypt32 / tests / encode.c
blob9b63455240f56c1189ae7fb4cae545bdb9bb2790
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 };
1294 static const unsigned char encodedCommonName[] = {
1295 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1296 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1297 static const BYTE encodedDirectoryName[] = {
1298 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1299 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1301 static void test_encodeAltName(DWORD dwEncoding)
1303 CERT_ALT_NAME_INFO info = { 0 };
1304 CERT_ALT_NAME_ENTRY entry = { 0 };
1305 BYTE *buf = NULL;
1306 DWORD size = 0;
1307 BOOL ret;
1308 char oid[] = "1.2.3";
1310 /* Test with empty info */
1311 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1312 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1313 if (buf)
1315 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1316 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1317 LocalFree(buf);
1319 /* Test with an empty entry */
1320 info.cAltEntry = 1;
1321 info.rgAltEntry = &entry;
1322 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1323 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1324 ok(!ret && GetLastError() == E_INVALIDARG,
1325 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1326 /* Test with an empty pointer */
1327 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1328 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1329 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1330 if (buf)
1332 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1333 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1334 LocalFree(buf);
1336 /* Test with a real URL */
1337 U(entry).pwszURL = (LPWSTR)url;
1338 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1339 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1340 if (buf)
1342 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1343 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1344 LocalFree(buf);
1346 /* Now with the URL containing an invalid IA5 char */
1347 U(entry).pwszURL = (LPWSTR)nihongoURL;
1348 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1349 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1350 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1351 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1352 /* The first invalid character is at index 7 */
1353 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1354 "Expected invalid char at index 7, got %d\n",
1355 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1356 /* Now with the URL missing a scheme */
1357 U(entry).pwszURL = (LPWSTR)dnsName;
1358 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1359 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1360 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1361 if (buf)
1363 /* This succeeds, but it shouldn't, so don't worry about conforming */
1364 LocalFree(buf);
1366 /* Now with a DNS name */
1367 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1368 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1369 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1370 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1371 if (buf)
1373 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1374 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1375 LocalFree(buf);
1377 /* Test with an IP address */
1378 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1379 U(entry).IPAddress.cbData = sizeof(localhost);
1380 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1381 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1382 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1383 if (buf)
1385 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1386 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1387 LocalFree(buf);
1389 /* Test with OID */
1390 entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1391 U(entry).pszRegisteredID = oid;
1392 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1393 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1394 if (buf)
1396 ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1397 ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1398 LocalFree(buf);
1400 /* Test with directory name */
1401 entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1402 U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1403 U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1404 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1405 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1406 if (buf)
1408 ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1409 ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1410 LocalFree(buf);
1414 static void test_decodeAltName(DWORD dwEncoding)
1416 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1417 0x00, 0x00, 0x01 };
1418 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1419 0x01 };
1420 BOOL ret;
1421 BYTE *buf = NULL;
1422 DWORD bufSize = 0;
1423 CERT_ALT_NAME_INFO *info;
1425 /* Test some bogus ones first */
1426 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1427 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1428 NULL, (BYTE *)&buf, &bufSize);
1429 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1430 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1431 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1432 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1433 &bufSize);
1434 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1435 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1436 /* Now expected cases */
1437 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1438 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1439 &bufSize);
1440 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1441 if (buf)
1443 info = (CERT_ALT_NAME_INFO *)buf;
1445 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1446 info->cAltEntry);
1447 LocalFree(buf);
1449 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1450 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1451 &bufSize);
1452 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1453 if (buf)
1455 info = (CERT_ALT_NAME_INFO *)buf;
1457 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1458 info->cAltEntry);
1459 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1460 "Expected CERT_ALT_NAME_URL, got %d\n",
1461 info->rgAltEntry[0].dwAltNameChoice);
1462 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1463 "Expected empty URL\n");
1464 LocalFree(buf);
1466 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1467 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1468 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1469 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1470 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1471 &bufSize);
1472 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1473 if (buf)
1475 info = (CERT_ALT_NAME_INFO *)buf;
1477 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1478 info->cAltEntry);
1479 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1480 "Expected CERT_ALT_NAME_URL, got %d\n",
1481 info->rgAltEntry[0].dwAltNameChoice);
1482 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1483 LocalFree(buf);
1485 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1486 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1487 &bufSize);
1488 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1489 if (buf)
1491 info = (CERT_ALT_NAME_INFO *)buf;
1493 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1494 info->cAltEntry);
1495 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1496 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1497 info->rgAltEntry[0].dwAltNameChoice);
1498 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1499 "Unexpected DNS name\n");
1500 LocalFree(buf);
1502 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1503 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1504 &bufSize);
1505 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1506 if (buf)
1508 info = (CERT_ALT_NAME_INFO *)buf;
1510 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1511 info->cAltEntry);
1512 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1513 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1514 info->rgAltEntry[0].dwAltNameChoice);
1515 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1516 "Unexpected IP address length %d\n",
1517 U(info->rgAltEntry[0]).IPAddress.cbData);
1518 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1519 sizeof(localhost)), "Unexpected IP address value\n");
1520 LocalFree(buf);
1522 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1523 sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1524 &bufSize);
1525 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1526 if (buf)
1528 info = (CERT_ALT_NAME_INFO *)buf;
1530 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1531 info->cAltEntry);
1532 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1533 "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1534 info->rgAltEntry[0].dwAltNameChoice);
1535 ok(!strcmp(info->rgAltEntry[0].pszRegisteredID, "1.2.3"),
1536 "Expected OID 1.2.3, got %s\n", info->rgAltEntry[0].pszRegisteredID);
1537 LocalFree(buf);
1539 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1540 encodedDirectoryName, sizeof(encodedDirectoryName),
1541 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1542 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1543 if (buf)
1545 info = (CERT_ALT_NAME_INFO *)buf;
1547 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1548 info->cAltEntry);
1549 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1550 "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1551 info->rgAltEntry[0].dwAltNameChoice);
1552 ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1553 sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1554 U(info->rgAltEntry[0]).DirectoryName.cbData);
1555 ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1556 encodedCommonName, sizeof(encodedCommonName)),
1557 "Unexpected directory name value\n");
1558 LocalFree(buf);
1562 struct UnicodeExpectedError
1564 DWORD valueType;
1565 LPCWSTR str;
1566 DWORD errorIndex;
1567 DWORD error;
1570 static const WCHAR oneW[] = { '1',0 };
1571 static const WCHAR aW[] = { 'a',0 };
1572 static const WCHAR quoteW[] = { '"', 0 };
1574 static struct UnicodeExpectedError unicodeErrors[] = {
1575 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1576 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1577 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1578 { 14, oneW, 0, CRYPT_E_ASN1_CHOICE },
1579 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1580 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1581 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1584 struct UnicodeExpectedResult
1586 DWORD valueType;
1587 LPCWSTR str;
1588 CRYPT_DATA_BLOB encoded;
1591 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1592 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1593 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1594 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1595 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1596 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1597 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1598 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1599 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1600 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1601 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1602 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1603 0x5b };
1604 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1605 0x6f,0x5b };
1606 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1607 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1608 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1609 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1611 static struct UnicodeExpectedResult unicodeResults[] = {
1612 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1613 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1614 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1615 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1616 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1617 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1618 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1619 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1620 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1621 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1622 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1623 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1624 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1627 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1628 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1629 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1632 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1634 BYTE *buf = NULL;
1635 DWORD size = 0, i;
1636 BOOL ret;
1637 CERT_NAME_VALUE value;
1639 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1640 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1641 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1642 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1643 /* Have to have a string of some sort */
1644 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1645 value.Value.pbData = NULL;
1646 value.Value.cbData = 0;
1647 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1648 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1649 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1650 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1651 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1652 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1653 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1654 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1655 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1656 value.dwValueType = CERT_RDN_ANY_TYPE;
1657 value.Value.pbData = (LPBYTE)oneW;
1658 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1659 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1660 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1661 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1662 value.Value.cbData = sizeof(oneW);
1663 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1664 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1665 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1666 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1667 /* An encoded string with specified length isn't good enough either */
1668 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1669 value.Value.pbData = oneUniversal;
1670 value.Value.cbData = sizeof(oneUniversal);
1671 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1672 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1673 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1674 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1675 /* More failure checking */
1676 value.Value.cbData = 0;
1677 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1679 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1680 value.dwValueType = unicodeErrors[i].valueType;
1681 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1682 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1683 ok(!ret && GetLastError() == unicodeErrors[i].error,
1684 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1685 unicodeErrors[i].error, GetLastError());
1686 ok(size == unicodeErrors[i].errorIndex,
1687 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1688 size);
1690 /* cbData can be zero if the string is NULL-terminated */
1691 value.Value.cbData = 0;
1692 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1694 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1695 value.dwValueType = unicodeResults[i].valueType;
1696 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1697 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1698 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1699 if (buf)
1701 ok(size == unicodeResults[i].encoded.cbData,
1702 "Value type %d: expected size %d, got %d\n",
1703 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1704 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1705 "Value type %d: unexpected value\n", value.dwValueType);
1706 LocalFree(buf);
1709 /* These "encode," but they do so by truncating each unicode character
1710 * rather than properly encoding it. Kept separate from the proper results,
1711 * because the encoded forms won't decode to their original strings.
1713 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1715 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1716 value.dwValueType = unicodeWeirdness[i].valueType;
1717 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1718 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1719 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1720 if (buf)
1722 ok(size == unicodeWeirdness[i].encoded.cbData,
1723 "Value type %d: expected size %d, got %d\n",
1724 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1725 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1726 "Value type %d: unexpected value\n", value.dwValueType);
1727 LocalFree(buf);
1732 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1734 if (n <= 0) return 0;
1735 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1736 return *str1 - *str2;
1739 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1741 DWORD i;
1743 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1745 BYTE *buf = NULL;
1746 BOOL ret;
1747 DWORD size = 0;
1749 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1750 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1751 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1752 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1753 if (ret && buf)
1755 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1757 ok(value->dwValueType == unicodeResults[i].valueType,
1758 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1759 value->dwValueType);
1760 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1761 value->Value.cbData / sizeof(WCHAR)),
1762 "Unexpected decoded value for index %d (value type %d)\n", i,
1763 unicodeResults[i].valueType);
1764 LocalFree(buf);
1769 struct encodedOctets
1771 const BYTE *val;
1772 const BYTE *encoded;
1775 static const unsigned char bin46[] = { 'h','i',0 };
1776 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1777 static const unsigned char bin48[] = {
1778 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1779 static const unsigned char bin49[] = {
1780 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1781 static const unsigned char bin50[] = { 0 };
1782 static const unsigned char bin51[] = { 0x04,0x00,0 };
1784 static const struct encodedOctets octets[] = {
1785 { bin46, bin47 },
1786 { bin48, bin49 },
1787 { bin50, bin51 },
1790 static void test_encodeOctets(DWORD dwEncoding)
1792 CRYPT_DATA_BLOB blob;
1793 DWORD i;
1795 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1797 BYTE *buf = NULL;
1798 BOOL ret;
1799 DWORD bufSize = 0;
1801 blob.cbData = strlen((const char*)octets[i].val);
1802 blob.pbData = (BYTE*)octets[i].val;
1803 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1804 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1805 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1806 if (buf)
1808 ok(buf[0] == 4,
1809 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1810 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1811 buf[1], octets[i].encoded[1]);
1812 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1813 octets[i].encoded[1] + 1), "Got unexpected value\n");
1814 LocalFree(buf);
1819 static void test_decodeOctets(DWORD dwEncoding)
1821 DWORD i;
1823 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1825 BYTE *buf = NULL;
1826 BOOL ret;
1827 DWORD bufSize = 0;
1829 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1830 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1831 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1832 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1833 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1834 "Expected size >= %d, got %d\n",
1835 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1836 ok(buf != NULL, "Expected allocated buffer\n");
1837 if (buf)
1839 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1841 if (blob->cbData)
1842 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1843 "Unexpected value\n");
1844 LocalFree(buf);
1849 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1851 struct encodedBits
1853 DWORD cUnusedBits;
1854 const BYTE *encoded;
1855 DWORD cbDecoded;
1856 const BYTE *decoded;
1859 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1860 static const unsigned char bin53[] = { 0xff,0xff };
1861 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1862 static const unsigned char bin55[] = { 0xff,0xfe };
1863 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1864 static const unsigned char bin57[] = { 0xfe };
1865 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1867 static const struct encodedBits bits[] = {
1868 /* normal test cases */
1869 { 0, bin52, 2, bin53 },
1870 { 1, bin54, 2, bin55 },
1871 /* strange test case, showing cUnusedBits >= 8 is allowed */
1872 { 9, bin56, 1, bin57 },
1873 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1874 { 17, bin58, 0, NULL },
1877 static void test_encodeBits(DWORD dwEncoding)
1879 DWORD i;
1881 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1883 CRYPT_BIT_BLOB blob;
1884 BOOL ret;
1885 BYTE *buf = NULL;
1886 DWORD bufSize = 0;
1888 blob.cbData = sizeof(bytesToEncode);
1889 blob.pbData = (BYTE *)bytesToEncode;
1890 blob.cUnusedBits = bits[i].cUnusedBits;
1891 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1892 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1893 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1894 if (buf)
1896 ok(bufSize == bits[i].encoded[1] + 2,
1897 "Got unexpected size %d, expected %d\n", bufSize,
1898 bits[i].encoded[1] + 2);
1899 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1900 "Unexpected value\n");
1901 LocalFree(buf);
1906 static void test_decodeBits(DWORD dwEncoding)
1908 static const BYTE ber[] = "\x03\x02\x01\xff";
1909 static const BYTE berDecoded = 0xfe;
1910 DWORD i;
1911 BOOL ret;
1912 BYTE *buf = NULL;
1913 DWORD bufSize = 0;
1915 /* normal cases */
1916 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1918 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1919 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1920 &bufSize);
1921 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1922 if (buf)
1924 CRYPT_BIT_BLOB *blob;
1926 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1927 "Got unexpected size %d\n", bufSize);
1928 blob = (CRYPT_BIT_BLOB *)buf;
1929 ok(blob->cbData == bits[i].cbDecoded,
1930 "Got unexpected length %d, expected %d\n", blob->cbData,
1931 bits[i].cbDecoded);
1932 if (blob->cbData && bits[i].cbDecoded)
1933 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1934 "Unexpected value\n");
1935 LocalFree(buf);
1938 /* special case: check that something that's valid in BER but not in DER
1939 * decodes successfully
1941 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1942 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1943 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1944 if (buf)
1946 CRYPT_BIT_BLOB *blob;
1948 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1949 "Got unexpected size %d\n", bufSize);
1950 blob = (CRYPT_BIT_BLOB *)buf;
1951 ok(blob->cbData == sizeof(berDecoded),
1952 "Got unexpected length %d\n", blob->cbData);
1953 if (blob->cbData)
1954 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1955 LocalFree(buf);
1959 struct Constraints2
1961 CERT_BASIC_CONSTRAINTS2_INFO info;
1962 const BYTE *encoded;
1965 static const unsigned char bin59[] = { 0x30,0x00 };
1966 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1967 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1968 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1969 static const struct Constraints2 constraints2[] = {
1970 /* empty constraints */
1971 { { FALSE, FALSE, 0}, bin59 },
1972 /* can be a CA */
1973 { { TRUE, FALSE, 0}, bin60 },
1974 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1975 * but that's not the case
1977 { { FALSE, TRUE, 0}, bin61 },
1978 /* can be a CA and has path length constraints set */
1979 { { TRUE, TRUE, 1}, bin62 },
1982 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1983 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1984 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1985 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1986 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1987 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1988 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1989 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1990 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1991 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1993 static void test_encodeBasicConstraints(DWORD dwEncoding)
1995 DWORD i, bufSize = 0;
1996 CERT_BASIC_CONSTRAINTS_INFO info;
1997 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1998 (LPBYTE)encodedDomainName };
1999 BOOL ret;
2000 BYTE *buf = NULL;
2002 /* First test with the simpler info2 */
2003 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2005 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2006 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2007 &bufSize);
2008 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2009 if (buf)
2011 ok(bufSize == constraints2[i].encoded[1] + 2,
2012 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2013 bufSize);
2014 ok(!memcmp(buf, constraints2[i].encoded,
2015 constraints2[i].encoded[1] + 2), "Unexpected value\n");
2016 LocalFree(buf);
2019 /* Now test with more complex basic constraints */
2020 info.SubjectType.cbData = 0;
2021 info.fPathLenConstraint = FALSE;
2022 info.cSubtreesConstraint = 0;
2023 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2024 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2025 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2026 if (buf)
2028 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2029 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2030 "Unexpected value\n");
2031 LocalFree(buf);
2033 /* None of the certs I examined had any subtree constraint, but I test one
2034 * anyway just in case.
2036 info.cSubtreesConstraint = 1;
2037 info.rgSubtreesConstraint = &nameBlob;
2038 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2039 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2040 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2041 if (buf)
2043 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2044 ok(!memcmp(buf, constraintWithDomainName,
2045 sizeof(constraintWithDomainName)), "Unexpected value\n");
2046 LocalFree(buf);
2048 /* FIXME: test encoding with subject type. */
2051 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2053 static void test_decodeBasicConstraints(DWORD dwEncoding)
2055 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2056 0xff };
2057 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2058 DWORD i;
2059 BOOL ret;
2060 BYTE *buf = NULL;
2061 DWORD bufSize = 0;
2063 /* First test with simpler info2 */
2064 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2066 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2067 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2068 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2069 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2070 GetLastError());
2071 if (buf)
2073 CERT_BASIC_CONSTRAINTS2_INFO *info =
2074 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2076 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2077 "Unexpected value for item %d\n", i);
2078 LocalFree(buf);
2081 /* Check with the order of encoded elements inverted */
2082 buf = (PBYTE)1;
2083 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2084 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2085 &bufSize);
2086 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2087 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2088 ok(!buf, "Expected buf to be set to NULL\n");
2089 /* Check with a non-DER bool */
2090 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2091 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2092 (BYTE *)&buf, &bufSize);
2093 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2094 if (buf)
2096 CERT_BASIC_CONSTRAINTS2_INFO *info =
2097 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2099 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2100 LocalFree(buf);
2102 /* Check with a non-basic constraints value */
2103 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2104 (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2105 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2106 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2107 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2108 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2109 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2110 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2111 (BYTE *)&buf, &bufSize);
2112 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2113 if (buf)
2115 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2117 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2118 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2119 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2120 LocalFree(buf);
2122 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2123 constraintWithDomainName, sizeof(constraintWithDomainName),
2124 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2125 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2126 if (buf)
2128 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2130 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2131 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2132 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2133 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2135 ok(info->rgSubtreesConstraint[0].cbData ==
2136 sizeof(encodedDomainName), "Wrong size %d\n",
2137 info->rgSubtreesConstraint[0].cbData);
2138 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2139 sizeof(encodedDomainName)), "Unexpected value\n");
2141 LocalFree(buf);
2145 /* These are terrible public keys of course, I'm just testing encoding */
2146 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2147 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2148 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2149 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2150 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2151 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2152 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2153 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2155 struct EncodedRSAPubKey
2157 const BYTE *modulus;
2158 size_t modulusLen;
2159 const BYTE *encoded;
2160 size_t decodedModulusLen;
2163 struct EncodedRSAPubKey rsaPubKeys[] = {
2164 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2165 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2166 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2167 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2170 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2172 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2173 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2174 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2175 BOOL ret;
2176 BYTE *buf = NULL;
2177 DWORD bufSize = 0, i;
2179 /* Try with a bogus blob type */
2180 hdr->bType = 2;
2181 hdr->bVersion = CUR_BLOB_VERSION;
2182 hdr->reserved = 0;
2183 hdr->aiKeyAlg = CALG_RSA_KEYX;
2184 rsaPubKey->magic = 0x31415352;
2185 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2186 rsaPubKey->pubexp = 65537;
2187 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2188 sizeof(modulus1));
2190 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2191 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2192 &bufSize);
2193 ok(!ret && GetLastError() == E_INVALIDARG,
2194 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2195 /* Now with a bogus reserved field */
2196 hdr->bType = PUBLICKEYBLOB;
2197 hdr->reserved = 1;
2198 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2199 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2200 &bufSize);
2201 if (buf)
2203 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2204 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2205 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2206 LocalFree(buf);
2208 /* Now with a bogus blob version */
2209 hdr->reserved = 0;
2210 hdr->bVersion = 0;
2211 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2212 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2213 &bufSize);
2214 if (buf)
2216 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2217 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2218 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2219 LocalFree(buf);
2221 /* And with a bogus alg ID */
2222 hdr->bVersion = CUR_BLOB_VERSION;
2223 hdr->aiKeyAlg = CALG_DES;
2224 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2225 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2226 &bufSize);
2227 if (buf)
2229 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2230 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2231 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2232 LocalFree(buf);
2234 /* Check a couple of RSA-related OIDs */
2235 hdr->aiKeyAlg = CALG_RSA_KEYX;
2236 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2237 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2238 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2239 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2240 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2241 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2242 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2243 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2244 /* Finally, all valid */
2245 hdr->aiKeyAlg = CALG_RSA_KEYX;
2246 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2248 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2249 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2250 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2251 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2252 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2253 if (buf)
2255 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2256 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2257 bufSize);
2258 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2259 "Unexpected value\n");
2260 LocalFree(buf);
2265 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2267 DWORD i;
2268 LPBYTE buf = NULL;
2269 DWORD bufSize = 0;
2270 BOOL ret;
2272 /* Try with a bad length */
2273 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2274 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2275 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2276 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2277 "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2278 /* Try with a couple of RSA-related OIDs */
2279 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2280 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2281 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2282 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2283 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2284 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2285 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2286 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2287 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2288 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2289 /* Now try success cases */
2290 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2292 bufSize = 0;
2293 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2294 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2295 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2296 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2297 if (buf)
2299 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2300 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2302 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2303 rsaPubKeys[i].decodedModulusLen,
2304 "Wrong size %d\n", bufSize);
2305 ok(hdr->bType == PUBLICKEYBLOB,
2306 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2307 hdr->bType);
2308 ok(hdr->bVersion == CUR_BLOB_VERSION,
2309 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2310 CUR_BLOB_VERSION, hdr->bVersion);
2311 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2312 hdr->reserved);
2313 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2314 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2315 ok(rsaPubKey->magic == 0x31415352,
2316 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2317 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2318 "Wrong bit len %d\n", rsaPubKey->bitlen);
2319 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2320 rsaPubKey->pubexp);
2321 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2322 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2323 "Unexpected modulus\n");
2324 LocalFree(buf);
2329 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2330 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2331 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2333 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2334 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2335 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2336 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2338 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2340 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2341 CRYPT_SEQUENCE_OF_ANY seq;
2342 DWORD i;
2343 BOOL ret;
2344 BYTE *buf = NULL;
2345 DWORD bufSize = 0;
2347 /* Encode a homogenous sequence */
2348 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2350 blobs[i].cbData = ints[i].encoded[1] + 2;
2351 blobs[i].pbData = (BYTE *)ints[i].encoded;
2353 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2354 seq.rgValue = blobs;
2356 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2357 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2358 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2359 if (buf)
2361 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2362 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2363 LocalFree(buf);
2365 /* Change the type of the first element in the sequence, and give it
2366 * another go
2368 blobs[0].cbData = times[0].encodedTime[1] + 2;
2369 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2370 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2371 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2372 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2373 if (buf)
2375 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2376 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2377 "Unexpected value\n");
2378 LocalFree(buf);
2382 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2384 BOOL ret;
2385 BYTE *buf = NULL;
2386 DWORD bufSize = 0;
2388 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2389 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2390 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2391 if (buf)
2393 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2394 DWORD i;
2396 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2397 "Wrong elements %d\n", seq->cValue);
2398 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2400 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2401 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2402 seq->rgValue[i].cbData);
2403 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2404 ints[i].encoded[1] + 2), "Unexpected value\n");
2406 LocalFree(buf);
2408 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2409 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2410 &bufSize);
2411 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2412 if (buf)
2414 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2416 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2417 "Wrong elements %d\n", seq->cValue);
2418 /* Just check the first element since it's all that changed */
2419 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2420 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2421 seq->rgValue[0].cbData);
2422 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2423 times[0].encodedTime[1] + 2), "Unexpected value\n");
2424 LocalFree(buf);
2428 struct encodedExtensions
2430 CERT_EXTENSIONS exts;
2431 const BYTE *encoded;
2434 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2435 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2436 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2437 static CERT_EXTENSION criticalExt =
2438 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2439 static CERT_EXTENSION nonCriticalExt =
2440 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2442 static const BYTE ext0[] = { 0x30,0x00 };
2443 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2444 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2445 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2446 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2448 static const struct encodedExtensions exts[] = {
2449 { { 0, NULL }, ext0 },
2450 { { 1, &criticalExt }, ext1 },
2451 { { 1, &nonCriticalExt }, ext2 },
2454 static void test_encodeExtensions(DWORD dwEncoding)
2456 DWORD i;
2458 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2460 BOOL ret;
2461 BYTE *buf = NULL;
2462 DWORD bufSize = 0;
2464 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2465 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2466 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2467 if (buf)
2469 ok(bufSize == exts[i].encoded[1] + 2,
2470 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2471 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2472 "Unexpected value\n");
2473 LocalFree(buf);
2478 static void test_decodeExtensions(DWORD dwEncoding)
2480 DWORD i;
2482 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2484 BOOL ret;
2485 BYTE *buf = NULL;
2486 DWORD bufSize = 0;
2488 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2489 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2490 NULL, (BYTE *)&buf, &bufSize);
2491 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2492 if (buf)
2494 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2495 DWORD j;
2497 ok(ext->cExtension == exts[i].exts.cExtension,
2498 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2499 ext->cExtension);
2500 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2502 ok(!strcmp(ext->rgExtension[j].pszObjId,
2503 exts[i].exts.rgExtension[j].pszObjId),
2504 "Expected OID %s, got %s\n",
2505 exts[i].exts.rgExtension[j].pszObjId,
2506 ext->rgExtension[j].pszObjId);
2507 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2508 exts[i].exts.rgExtension[j].Value.pbData,
2509 exts[i].exts.rgExtension[j].Value.cbData),
2510 "Unexpected value\n");
2512 LocalFree(buf);
2517 /* MS encodes public key info with a NULL if the algorithm identifier's
2518 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2519 * it encodes them by omitting the algorithm parameters. This latter approach
2520 * seems more correct, so accept either form.
2522 struct encodedPublicKey
2524 CERT_PUBLIC_KEY_INFO info;
2525 const BYTE *encoded;
2526 const BYTE *encodedNoNull;
2527 CERT_PUBLIC_KEY_INFO decoded;
2530 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2531 0xe, 0xf };
2532 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2534 static const unsigned char bin64[] = {
2535 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2536 static const unsigned char bin65[] = {
2537 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2538 static const unsigned char bin66[] = {
2539 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2540 static const unsigned char bin67[] = {
2541 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2542 static const unsigned char bin68[] = {
2543 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2544 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2545 static const unsigned char bin69[] = {
2546 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2547 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2548 static const unsigned char bin70[] = {
2549 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2550 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2551 0x0f};
2552 static const unsigned char bin71[] = {
2553 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2554 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2555 0x0f};
2556 static unsigned char bin72[] = { 0x05,0x00};
2558 static CHAR oid_bogus[] = "1.2.3",
2559 oid_rsa[] = szOID_RSA;
2561 static const struct encodedPublicKey pubKeys[] = {
2562 /* with a bogus OID */
2563 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2564 bin64, bin65,
2565 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2566 /* some normal keys */
2567 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2568 bin66, bin67,
2569 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2570 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2571 bin68, bin69,
2572 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2573 /* with add'l parameters--note they must be DER-encoded */
2574 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2575 (BYTE *)aKey, 0 } },
2576 bin70, bin71,
2577 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2578 (BYTE *)aKey, 0 } } },
2581 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2583 DWORD i;
2585 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2587 BOOL ret;
2588 BYTE *buf = NULL;
2589 DWORD bufSize = 0;
2591 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2592 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2593 &bufSize);
2594 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2595 if (buf)
2597 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2598 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2599 "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2600 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2601 if (bufSize == pubKeys[i].encoded[1] + 2)
2602 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2603 "Unexpected value\n");
2604 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2605 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2606 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2607 LocalFree(buf);
2612 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2613 const CERT_PUBLIC_KEY_INFO *got)
2615 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2616 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2617 got->Algorithm.pszObjId);
2618 ok(expected->Algorithm.Parameters.cbData ==
2619 got->Algorithm.Parameters.cbData,
2620 "Expected parameters of %d bytes, got %d\n",
2621 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2622 if (expected->Algorithm.Parameters.cbData)
2623 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2624 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2625 "Unexpected algorithm parameters\n");
2626 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2627 "Expected public key of %d bytes, got %d\n",
2628 expected->PublicKey.cbData, got->PublicKey.cbData);
2629 if (expected->PublicKey.cbData)
2630 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2631 got->PublicKey.cbData), "Unexpected public key value\n");
2634 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2636 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2637 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2638 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2639 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2640 DWORD i;
2641 BOOL ret;
2642 BYTE *buf = NULL;
2643 DWORD bufSize = 0;
2645 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2647 /* The NULL form decodes to the decoded member */
2648 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2649 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2650 NULL, (BYTE *)&buf, &bufSize);
2651 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2652 if (buf)
2654 comparePublicKeyInfo(&pubKeys[i].decoded,
2655 (CERT_PUBLIC_KEY_INFO *)buf);
2656 LocalFree(buf);
2658 /* The non-NULL form decodes to the original */
2659 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2660 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2661 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2662 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2663 if (buf)
2665 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2666 LocalFree(buf);
2669 /* Test with bogus (not valid DER) parameters */
2670 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2671 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2672 NULL, (BYTE *)&buf, &bufSize);
2673 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2674 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2677 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2678 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2679 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2680 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2681 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2682 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2683 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2684 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2685 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2686 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2687 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2688 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2689 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2690 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2691 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2692 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2693 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2694 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2695 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2696 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2697 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2698 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2699 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2700 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2701 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2702 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2703 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2704 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2705 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2706 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2707 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2708 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2709 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2710 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2711 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2712 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2713 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2714 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2715 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2716 static const BYTE v1CertWithPubKey[] = {
2717 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2718 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2719 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2720 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2721 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2722 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2723 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2724 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2725 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2726 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2727 0x01,0x01 };
2728 static const BYTE v1CertWithPubKeyNoNull[] = {
2729 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2730 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2731 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2732 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2733 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2734 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2735 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2736 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2737 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2738 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2739 static const BYTE v1CertWithSubjectKeyId[] = {
2740 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2741 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2742 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2743 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2744 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2745 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2746 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2747 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2748 0x4c,0x61,0x6e,0x67,0x00 };
2750 static const BYTE serialNum[] = { 0x01 };
2752 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2754 BOOL ret;
2755 BYTE *buf = NULL;
2756 DWORD size = 0;
2757 CERT_INFO info = { 0 };
2758 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2759 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2760 CERT_EXTENSION ext;
2762 /* Test with NULL pvStructInfo */
2763 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2764 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2765 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2766 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2767 /* Test with a V1 cert */
2768 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2769 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2770 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2771 if (buf)
2773 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2774 v1Cert[1] + 2, size);
2775 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2776 LocalFree(buf);
2778 /* Test v2 cert */
2779 info.dwVersion = CERT_V2;
2780 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2781 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2782 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2783 if (buf)
2785 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2786 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2787 LocalFree(buf);
2789 /* Test v3 cert */
2790 info.dwVersion = CERT_V3;
2791 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2792 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2793 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2794 if (buf)
2796 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2797 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2798 LocalFree(buf);
2800 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2801 * API doesn't prevent it)
2803 info.dwVersion = CERT_V1;
2804 info.cExtension = 1;
2805 info.rgExtension = &criticalExt;
2806 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2807 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2808 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2809 if (buf)
2811 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2812 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2813 LocalFree(buf);
2815 /* test v1 cert with a serial number */
2816 info.SerialNumber.cbData = sizeof(serialNum);
2817 info.SerialNumber.pbData = (BYTE *)serialNum;
2818 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2819 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2820 if (buf)
2822 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2823 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2824 LocalFree(buf);
2826 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2827 info.Issuer.cbData = sizeof(encodedCommonName);
2828 info.Issuer.pbData = (BYTE *)encodedCommonName;
2829 info.Subject.cbData = sizeof(encodedCommonName);
2830 info.Subject.pbData = (BYTE *)encodedCommonName;
2831 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2832 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2833 if (buf)
2835 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2836 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2837 LocalFree(buf);
2839 /* Add a public key */
2840 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2841 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2842 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2843 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2844 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2845 if (buf)
2847 ok(size == sizeof(v1CertWithPubKey) ||
2848 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2849 if (size == sizeof(v1CertWithPubKey))
2850 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2851 else if (size == sizeof(v1CertWithPubKeyNoNull))
2852 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2853 "Got unexpected value\n");
2854 LocalFree(buf);
2856 /* Remove the public key, and add a subject key identifier extension */
2857 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2858 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2859 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2860 ext.pszObjId = oid_subject_key_identifier;
2861 ext.fCritical = FALSE;
2862 ext.Value.cbData = sizeof(octetCommonNameValue);
2863 ext.Value.pbData = (BYTE *)octetCommonNameValue;
2864 info.cExtension = 1;
2865 info.rgExtension = &ext;
2866 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2867 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2868 if (buf)
2870 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2871 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2872 LocalFree(buf);
2876 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2878 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2879 v1CertWithConstraints, v1CertWithSerial };
2880 BOOL ret;
2881 BYTE *buf = NULL;
2882 DWORD size = 0, i;
2884 /* Test with NULL pbEncoded */
2885 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2886 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2887 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2888 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2889 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2890 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2891 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2892 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2893 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2894 * minimum a cert must have a non-zero serial number, an issuer, and a
2895 * subject.
2897 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2899 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2900 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2901 (BYTE *)&buf, &size);
2902 ok(!ret, "Expected failure\n");
2904 /* Now check with serial number, subject and issuer specified */
2905 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2906 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2907 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2908 if (buf)
2910 CERT_INFO *info = (CERT_INFO *)buf;
2912 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2913 ok(info->SerialNumber.cbData == 1,
2914 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2915 ok(*info->SerialNumber.pbData == *serialNum,
2916 "Expected serial number %d, got %d\n", *serialNum,
2917 *info->SerialNumber.pbData);
2918 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2919 "Wrong size %d\n", info->Issuer.cbData);
2920 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2921 "Unexpected issuer\n");
2922 ok(info->Subject.cbData == sizeof(encodedCommonName),
2923 "Wrong size %d\n", info->Subject.cbData);
2924 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2925 info->Subject.cbData), "Unexpected subject\n");
2926 LocalFree(buf);
2928 /* Check again with pub key specified */
2929 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2930 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
2931 (BYTE *)&buf, &size);
2932 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2933 if (buf)
2935 CERT_INFO *info = (CERT_INFO *)buf;
2937 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2938 ok(info->SerialNumber.cbData == 1,
2939 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2940 ok(*info->SerialNumber.pbData == *serialNum,
2941 "Expected serial number %d, got %d\n", *serialNum,
2942 *info->SerialNumber.pbData);
2943 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2944 "Wrong size %d\n", info->Issuer.cbData);
2945 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2946 "Unexpected issuer\n");
2947 ok(info->Subject.cbData == sizeof(encodedCommonName),
2948 "Wrong size %d\n", info->Subject.cbData);
2949 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2950 info->Subject.cbData), "Unexpected subject\n");
2951 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
2952 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
2953 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
2954 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
2955 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
2956 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
2957 sizeof(aKey)), "Unexpected public key\n");
2958 LocalFree(buf);
2962 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2963 0xe, 0xf };
2965 static const BYTE signedBigCert[] = {
2966 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2967 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2968 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2969 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2970 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2971 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2972 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2973 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2974 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2975 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2976 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2977 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2979 static void test_encodeCert(DWORD dwEncoding)
2981 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2982 * also that bigCert is a NULL-terminated string, so don't count its
2983 * last byte (otherwise the signed cert won't decode.)
2985 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2986 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2987 BOOL ret;
2988 BYTE *buf = NULL;
2989 DWORD bufSize = 0;
2991 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2992 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2993 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2994 if (buf)
2996 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
2997 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2998 LocalFree(buf);
3002 static void test_decodeCert(DWORD dwEncoding)
3004 BOOL ret;
3005 BYTE *buf = NULL;
3006 DWORD size = 0;
3008 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3009 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3010 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3011 if (buf)
3013 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3015 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3016 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3017 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3018 "Unexpected cert\n");
3019 ok(info->Signature.cbData == sizeof(hash),
3020 "Wrong signature size %d\n", info->Signature.cbData);
3021 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3022 "Unexpected signature\n");
3023 LocalFree(buf);
3025 /* A signed cert decodes as a CERT_INFO too */
3026 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3027 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3028 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3029 if (buf)
3031 CERT_INFO *info = (CERT_INFO *)buf;
3033 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3034 ok(info->SerialNumber.cbData == 1,
3035 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3036 ok(*info->SerialNumber.pbData == *serialNum,
3037 "Expected serial number %d, got %d\n", *serialNum,
3038 *info->SerialNumber.pbData);
3039 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3040 "Wrong size %d\n", info->Issuer.cbData);
3041 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3042 "Unexpected issuer\n");
3043 ok(info->Subject.cbData == sizeof(encodedCommonName),
3044 "Wrong size %d\n", info->Subject.cbData);
3045 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3046 info->Subject.cbData), "Unexpected subject\n");
3047 LocalFree(buf);
3051 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3052 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3053 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3054 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3055 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3056 0x00, 0x03 };
3057 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3058 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3059 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3060 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3061 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3062 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3063 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3064 0x2e, 0x6f, 0x72, 0x67 };
3065 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3066 CRL_REASON_AFFILIATION_CHANGED;
3068 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3070 CRL_DIST_POINTS_INFO info = { 0 };
3071 CRL_DIST_POINT point = { { 0 } };
3072 CERT_ALT_NAME_ENTRY entry = { 0 };
3073 BOOL ret;
3074 BYTE *buf = NULL;
3075 DWORD size = 0;
3077 /* Test with an empty info */
3078 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3079 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3080 ok(!ret && GetLastError() == E_INVALIDARG,
3081 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3082 /* Test with one empty dist point */
3083 info.cDistPoint = 1;
3084 info.rgDistPoint = &point;
3085 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3086 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3087 if (buf)
3089 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3090 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3091 LocalFree(buf);
3093 /* A dist point with an invalid name */
3094 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3095 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3096 U(entry).pwszURL = (LPWSTR)nihongoURL;
3097 U(point.DistPointName).FullName.cAltEntry = 1;
3098 U(point.DistPointName).FullName.rgAltEntry = &entry;
3099 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3100 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3101 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3102 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3103 /* The first invalid character is at index 7 */
3104 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3105 "Expected invalid char at index 7, got %d\n",
3106 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3107 /* A dist point with (just) a valid name */
3108 U(entry).pwszURL = (LPWSTR)url;
3109 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3110 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3111 if (buf)
3113 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3114 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3115 LocalFree(buf);
3117 /* A dist point with (just) reason flags */
3118 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3119 point.ReasonFlags.cbData = sizeof(crlReason);
3120 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3121 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3122 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3123 if (buf)
3125 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3126 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3127 LocalFree(buf);
3129 /* A dist point with just an issuer */
3130 point.ReasonFlags.cbData = 0;
3131 point.CRLIssuer.cAltEntry = 1;
3132 point.CRLIssuer.rgAltEntry = &entry;
3133 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3134 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3135 if (buf)
3137 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3138 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3139 LocalFree(buf);
3141 /* A dist point with both a name and an issuer */
3142 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3143 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3144 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3145 if (buf)
3147 ok(size == sizeof(distPointWithUrlAndIssuer),
3148 "Wrong size %d\n", size);
3149 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3150 LocalFree(buf);
3154 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3156 BOOL ret;
3157 BYTE *buf = NULL;
3158 DWORD size = 0;
3159 PCRL_DIST_POINTS_INFO info;
3160 PCRL_DIST_POINT point;
3161 PCERT_ALT_NAME_ENTRY entry;
3163 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3164 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3165 (BYTE *)&buf, &size);
3166 if (ret)
3168 info = (PCRL_DIST_POINTS_INFO)buf;
3169 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3170 "Wrong size %d\n", size);
3171 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3172 info->cDistPoint);
3173 point = info->rgDistPoint;
3174 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3175 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3176 point->DistPointName.dwDistPointNameChoice);
3177 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3178 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3179 LocalFree(buf);
3181 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3182 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3183 (BYTE *)&buf, &size);
3184 if (ret)
3186 info = (PCRL_DIST_POINTS_INFO)buf;
3187 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3188 "Wrong size %d\n", size);
3189 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3190 info->cDistPoint);
3191 point = info->rgDistPoint;
3192 ok(point->DistPointName.dwDistPointNameChoice ==
3193 CRL_DIST_POINT_FULL_NAME,
3194 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3195 point->DistPointName.dwDistPointNameChoice);
3196 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3197 "Expected 1 name entry, got %d\n",
3198 U(point->DistPointName).FullName.cAltEntry);
3199 entry = U(point->DistPointName).FullName.rgAltEntry;
3200 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3201 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3202 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3203 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3204 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3205 LocalFree(buf);
3207 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3208 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3209 NULL, (BYTE *)&buf, &size);
3210 if (ret)
3212 info = (PCRL_DIST_POINTS_INFO)buf;
3213 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3214 "Wrong size %d\n", size);
3215 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3216 info->cDistPoint);
3217 point = info->rgDistPoint;
3218 ok(point->DistPointName.dwDistPointNameChoice ==
3219 CRL_DIST_POINT_NO_NAME,
3220 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3221 point->DistPointName.dwDistPointNameChoice);
3222 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3223 "Expected reason length\n");
3224 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3225 "Unexpected reason\n");
3226 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3227 LocalFree(buf);
3229 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3230 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3231 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3232 if (ret)
3234 info = (PCRL_DIST_POINTS_INFO)buf;
3235 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3236 "Wrong size %d\n", size);
3237 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3238 info->cDistPoint);
3239 point = info->rgDistPoint;
3240 ok(point->DistPointName.dwDistPointNameChoice ==
3241 CRL_DIST_POINT_FULL_NAME,
3242 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3243 point->DistPointName.dwDistPointNameChoice);
3244 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3245 "Expected 1 name entry, got %d\n",
3246 U(point->DistPointName).FullName.cAltEntry);
3247 entry = U(point->DistPointName).FullName.rgAltEntry;
3248 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3249 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3250 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3251 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3252 ok(point->CRLIssuer.cAltEntry == 1,
3253 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3254 entry = point->CRLIssuer.rgAltEntry;
3255 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3256 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3257 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3258 LocalFree(buf);
3262 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3263 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3264 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3265 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3266 0x67 };
3268 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3270 BOOL ret;
3271 BYTE *buf = NULL;
3272 DWORD size = 0;
3273 CRL_ISSUING_DIST_POINT point = { { 0 } };
3274 CERT_ALT_NAME_ENTRY entry;
3276 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3277 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3278 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3280 skip("no X509_ISSUING_DIST_POINT encode support\n");
3281 return;
3283 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3284 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3285 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3286 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3287 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3288 if (buf)
3290 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3291 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3292 LocalFree(buf);
3294 /* nonsensical flags */
3295 point.fOnlyContainsUserCerts = TRUE;
3296 point.fOnlyContainsCACerts = TRUE;
3297 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3298 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3299 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3300 if (buf)
3302 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3303 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3304 LocalFree(buf);
3306 /* unimplemented name type */
3307 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3308 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3309 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3310 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3311 ok(!ret && GetLastError() == E_INVALIDARG,
3312 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3313 /* empty name */
3314 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3315 U(point.DistPointName).FullName.cAltEntry = 0;
3316 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3317 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3318 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3319 if (buf)
3321 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3322 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3323 LocalFree(buf);
3325 /* name with URL entry */
3326 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3327 U(entry).pwszURL = (LPWSTR)url;
3328 U(point.DistPointName).FullName.cAltEntry = 1;
3329 U(point.DistPointName).FullName.rgAltEntry = &entry;
3330 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3331 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3332 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3333 if (buf)
3335 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3336 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3337 LocalFree(buf);
3341 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3342 const CERT_ALT_NAME_ENTRY *got)
3344 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3345 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3346 got->dwAltNameChoice);
3347 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3349 switch (got->dwAltNameChoice)
3351 case CERT_ALT_NAME_RFC822_NAME:
3352 case CERT_ALT_NAME_DNS_NAME:
3353 case CERT_ALT_NAME_EDI_PARTY_NAME:
3354 case CERT_ALT_NAME_URL:
3355 case CERT_ALT_NAME_REGISTERED_ID:
3356 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3357 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
3358 break;
3359 case CERT_ALT_NAME_X400_ADDRESS:
3360 case CERT_ALT_NAME_DIRECTORY_NAME:
3361 case CERT_ALT_NAME_IP_ADDRESS:
3362 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3363 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3364 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3365 U(*got).IPAddress.cbData), "Unexpected value\n");
3366 break;
3371 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3372 const CERT_ALT_NAME_INFO *got)
3374 DWORD i;
3376 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3377 expected->cAltEntry, got->cAltEntry);
3378 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3379 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3382 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3383 const CRL_DIST_POINT_NAME *got)
3385 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3386 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3387 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3388 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3391 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3392 const CRL_ISSUING_DIST_POINT *got)
3394 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3395 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3396 "Unexpected fOnlyContainsUserCerts\n");
3397 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3398 "Unexpected fOnlyContainsCACerts\n");
3399 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3400 "Unexpected reason flags\n");
3401 ok(got->fIndirectCRL == expected->fIndirectCRL,
3402 "Unexpected fIndirectCRL\n");
3405 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3407 BOOL ret;
3408 BYTE *buf = NULL;
3409 DWORD size = 0;
3410 CRL_ISSUING_DIST_POINT point = { { 0 } };
3412 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3413 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3414 (BYTE *)&buf, &size);
3415 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3417 skip("no X509_ISSUING_DIST_POINT decode support\n");
3418 return;
3420 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3421 if (ret)
3423 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3424 LocalFree(buf);
3426 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3427 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3428 (BYTE *)&buf, &size);
3429 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3430 if (ret)
3432 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3433 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3434 LocalFree(buf);
3436 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3437 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3438 (BYTE *)&buf, &size);
3439 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3440 if (ret)
3442 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3443 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3444 U(point.DistPointName).FullName.cAltEntry = 0;
3445 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3446 LocalFree(buf);
3448 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3449 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3450 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3451 if (ret)
3453 CERT_ALT_NAME_ENTRY entry;
3455 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3456 U(entry).pwszURL = (LPWSTR)url;
3457 U(point.DistPointName).FullName.cAltEntry = 1;
3458 U(point.DistPointName).FullName.rgAltEntry = &entry;
3459 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3460 LocalFree(buf);
3464 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3465 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3466 0x30, 0x5a };
3467 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3468 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3469 0x30, 0x30, 0x30, 0x30, 0x5a };
3470 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3471 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3472 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3473 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3474 0x5a };
3475 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3476 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3477 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3478 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3479 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3480 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3481 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3482 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3483 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3484 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3485 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3486 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3487 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3488 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3489 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3490 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3491 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3492 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3493 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3494 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3495 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3496 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3497 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3498 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3499 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3500 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3501 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3502 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3503 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3504 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3505 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3506 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3507 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3508 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3509 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3510 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3511 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3512 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3513 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3514 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3516 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3518 BOOL ret;
3519 BYTE *buf = NULL;
3520 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3521 DWORD size = 0;
3522 CRL_INFO info = { 0 };
3523 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3524 CERT_EXTENSION ext;
3526 /* Test with a V1 CRL */
3527 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3528 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3529 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3530 if (buf)
3532 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3533 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3534 LocalFree(buf);
3536 /* Test v2 CRL */
3537 info.dwVersion = CRL_V2;
3538 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3539 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3540 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3541 if (buf)
3543 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3544 v2CRL[1] + 2, size);
3545 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3546 LocalFree(buf);
3548 /* v1 CRL with a name */
3549 info.dwVersion = CRL_V1;
3550 info.Issuer.cbData = sizeof(encodedCommonName);
3551 info.Issuer.pbData = (BYTE *)encodedCommonName;
3552 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3553 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3554 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3555 if (buf)
3557 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3558 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3559 LocalFree(buf);
3561 /* v1 CRL with a name and a NULL entry pointer */
3562 info.cCRLEntry = 1;
3563 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3564 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3565 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3566 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3567 /* now set an empty entry */
3568 info.rgCRLEntry = &entry;
3569 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3570 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3571 if (buf)
3573 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3574 "Wrong size %d\n", size);
3575 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3576 "Got unexpected value\n");
3577 LocalFree(buf);
3579 /* an entry with a serial number */
3580 entry.SerialNumber.cbData = sizeof(serialNum);
3581 entry.SerialNumber.pbData = (BYTE *)serialNum;
3582 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3583 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3584 if (buf)
3586 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3587 "Wrong size %d\n", size);
3588 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3589 "Got unexpected value\n");
3590 LocalFree(buf);
3592 /* an entry with an extension */
3593 entry.cExtension = 1;
3594 entry.rgExtension = &criticalExt;
3595 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3596 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3597 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3598 if (buf)
3600 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3601 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3602 LocalFree(buf);
3604 /* a CRL with an extension */
3605 entry.cExtension = 0;
3606 info.cExtension = 1;
3607 info.rgExtension = &criticalExt;
3608 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3609 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3610 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3611 if (buf)
3613 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3614 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3615 LocalFree(buf);
3617 /* a v2 CRL with an extension, this time non-critical */
3618 info.dwVersion = CRL_V2;
3619 info.rgExtension = &nonCriticalExt;
3620 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3621 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3622 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3623 if (buf)
3625 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3626 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3627 LocalFree(buf);
3629 /* a v2 CRL with an issuing dist point extension */
3630 ext.pszObjId = oid_issuing_dist_point;
3631 ext.fCritical = TRUE;
3632 ext.Value.cbData = sizeof(urlIDP);
3633 ext.Value.pbData = (LPBYTE)urlIDP;
3634 entry.rgExtension = &ext;
3635 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3636 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3637 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3638 if (buf)
3640 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3641 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3642 LocalFree(buf);
3646 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3647 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3648 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3649 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3650 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3651 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3652 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3653 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3654 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3655 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3656 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3657 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3658 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3659 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3660 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3661 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3662 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3663 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3664 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3665 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3666 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3667 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3668 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3669 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3670 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3671 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3672 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3673 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3674 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3675 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3676 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3677 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3678 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3679 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3680 0xcd };
3681 static const BYTE verisignCRLWithLotsOfEntries[] = {
3682 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3683 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3684 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3685 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3686 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3687 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3688 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3689 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3690 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3691 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3692 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3693 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3694 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3695 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3696 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3697 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3698 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3699 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3700 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3701 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3702 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3703 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3704 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3705 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3706 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3707 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3708 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3709 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3710 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3711 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3712 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3713 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3714 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3715 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3716 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3717 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3718 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3719 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3720 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3721 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3722 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3723 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3724 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3725 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3726 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3727 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3728 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3729 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3730 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3731 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3732 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3733 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3734 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3735 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3736 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3737 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3738 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3739 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3740 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3741 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3742 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3743 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3744 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3745 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3746 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3747 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3748 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3749 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3750 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3751 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3752 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3753 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3754 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3755 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3756 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3757 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3758 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3759 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3760 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3761 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3762 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3763 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3764 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3765 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3766 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3767 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3768 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3769 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3770 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3771 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3772 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3773 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3774 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3775 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3776 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3777 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3778 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3779 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3780 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3781 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3782 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3783 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3784 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3785 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3786 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3787 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3788 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3789 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3790 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3791 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3792 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3793 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3794 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3795 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3796 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3797 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3798 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3799 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3800 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3801 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3802 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3803 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3804 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3805 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3806 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3807 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3808 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3809 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3810 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3811 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3812 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3813 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3814 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3815 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3816 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3817 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3818 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3819 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3820 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3821 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3822 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3823 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3824 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3825 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3826 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3827 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3828 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3829 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3830 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3831 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3832 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3833 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3834 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3835 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3836 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3837 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3838 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3839 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3840 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3841 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3842 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3843 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3844 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3845 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3846 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3847 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3848 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3849 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3850 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3851 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3852 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3853 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3854 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3855 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3856 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3857 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3858 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3859 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3860 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3861 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3862 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3863 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3864 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3865 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3866 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3867 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3868 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3869 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3870 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3871 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3872 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3873 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3874 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3875 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3876 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3877 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3878 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3879 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3880 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3881 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3882 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3883 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3884 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3885 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3886 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3887 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3888 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3889 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3890 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3891 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3892 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3893 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3894 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3895 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3896 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3897 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3898 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3899 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3900 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3901 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3902 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3903 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3904 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3905 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3906 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3907 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3908 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3909 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3910 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3911 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3912 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3913 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3914 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3915 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3916 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3917 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3918 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3919 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3920 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3921 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3922 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3923 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3924 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3925 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3926 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3927 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3928 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3929 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3930 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3931 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3932 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3933 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3934 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3935 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3936 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3937 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3938 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3939 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3940 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3941 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3942 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3943 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3944 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3945 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3946 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3947 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3948 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3949 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3950 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3951 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3952 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3953 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3954 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3955 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
3956 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
3957 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
3958 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
3959 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
3960 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
3961 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
3962 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
3963 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
3964 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
3965 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
3966 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
3967 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
3968 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
3969 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
3970 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
3971 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
3972 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
3973 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
3974 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
3975 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
3976 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
3977 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
3978 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
3979 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
3980 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
3981 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
3982 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
3983 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
3984 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
3985 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
3986 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
3987 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
3988 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
3989 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
3990 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
3991 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
3992 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
3993 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
3994 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
3995 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
3996 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
3997 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
3998 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
3999 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4000 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4001 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4002 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4003 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4004 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4005 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4006 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4007 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4008 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4009 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4010 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4011 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4012 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4013 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4014 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4015 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4016 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4017 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4018 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4019 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4020 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4021 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4022 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4023 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4024 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4025 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4026 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4027 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4028 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4029 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4030 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4031 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4032 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4033 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4034 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4035 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4036 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4037 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4038 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4039 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4040 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4041 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4042 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4043 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4044 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4045 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4046 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4047 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4048 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4049 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4050 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4051 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4052 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4053 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4054 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4055 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4056 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4057 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4058 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4059 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4060 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4061 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4062 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4063 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4064 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4065 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4066 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4067 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4068 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4069 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4070 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4071 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4072 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4073 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4074 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4075 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4076 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4077 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4078 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4079 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4080 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4081 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4082 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4083 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4084 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4085 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4086 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4087 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4088 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4089 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4090 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4091 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4092 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4093 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4094 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4095 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4096 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4097 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4098 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4099 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4100 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4101 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4102 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4103 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4104 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4105 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4106 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4107 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4108 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4109 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4110 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4111 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4112 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4113 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4114 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4115 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4116 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4117 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4118 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4119 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4120 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4121 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4122 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4123 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4124 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4125 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4126 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4127 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4128 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4129 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4130 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4131 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4132 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4133 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4134 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4135 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4136 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4137 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4138 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4139 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4140 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4141 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4142 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4143 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4144 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4145 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4146 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4147 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4148 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4149 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4150 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4151 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4152 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4153 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4154 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4155 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4156 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4157 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4158 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4159 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4160 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4161 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4162 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4163 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4164 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4165 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4166 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4167 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4168 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4169 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4170 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4171 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4172 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4173 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4174 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4175 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4176 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4177 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4178 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4179 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4180 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4181 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4182 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4183 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4184 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4185 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4186 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4187 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4188 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4189 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4191 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4193 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4194 BOOL ret;
4195 BYTE *buf = NULL;
4196 DWORD size = 0, i;
4198 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4200 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4201 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4202 (BYTE *)&buf, &size);
4203 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4204 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4206 /* at a minimum, a CRL must contain an issuer: */
4207 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4208 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4209 (BYTE *)&buf, &size);
4210 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4211 if (buf)
4213 CRL_INFO *info = (CRL_INFO *)buf;
4215 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4216 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4217 info->cCRLEntry);
4218 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4219 "Wrong issuer size %d\n", info->Issuer.cbData);
4220 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4221 "Unexpected issuer\n");
4222 LocalFree(buf);
4224 /* check decoding with an empty CRL entry */
4225 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4226 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4227 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4228 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4229 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4230 /* with a real CRL entry */
4231 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4232 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4233 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4234 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4235 if (buf)
4237 CRL_INFO *info = (CRL_INFO *)buf;
4238 CRL_ENTRY *entry;
4240 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4241 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4242 info->cCRLEntry);
4243 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4244 entry = info->rgCRLEntry;
4245 ok(entry->SerialNumber.cbData == 1,
4246 "Expected serial number size 1, got %d\n",
4247 entry->SerialNumber.cbData);
4248 ok(*entry->SerialNumber.pbData == *serialNum,
4249 "Expected serial number %d, got %d\n", *serialNum,
4250 *entry->SerialNumber.pbData);
4251 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4252 "Wrong issuer size %d\n", info->Issuer.cbData);
4253 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4254 "Unexpected issuer\n");
4256 /* a real CRL from verisign that has extensions */
4257 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4258 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4259 NULL, (BYTE *)&buf, &size);
4260 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4261 if (buf)
4263 CRL_INFO *info = (CRL_INFO *)buf;
4264 CRL_ENTRY *entry;
4266 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4267 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4268 info->cCRLEntry);
4269 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4270 entry = info->rgCRLEntry;
4271 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4272 info->cExtension);
4273 LocalFree(buf);
4275 /* another real CRL from verisign that has lots of entries */
4276 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4277 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4278 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4279 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4280 if (buf)
4282 CRL_INFO *info = (CRL_INFO *)buf;
4284 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4285 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4286 info->cCRLEntry);
4287 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4288 info->cExtension);
4289 LocalFree(buf);
4291 /* and finally, with an extension */
4292 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4293 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4294 NULL, (BYTE *)&buf, &size);
4295 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4296 if (buf)
4298 CRL_INFO *info = (CRL_INFO *)buf;
4299 CRL_ENTRY *entry;
4301 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4302 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4303 info->cCRLEntry);
4304 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4305 entry = info->rgCRLEntry;
4306 ok(entry->SerialNumber.cbData == 1,
4307 "Expected serial number size 1, got %d\n",
4308 entry->SerialNumber.cbData);
4309 ok(*entry->SerialNumber.pbData == *serialNum,
4310 "Expected serial number %d, got %d\n", *serialNum,
4311 *entry->SerialNumber.pbData);
4312 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4313 "Wrong issuer size %d\n", info->Issuer.cbData);
4314 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4315 "Unexpected issuer\n");
4316 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4317 info->cExtension);
4319 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4320 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4321 NULL, (BYTE *)&buf, &size);
4322 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4323 if (buf)
4325 CRL_INFO *info = (CRL_INFO *)buf;
4327 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4328 info->cExtension);
4329 LocalFree(buf);
4331 /* And again, with an issuing dist point */
4332 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4333 v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4334 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4335 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4336 if (buf)
4338 CRL_INFO *info = (CRL_INFO *)buf;
4340 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4341 info->cExtension);
4342 LocalFree(buf);
4346 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4347 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4348 static const BYTE encodedUsage[] = {
4349 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4350 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4351 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4353 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4355 BOOL ret;
4356 BYTE *buf = NULL;
4357 DWORD size = 0;
4358 CERT_ENHKEY_USAGE usage;
4360 /* Test with empty usage */
4361 usage.cUsageIdentifier = 0;
4362 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4363 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4364 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4365 if (buf)
4367 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4368 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4369 LocalFree(buf);
4371 /* Test with a few usages */
4372 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4373 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4374 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4375 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4376 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4377 if (buf)
4379 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4380 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4381 LocalFree(buf);
4385 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4387 BOOL ret;
4388 LPBYTE buf = NULL;
4389 DWORD size = 0;
4391 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4392 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4393 (BYTE *)&buf, &size);
4394 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4395 if (buf)
4397 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4399 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4400 "Wrong size %d\n", size);
4401 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4402 usage->cUsageIdentifier);
4403 LocalFree(buf);
4405 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4406 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4407 (BYTE *)&buf, &size);
4408 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4409 if (buf)
4411 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4412 DWORD i;
4414 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4415 "Wrong size %d\n", size);
4416 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4417 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4418 for (i = 0; i < usage->cUsageIdentifier; i++)
4419 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4420 "Expected OID %s, got %s\n", keyUsages[i],
4421 usage->rgpszUsageIdentifier[i]);
4422 LocalFree(buf);
4426 static const BYTE authorityKeyIdWithId[] = { 0x30,0x03,0x80,0x01,0x01 };
4427 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4428 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4429 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4430 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4432 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4434 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4435 BOOL ret;
4436 BYTE *buf = NULL;
4437 DWORD size = 0;
4439 /* Test with empty id */
4440 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4441 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4442 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4443 if (buf)
4445 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4446 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4447 LocalFree(buf);
4449 /* With just a key id */
4450 info.KeyId.cbData = sizeof(serialNum);
4451 info.KeyId.pbData = (BYTE *)serialNum;
4452 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4453 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4454 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4455 if (buf)
4457 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4458 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4459 LocalFree(buf);
4461 /* With just an issuer */
4462 info.KeyId.cbData = 0;
4463 info.CertIssuer.cbData = sizeof(encodedCommonName);
4464 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4465 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4466 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4467 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4468 if (buf)
4470 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4471 size);
4472 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4473 LocalFree(buf);
4475 /* With just a serial number */
4476 info.CertIssuer.cbData = 0;
4477 info.CertSerialNumber.cbData = sizeof(serialNum);
4478 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4479 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4480 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4481 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4482 if (buf)
4484 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4485 size);
4486 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4487 LocalFree(buf);
4491 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4493 BOOL ret;
4494 LPBYTE buf = NULL;
4495 DWORD size = 0;
4497 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4498 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4499 (BYTE *)&buf, &size);
4500 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4501 if (buf)
4503 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4505 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4506 size);
4507 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4508 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4509 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4510 LocalFree(buf);
4512 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4513 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4514 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4515 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4516 if (buf)
4518 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4520 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4521 size);
4522 ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4523 ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4524 "Unexpected key id\n");
4525 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4526 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4527 LocalFree(buf);
4529 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4530 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4531 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4532 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4533 if (buf)
4535 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4537 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4538 size);
4539 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4540 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4541 "Unexpected issuer len\n");
4542 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4543 sizeof(encodedCommonName)), "Unexpected issuer\n");
4544 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4545 LocalFree(buf);
4547 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4548 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4549 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4550 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4551 if (buf)
4553 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4555 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4556 size);
4557 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4558 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4559 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4560 "Unexpected serial number len\n");
4561 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4562 "Unexpected serial number\n");
4563 LocalFree(buf);
4567 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4568 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4569 0x6f,0x72,0x67 };
4571 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4573 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4574 CERT_ALT_NAME_ENTRY entry = { 0 };
4575 BOOL ret;
4576 BYTE *buf = NULL;
4577 DWORD size = 0;
4579 /* Test with empty id */
4580 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4581 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4582 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4583 if (buf)
4585 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4586 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4587 LocalFree(buf);
4589 /* With just a key id */
4590 info.KeyId.cbData = sizeof(serialNum);
4591 info.KeyId.pbData = (BYTE *)serialNum;
4592 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4593 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4594 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4595 if (buf)
4597 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4598 size);
4599 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4600 LocalFree(buf);
4602 /* With a bogus issuer name */
4603 info.KeyId.cbData = 0;
4604 info.AuthorityCertIssuer.cAltEntry = 1;
4605 info.AuthorityCertIssuer.rgAltEntry = &entry;
4606 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4607 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4608 ok(!ret && GetLastError() == E_INVALIDARG,
4609 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4610 /* With an issuer name */
4611 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4612 U(entry).pwszURL = (LPWSTR)url;
4613 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4614 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4615 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4616 if (buf)
4618 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4619 size);
4620 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4621 "Unexpected value\n");
4622 LocalFree(buf);
4624 /* With just a serial number */
4625 info.AuthorityCertIssuer.cAltEntry = 0;
4626 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4627 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4628 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4629 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4630 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4631 if (buf)
4633 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4634 size);
4635 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4636 LocalFree(buf);
4640 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4642 BOOL ret;
4643 LPBYTE buf = NULL;
4644 DWORD size = 0;
4646 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4647 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4648 (BYTE *)&buf, &size);
4649 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4650 if (buf)
4652 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4654 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4655 size);
4656 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4657 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4658 "Expected no issuer name entries\n");
4659 ok(info->AuthorityCertSerialNumber.cbData == 0,
4660 "Expected no serial number\n");
4661 LocalFree(buf);
4663 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4664 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4665 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4666 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4667 if (buf)
4669 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4671 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4672 size);
4673 ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4674 ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4675 "Unexpected key id\n");
4676 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4677 "Expected no issuer name entries\n");
4678 ok(info->AuthorityCertSerialNumber.cbData == 0,
4679 "Expected no serial number\n");
4680 LocalFree(buf);
4682 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4683 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4684 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4685 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4686 if (buf)
4688 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4690 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4691 size);
4692 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4693 ok(info->AuthorityCertIssuer.cAltEntry == 1,
4694 "Expected 1 issuer entry, got %d\n",
4695 info->AuthorityCertIssuer.cAltEntry);
4696 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4697 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4698 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4699 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4700 url), "Unexpected URL\n");
4701 ok(info->AuthorityCertSerialNumber.cbData == 0,
4702 "Expected no serial number\n");
4703 LocalFree(buf);
4705 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4706 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4707 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4708 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4709 if (buf)
4711 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4713 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4714 size);
4715 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4716 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4717 "Expected no issuer name entries\n");
4718 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4719 "Unexpected serial number len\n");
4720 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4721 sizeof(serialNum)), "Unexpected serial number\n");
4722 LocalFree(buf);
4726 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
4727 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
4728 0x03,0,0,0,0,0,0 };
4729 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
4730 0xa0,0x01,0x01 };
4731 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
4732 0x03,0x02,0x01,0x01 };
4733 static BYTE bogusDER[] = { 1 };
4735 static void test_encodePKCSContentInfo(DWORD dwEncoding)
4737 BOOL ret;
4738 BYTE *buf = NULL;
4739 DWORD size = 0;
4740 CRYPT_CONTENT_INFO info = { 0 };
4741 char oid1[] = "1.2.3";
4743 SetLastError(0xdeadbeef);
4744 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
4745 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4746 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4747 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4748 SetLastError(0xdeadbeef);
4749 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4750 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4751 ok(!ret && GetLastError() == E_INVALIDARG,
4752 "Expected E_INVALIDARG, got %x\n", GetLastError());
4753 info.pszObjId = oid1;
4754 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4755 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4756 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4757 if (buf)
4759 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
4760 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
4761 LocalFree(buf);
4763 info.Content.pbData = bogusDER;
4764 info.Content.cbData = sizeof(bogusDER);
4765 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4766 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4767 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
4768 if (buf)
4770 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
4771 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
4772 LocalFree(buf);
4774 info.Content.pbData = (BYTE *)ints[0].encoded;
4775 info.Content.cbData = ints[0].encoded[1] + 2;
4776 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4777 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4778 if (buf)
4780 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
4781 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
4782 LocalFree(buf);
4786 static void test_decodePKCSContentInfo(DWORD dwEncoding)
4788 BOOL ret;
4789 LPBYTE buf = NULL;
4790 DWORD size = 0;
4791 CRYPT_CONTENT_INFO *info;
4793 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4794 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
4795 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4796 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4797 if (buf)
4799 info = (CRYPT_CONTENT_INFO *)buf;
4801 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4802 info->pszObjId);
4803 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
4804 info->Content.cbData);
4805 LocalFree(buf);
4807 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4808 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
4809 0, NULL, NULL, &size);
4810 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4811 SetLastError(0xdeadbeef);
4812 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4813 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
4814 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4815 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4816 * I doubt an app depends on that.
4818 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4819 GetLastError() == CRYPT_E_ASN1_CORRUPT),
4820 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4821 GetLastError());
4822 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4823 intPKCSContentInfo, sizeof(intPKCSContentInfo),
4824 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4825 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4826 if (buf)
4828 info = (CRYPT_CONTENT_INFO *)buf;
4830 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4831 info->pszObjId);
4832 ok(info->Content.cbData == ints[0].encoded[1] + 2,
4833 "Unexpected size %d\n", info->Content.cbData);
4834 ok(!memcmp(info->Content.pbData, ints[0].encoded,
4835 info->Content.cbData), "Unexpected value\n");
4839 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
4840 0x00 };
4841 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
4842 0x01 };
4843 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
4844 0x02,0x01,0x01 };
4846 static void test_encodePKCSAttribute(DWORD dwEncoding)
4848 CRYPT_ATTRIBUTE attr = { 0 };
4849 BOOL ret;
4850 LPBYTE buf = NULL;
4851 DWORD size = 0;
4852 CRYPT_ATTR_BLOB blob;
4853 char oid[] = "1.2.3";
4855 SetLastError(0xdeadbeef);
4856 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
4857 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4858 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4859 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4860 SetLastError(0xdeadbeef);
4861 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4862 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4863 ok(!ret && GetLastError() == E_INVALIDARG,
4864 "Expected E_INVALIDARG, got %x\n", GetLastError());
4865 attr.pszObjId = oid;
4866 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4867 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4868 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4869 if (buf)
4871 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
4872 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
4873 LocalFree(buf);
4875 blob.cbData = sizeof(bogusDER);
4876 blob.pbData = bogusDER;
4877 attr.cValue = 1;
4878 attr.rgValue = &blob;
4879 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4880 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4881 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4882 if (buf)
4884 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
4885 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
4886 LocalFree(buf);
4888 blob.pbData = (BYTE *)ints[0].encoded;
4889 blob.cbData = ints[0].encoded[1] + 2;
4890 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4891 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4892 if (buf)
4894 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
4895 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
4896 LocalFree(buf);
4900 static void test_decodePKCSAttribute(DWORD dwEncoding)
4902 BOOL ret;
4903 LPBYTE buf = NULL;
4904 DWORD size = 0;
4905 CRYPT_ATTRIBUTE *attr;
4907 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4908 emptyPKCSAttr, sizeof(emptyPKCSAttr),
4909 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4910 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4911 if (buf)
4913 attr = (CRYPT_ATTRIBUTE *)buf;
4915 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4916 attr->pszObjId);
4917 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
4918 LocalFree(buf);
4920 SetLastError(0xdeadbeef);
4921 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4922 bogusPKCSAttr, sizeof(bogusPKCSAttr),
4923 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4924 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4925 * I doubt an app depends on that.
4927 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4928 GetLastError() == CRYPT_E_ASN1_CORRUPT),
4929 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4930 GetLastError());
4931 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4932 intPKCSAttr, sizeof(intPKCSAttr),
4933 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4934 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4935 if (buf)
4937 attr = (CRYPT_ATTRIBUTE *)buf;
4939 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4940 attr->pszObjId);
4941 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
4942 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
4943 "Unexpected size %d\n", attr->rgValue[0].cbData);
4944 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
4945 attr->rgValue[0].cbData), "Unexpected value\n");
4949 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
4950 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
4951 0x2a,0x03,0x31,0x00 };
4952 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
4953 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
4955 static void test_encodePKCSAttributes(DWORD dwEncoding)
4957 CRYPT_ATTRIBUTES attributes = { 0 };
4958 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
4959 CRYPT_ATTR_BLOB blob;
4960 BOOL ret;
4961 LPBYTE buf = NULL;
4962 DWORD size = 0;
4963 char oid1[] = "1.2.3", oid2[] = "1.5.6";
4965 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4966 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4967 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4968 if (buf)
4970 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
4971 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
4972 LocalFree(buf);
4974 attributes.cAttr = 1;
4975 attributes.rgAttr = attr;
4976 SetLastError(0xdeadbeef);
4977 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4978 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4979 ok(!ret && GetLastError() == E_INVALIDARG,
4980 "Expected E_INVALIDARG, got %x\n", GetLastError());
4981 attr[0].pszObjId = oid1;
4982 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4983 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4984 if (buf)
4986 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
4987 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
4988 LocalFree(buf);
4990 attr[1].pszObjId = oid2;
4991 attr[1].cValue = 1;
4992 attr[1].rgValue = &blob;
4993 blob.pbData = (BYTE *)ints[0].encoded;
4994 blob.cbData = ints[0].encoded[1] + 2;
4995 attributes.cAttr = 2;
4996 ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4997 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4998 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4999 if (buf)
5001 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5002 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5003 LocalFree(buf);
5007 static void test_decodePKCSAttributes(DWORD dwEncoding)
5009 BOOL ret;
5010 LPBYTE buf = NULL;
5011 DWORD size = 0;
5012 CRYPT_ATTRIBUTES *attributes;
5014 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5015 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5016 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5017 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5018 if (buf)
5020 attributes = (CRYPT_ATTRIBUTES *)buf;
5021 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5022 attributes->cAttr);
5023 LocalFree(buf);
5025 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5026 singlePKCSAttributes, sizeof(singlePKCSAttributes),
5027 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5028 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5029 if (buf)
5031 attributes = (CRYPT_ATTRIBUTES *)buf;
5032 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5033 attributes->cAttr);
5034 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5035 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5036 ok(attributes->rgAttr[0].cValue == 0,
5037 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5038 LocalFree(buf);
5040 ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5041 doublePKCSAttributes, sizeof(doublePKCSAttributes),
5042 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5043 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5044 if (buf)
5046 attributes = (CRYPT_ATTRIBUTES *)buf;
5047 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5048 attributes->cAttr);
5049 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5050 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5051 ok(attributes->rgAttr[0].cValue == 0,
5052 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5053 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5054 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5055 ok(attributes->rgAttr[1].cValue == 1,
5056 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5057 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5058 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5059 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5060 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5061 LocalFree(buf);
5065 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
5066 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5067 0x67 };
5068 static const BYTE minimalPKCSSigner[] = {
5069 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5070 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5071 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
5072 static const BYTE PKCSSignerWithSerial[] = {
5073 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5074 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5075 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5076 0x00 };
5077 static const BYTE PKCSSignerWithHashAlgo[] = {
5078 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5079 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5080 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5081 0x00,0x04,0x00 };
5082 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
5083 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5084 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5085 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
5086 0x06,0x05,0x00,0x04,0x00 };
5087 static const BYTE PKCSSignerWithHash[] = {
5088 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5089 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5090 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
5091 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
5092 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
5093 static const BYTE PKCSSignerWithAuthAttr[] = {
5094 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5095 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5096 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
5097 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
5098 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
5099 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
5100 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
5102 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
5104 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
5105 BOOL ret;
5106 LPBYTE buf = NULL;
5107 DWORD size = 0;
5108 CMSG_SIGNER_INFO info = { 0 };
5109 char oid_common_name[] = szOID_COMMON_NAME;
5110 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
5111 (LPBYTE)encodedCommonName };
5112 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
5114 SetLastError(0xdeadbeef);
5115 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5116 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5117 ok(!ret && GetLastError() == E_INVALIDARG,
5118 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5119 /* To be encoded, a signer must have an issuer at least, and the encoding
5120 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
5121 * see decoding tests.)
5123 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
5124 info.Issuer.pbData = encodedCommonNameNoNull;
5125 SetLastError(0xdeadbeef);
5126 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5127 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5128 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5129 ok(!ret && GetLastError() == E_INVALIDARG,
5130 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5131 else
5133 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5134 if (buf)
5136 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
5137 if (size == sizeof(minimalPKCSSigner))
5138 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
5139 else
5140 ok(0, "Unexpected value\n");
5141 LocalFree(buf);
5144 info.SerialNumber.cbData = sizeof(serialNum);
5145 info.SerialNumber.pbData = (BYTE *)serialNum;
5146 SetLastError(0xdeadbeef);
5147 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5148 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5149 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5150 ok(!ret && GetLastError() == E_INVALIDARG,
5151 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5152 else
5154 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5155 if (buf)
5157 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
5158 size);
5159 if (size == sizeof(PKCSSignerWithSerial))
5160 ok(!memcmp(buf, PKCSSignerWithSerial, size),
5161 "Unexpected value\n");
5162 else
5163 ok(0, "Unexpected value\n");
5164 LocalFree(buf);
5167 info.HashAlgorithm.pszObjId = oid1;
5168 SetLastError(0xdeadbeef);
5169 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5170 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5171 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5172 ok(!ret && GetLastError() == E_INVALIDARG,
5173 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5174 else
5176 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5177 if (buf)
5179 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
5180 size);
5181 if (size == sizeof(PKCSSignerWithHashAlgo))
5182 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
5183 "Unexpected value\n");
5184 else
5185 ok(0, "Unexpected value\n");
5186 LocalFree(buf);
5189 info.HashEncryptionAlgorithm.pszObjId = oid2;
5190 SetLastError(0xdeadbeef);
5191 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5192 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5193 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5194 ok(!ret && GetLastError() == E_INVALIDARG,
5195 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5196 else
5198 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5199 if (buf)
5201 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
5202 "Unexpected size %d\n", size);
5203 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
5204 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
5205 "Unexpected value\n");
5206 else
5207 ok(0, "Unexpected value\n");
5208 LocalFree(buf);
5211 info.EncryptedHash.cbData = sizeof(hash);
5212 info.EncryptedHash.pbData = (BYTE *)hash;
5213 SetLastError(0xdeadbeef);
5214 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5215 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5216 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5217 ok(!ret && GetLastError() == E_INVALIDARG,
5218 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5219 else
5221 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5222 if (buf)
5224 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
5225 size);
5226 if (size == sizeof(PKCSSignerWithHash))
5227 ok(!memcmp(buf, PKCSSignerWithHash, size),
5228 "Unexpected value\n");
5229 else
5230 ok(0, "Unexpected value\n");
5231 LocalFree(buf);
5234 info.AuthAttrs.cAttr = 1;
5235 info.AuthAttrs.rgAttr = &attr;
5236 SetLastError(0xdeadbeef);
5237 ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5238 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5239 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5240 ok(!ret && GetLastError() == E_INVALIDARG,
5241 "Expected E_INVALIDARG, got %08x\n", GetLastError());
5242 else
5244 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5245 if (buf)
5247 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
5248 size);
5249 if (size == sizeof(PKCSSignerWithAuthAttr))
5250 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
5251 "Unexpected value\n");
5252 else
5253 ok(0, "Unexpected value\n");
5254 LocalFree(buf);
5259 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
5261 BOOL ret;
5262 LPBYTE buf = NULL;
5263 DWORD size = 0;
5264 CMSG_SIGNER_INFO *info;
5266 /* A PKCS signer can't be decoded without a serial number. */
5267 SetLastError(0xdeadbeef);
5268 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5269 minimalPKCSSigner, sizeof(minimalPKCSSigner),
5270 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5271 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
5272 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
5273 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5274 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
5275 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5276 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5277 if (buf)
5279 info = (CMSG_SIGNER_INFO *)buf;
5280 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5281 info->dwVersion);
5282 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5283 "Unexpected size %d\n", info->Issuer.cbData);
5284 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5285 info->Issuer.cbData), "Unexpected value\n");
5286 ok(info->SerialNumber.cbData == sizeof(serialNum),
5287 "Unexpected size %d\n", info->SerialNumber.cbData);
5288 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5289 "Unexpected value\n");
5290 LocalFree(buf);
5292 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5293 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
5294 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5295 if (buf)
5297 info = (CMSG_SIGNER_INFO *)buf;
5298 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5299 info->dwVersion);
5300 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5301 "Unexpected size %d\n", info->Issuer.cbData);
5302 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5303 info->Issuer.cbData), "Unexpected value\n");
5304 ok(info->SerialNumber.cbData == sizeof(serialNum),
5305 "Unexpected size %d\n", info->SerialNumber.cbData);
5306 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5307 "Unexpected value\n");
5308 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5309 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5310 LocalFree(buf);
5312 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5313 PKCSSignerWithHashAndEncryptionAlgo,
5314 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
5315 NULL, (BYTE *)&buf, &size);
5316 if (buf)
5318 info = (CMSG_SIGNER_INFO *)buf;
5319 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5320 info->dwVersion);
5321 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5322 "Unexpected size %d\n", info->Issuer.cbData);
5323 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5324 info->Issuer.cbData), "Unexpected value\n");
5325 ok(info->SerialNumber.cbData == sizeof(serialNum),
5326 "Unexpected size %d\n", info->SerialNumber.cbData);
5327 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5328 "Unexpected value\n");
5329 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5330 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5331 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5332 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5333 LocalFree(buf);
5335 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5336 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
5337 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5338 if (buf)
5340 info = (CMSG_SIGNER_INFO *)buf;
5341 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5342 info->dwVersion);
5343 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5344 "Unexpected size %d\n", info->Issuer.cbData);
5345 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5346 info->Issuer.cbData), "Unexpected value\n");
5347 ok(info->SerialNumber.cbData == sizeof(serialNum),
5348 "Unexpected size %d\n", info->SerialNumber.cbData);
5349 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5350 "Unexpected value\n");
5351 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5352 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5353 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5354 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5355 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
5356 info->EncryptedHash.cbData);
5357 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
5358 "Unexpected value\n");
5359 LocalFree(buf);
5361 ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5362 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
5363 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5364 if (buf)
5366 info = (CMSG_SIGNER_INFO *)buf;
5367 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
5368 info->AuthAttrs.cAttr);
5369 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
5370 "Expected %s, got %s\n", szOID_COMMON_NAME,
5371 info->AuthAttrs.rgAttr[0].pszObjId);
5372 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
5373 info->AuthAttrs.rgAttr[0].cValue);
5374 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
5375 sizeof(encodedCommonName), "Unexpected size %d\n",
5376 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
5377 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
5378 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
5379 LocalFree(buf);
5383 /* Free *pInfo with HeapFree */
5384 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
5386 BOOL ret;
5387 DWORD size = 0;
5388 HCRYPTKEY key;
5390 /* This crashes
5391 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
5393 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
5394 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5395 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5396 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
5397 &size);
5398 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5399 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5400 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
5401 NULL, &size);
5402 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5403 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5404 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5405 0, NULL, NULL, &size);
5406 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5407 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5408 /* Test with no key */
5409 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5410 0, NULL, NULL, &size);
5411 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
5412 GetLastError());
5413 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
5414 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
5415 if (ret)
5417 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
5418 NULL, 0, NULL, NULL, &size);
5419 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
5420 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
5421 if (*pInfo)
5423 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
5424 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
5425 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
5426 GetLastError());
5427 if (ret)
5429 /* By default (we passed NULL as the OID) the OID is
5430 * szOID_RSA_RSA.
5432 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
5433 "Expected %s, got %s\n", szOID_RSA_RSA,
5434 (*pInfo)->Algorithm.pszObjId);
5440 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
5441 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
5442 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
5443 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5444 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5445 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5446 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
5447 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
5448 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5449 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5450 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5451 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5452 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
5453 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
5454 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
5455 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
5456 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
5457 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
5458 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
5459 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
5460 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
5461 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
5462 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
5463 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
5464 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
5466 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
5468 BOOL ret;
5469 HCRYPTKEY key;
5470 PCCERT_CONTEXT context;
5472 /* These crash
5473 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
5474 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
5475 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
5476 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5477 NULL);
5479 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
5480 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5481 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5482 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
5483 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5484 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5485 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
5486 &key);
5487 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5488 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5489 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5490 &key);
5491 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5492 CryptDestroyKey(key);
5494 /* Test importing a public key from a certificate context */
5495 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
5496 sizeof(expiredCert));
5497 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
5498 GetLastError());
5499 if (context)
5501 ok(!strcmp(szOID_RSA_RSA,
5502 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
5503 "Expected %s, got %s\n", szOID_RSA_RSA,
5504 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
5505 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
5506 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
5507 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5508 CryptDestroyKey(key);
5509 CertFreeCertificateContext(context);
5513 static const char cspName[] = "WineCryptTemp";
5515 static void testPortPublicKeyInfo(void)
5517 HCRYPTPROV csp;
5518 BOOL ret;
5519 PCERT_PUBLIC_KEY_INFO info = NULL;
5521 /* Just in case a previous run failed, delete this thing */
5522 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5523 CRYPT_DELETEKEYSET);
5524 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5525 CRYPT_NEWKEYSET);
5527 testExportPublicKey(csp, &info);
5528 testImportPublicKey(csp, info);
5530 HeapFree(GetProcessHeap(), 0, info);
5531 CryptReleaseContext(csp, 0);
5532 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5533 CRYPT_DELETEKEYSET);
5536 START_TEST(encode)
5538 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
5539 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
5540 DWORD i;
5542 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
5544 test_encodeInt(encodings[i]);
5545 test_decodeInt(encodings[i]);
5546 test_encodeEnumerated(encodings[i]);
5547 test_decodeEnumerated(encodings[i]);
5548 test_encodeFiletime(encodings[i]);
5549 test_decodeFiletime(encodings[i]);
5550 test_encodeName(encodings[i]);
5551 test_decodeName(encodings[i]);
5552 test_encodeUnicodeName(encodings[i]);
5553 test_decodeUnicodeName(encodings[i]);
5554 test_encodeNameValue(encodings[i]);
5555 test_decodeNameValue(encodings[i]);
5556 test_encodeUnicodeNameValue(encodings[i]);
5557 test_decodeUnicodeNameValue(encodings[i]);
5558 test_encodeAltName(encodings[i]);
5559 test_decodeAltName(encodings[i]);
5560 test_encodeOctets(encodings[i]);
5561 test_decodeOctets(encodings[i]);
5562 test_encodeBits(encodings[i]);
5563 test_decodeBits(encodings[i]);
5564 test_encodeBasicConstraints(encodings[i]);
5565 test_decodeBasicConstraints(encodings[i]);
5566 test_encodeRsaPublicKey(encodings[i]);
5567 test_decodeRsaPublicKey(encodings[i]);
5568 test_encodeSequenceOfAny(encodings[i]);
5569 test_decodeSequenceOfAny(encodings[i]);
5570 test_encodeExtensions(encodings[i]);
5571 test_decodeExtensions(encodings[i]);
5572 test_encodePublicKeyInfo(encodings[i]);
5573 test_decodePublicKeyInfo(encodings[i]);
5574 test_encodeCertToBeSigned(encodings[i]);
5575 test_decodeCertToBeSigned(encodings[i]);
5576 test_encodeCert(encodings[i]);
5577 test_decodeCert(encodings[i]);
5578 test_encodeCRLDistPoints(encodings[i]);
5579 test_decodeCRLDistPoints(encodings[i]);
5580 test_encodeCRLIssuingDistPoint(encodings[i]);
5581 test_decodeCRLIssuingDistPoint(encodings[i]);
5582 test_encodeCRLToBeSigned(encodings[i]);
5583 test_decodeCRLToBeSigned(encodings[i]);
5584 test_encodeEnhancedKeyUsage(encodings[i]);
5585 test_decodeEnhancedKeyUsage(encodings[i]);
5586 test_encodeAuthorityKeyId(encodings[i]);
5587 test_decodeAuthorityKeyId(encodings[i]);
5588 test_encodeAuthorityKeyId2(encodings[i]);
5589 test_decodeAuthorityKeyId2(encodings[i]);
5590 test_encodePKCSContentInfo(encodings[i]);
5591 test_decodePKCSContentInfo(encodings[i]);
5592 test_encodePKCSAttribute(encodings[i]);
5593 test_decodePKCSAttribute(encodings[i]);
5594 test_encodePKCSAttributes(encodings[i]);
5595 test_decodePKCSAttributes(encodings[i]);
5596 test_encodePKCSSignerInfo(encodings[i]);
5597 test_decodePKCSSignerInfo(encodings[i]);
5599 testPortPublicKeyInfo();