mshtml: Print wine_gecko version in load_wine_gecko.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
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.
10  *
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.
15  *
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
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29 struct encodedInt
30 {
31     int val;
32     const BYTE *encoded;
33 };
34
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};
42
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 },
51 };
52
53 struct encodedBigInt
54 {
55     const BYTE *val;
56     const BYTE *encoded;
57     const BYTE *decoded;
58 };
59
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};
63
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};
67
68 static const struct encodedBigInt bigInts[] = {
69  { bin8, bin9, bin10 },
70  { bin11, bin12, bin13 },
71 };
72
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};
77
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 },
82 };
83
84 static void test_encodeInt(DWORD dwEncoding)
85 {
86     DWORD bufSize = 0;
87     int i;
88     BOOL ret;
89     CRYPT_INTEGER_BLOB blob;
90     BYTE *buf = NULL;
91
92     /* CryptEncodeObjectEx with NULL bufSize crashes..
93     ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
94      NULL);
95      */
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.
103      */
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++)
109     {
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)
118         {
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);
126         }
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)
137         {
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);
145         }
146     }
147     /* encode a couple bigger ints, just to show it's little-endian and leading
148      * sign bytes are dropped
149      */
150     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
151     {
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)
161         {
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);
170         }
171     }
172     /* and, encode some uints */
173     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
174     {
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)
184         {
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);
193         }
194     }
195 }
196
197 static void test_decodeInt(DWORD dwEncoding)
198 {
199     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
200     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
201     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
202     /* static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 }; */
203     BYTE *buf = NULL;
204     DWORD bufSize = 0;
205     int i;
206     BOOL ret;
207
208     /* CryptDecodeObjectEx with NULL bufSize crashes..
209     ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded, 
210      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
211      */
212     /* check bogus encoding */
213     ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded, 
214      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
215     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
216      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
217     /* check with NULL integer buffer */
218     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
219      &bufSize);
220     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
221      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
222     /* check with a valid, but too large, integer */
223     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
224      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
225     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
226      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
227     /* check with a DER-encoded string */
228     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
229      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
231      "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError());
232     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
233     {
234         /* When the output buffer is NULL, this always succeeds */
235         SetLastError(0xdeadbeef);
236         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
237          (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
238          &bufSize);
239         ok(ret && GetLastError() == NOERROR,
240          "Expected success and NOERROR, got %d\n", GetLastError());
241         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242          (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2,
243          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
244         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
245         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
246         ok(buf != NULL, "Expected allocated buffer\n");
247         if (buf)
248         {
249             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
250              ints[i].val, *(int *)buf);
251             LocalFree(buf);
252         }
253     }
254     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
255     {
256         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
257          (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
258          &bufSize);
259         ok(ret && GetLastError() == NOERROR,
260          "Expected success and NOERROR, got %d\n", GetLastError());
261         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
262          (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2,
263          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
264         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
265         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
266         ok(buf != NULL, "Expected allocated buffer\n");
267         if (buf)
268         {
269             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
270
271             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
272              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
273              blob->cbData);
274             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
275              "Unexpected value\n");
276             LocalFree(buf);
277         }
278     }
279     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
280     {
281         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
282          (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
283          &bufSize);
284         ok(ret && GetLastError() == NOERROR,
285          "Expected success and NOERROR, got %d\n", GetLastError());
286         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
287          (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
288          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
289         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
290         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
291         ok(buf != NULL, "Expected allocated buffer\n");
292         if (buf)
293         {
294             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
295
296             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
297              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
298              blob->cbData);
299             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
300              "Unexpected value\n");
301             LocalFree(buf);
302         }
303     }
304     /* Decode the value 1 with long-form length */
305     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
306      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
307     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
308     if (buf)
309     {
310         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
311         LocalFree(buf);
312     }
313     /* Try to decode some bogus large items */
314     /* The buffer size is smaller than the encoded length, so this should fail
315      * with CRYPT_E_ASN1_EOD if it's being decoded.
316      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
317      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
318      * So this test unfortunately isn't useful.
319     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
320      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
321     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
322      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
323      */
324     /* This will try to decode the buffer and overflow it, check that it's
325      * caught.
326      */
327 #if 0  /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
328     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
329      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
330     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
331      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
332 #endif
333 }
334
335 static const BYTE bin18[] = {0x0a,0x01,0x01};
336 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
337
338 /* These are always encoded unsigned, and aren't constrained to be any
339  * particular value
340  */
341 static const struct encodedInt enums[] = {
342  { 1,    bin18 },
343  { -128, bin19 },
344 };
345
346 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
347  * X509_ENUMERATED.
348  */
349 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
350  szOID_CRL_REASON_CODE };
351
352 static void test_encodeEnumerated(DWORD dwEncoding)
353 {
354     DWORD i, j;
355
356     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
357     {
358         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
359         {
360             BOOL ret;
361             BYTE *buf = NULL;
362             DWORD bufSize = 0;
363
364             ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
365              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
366              &bufSize);
367             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
368             if (buf)
369             {
370                 ok(buf[0] == 0xa,
371                  "Got unexpected type %d for enumerated (expected 0xa)\n",
372                  buf[0]);
373                 ok(buf[1] == enums[j].encoded[1],
374                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
375                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
376                  enums[j].encoded[1] + 1),
377                  "Encoded value of 0x%08x didn't match expected\n",
378                  enums[j].val);
379                 LocalFree(buf);
380             }
381         }
382     }
383 }
384
385 static void test_decodeEnumerated(DWORD dwEncoding)
386 {
387     DWORD i, j;
388
389     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
390     {
391         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
392         {
393             BOOL ret;
394             DWORD bufSize = sizeof(int);
395             int val;
396
397             ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
398              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
399              (BYTE *)&val, &bufSize);
400             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
401             ok(bufSize == sizeof(int),
402              "Got unexpected size %d for enumerated\n", bufSize);
403             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
404              val, enums[j].val);
405         }
406     }
407 }
408
409 struct encodedFiletime
410 {
411     SYSTEMTIME sysTime;
412     const BYTE *encodedTime;
413 };
414
415 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
416  const struct encodedFiletime *time)
417 {
418     FILETIME ft = { 0 };
419     BYTE *buf = NULL;
420     DWORD bufSize = 0;
421     BOOL ret;
422
423     ret = SystemTimeToFileTime(&time->sysTime, &ft);
424     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
425     ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
426      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
427     /* years other than 1950-2050 are not allowed for encodings other than
428      * X509_CHOICE_OF_TIME.
429      */
430     if (structType == X509_CHOICE_OF_TIME ||
431      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
432     {
433         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
434          GetLastError());
435         ok(buf != NULL, "Expected an allocated buffer\n");
436         if (buf)
437         {
438             ok(buf[0] == time->encodedTime[0],
439              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
440              buf[0]);
441             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
442              time->encodedTime[1], bufSize);
443             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
444              "Got unexpected value for time encoding\n");
445             LocalFree(buf);
446         }
447     }
448     else
449         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
450          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
451 }
452
453 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
454  const struct encodedFiletime *time)
455 {
456     FILETIME ft1 = { 0 }, ft2 = { 0 };
457     DWORD size = sizeof(ft2);
458     BOOL ret;
459
460     ret = SystemTimeToFileTime(&time->sysTime, &ft1);
461     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
462     ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
463      time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
464     /* years other than 1950-2050 are not allowed for encodings other than
465      * X509_CHOICE_OF_TIME.
466      */
467     if (structType == X509_CHOICE_OF_TIME ||
468      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
469     {
470         ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
471          GetLastError());
472         ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
473          "Got unexpected value for time decoding\n");
474     }
475     else
476         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
477          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
478 }
479
480 static const BYTE bin20[] = {
481     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
482 static const BYTE bin21[] = {
483     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
484 static const BYTE bin22[] = {
485     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
486
487 static const struct encodedFiletime times[] = {
488  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
489  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
490  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
491 };
492
493 static void test_encodeFiletime(DWORD dwEncoding)
494 {
495     DWORD i;
496
497     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
498     {
499         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
500         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
501         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
502     }
503 }
504
505 static const BYTE bin23[] = {
506     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
507 static const BYTE bin24[] = {
508     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
509 static const BYTE bin25[] = {
510     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
511 static const BYTE bin26[] = {
512     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
513 static const BYTE bin27[] = {
514     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
515 static const BYTE bin28[] = {
516     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
517 static const BYTE bin29[] = {
518     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
519 static const BYTE bin30[] = {
520     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
521 static const BYTE bin31[] = {
522     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
523 static const BYTE bin32[] = {
524     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
525 static const BYTE bin33[] = {
526     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
527 static const BYTE bin34[] = {
528     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
529 static const BYTE bin35[] = {
530     0x17,0x08, '4','5','0','6','0','6','1','6'};
531 static const BYTE bin36[] = {
532     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
533 static const BYTE bin37[] = {
534     0x18,0x04, '2','1','4','5'};
535 static const BYTE bin38[] = {
536     0x18,0x08, '2','1','4','5','0','6','0','6'};
537
538 static void test_decodeFiletime(DWORD dwEncoding)
539 {
540     static const struct encodedFiletime otherTimes[] = {
541      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
542      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
543      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
544      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
545      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
546      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
547      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
548      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
549      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
550      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
551      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
552      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
553     };
554     /* An oddball case that succeeds in Windows, but doesn't seem correct
555      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
556      */
557     static const unsigned char *bogusTimes[] = {
558      /* oddly, this succeeds on Windows, with year 2765
559      "\x18" "\x0f" "21r50606161000Z",
560       */
561      bin35,
562      bin36,
563      bin37,
564      bin38,
565     };
566     DWORD i, size;
567     FILETIME ft1 = { 0 }, ft2 = { 0 };
568     BOOL ret;
569
570     /* Check bogus length with non-NULL buffer */
571     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
572     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
573     size = 1;
574     ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
575      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
576     ok(!ret && GetLastError() == ERROR_MORE_DATA,
577      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
578     /* Normal tests */
579     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
580     {
581         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
582         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
583         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
584     }
585     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
586     {
587         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
588         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
589         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
590     }
591     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
592     {
593         size = sizeof(ft1);
594         ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
595          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
596         ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
597          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
598     }
599 }
600
601 static const char commonName[] = "Juan Lang";
602 static const char surName[] = "Lang";
603
604 static const BYTE emptySequence[] = { 0x30, 0 };
605 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
606 static const BYTE twoRDNs[] = {
607     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
608     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
609     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
610 static const BYTE encodedTwoRDNs[] = {
611 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
612 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
613 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
614 0x6e,0x67,0x00,
615 };
616
617 static const BYTE us[] = { 0x55, 0x53 };
618 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
619  0x74, 0x61 };
620 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
621  0x6f, 0x6c, 0x69, 0x73 };
622 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
623  0x76, 0x65, 0x72, 0x73 };
624 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
625  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
626 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
627  0x73, 0x74 };
628 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
629  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
630
631 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
632 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
633
634 static CHAR oid_us[]            = "2.5.4.6",
635             oid_minnesota[]     = "2.5.4.8",
636             oid_minneapolis[]   = "2.5.4.7",
637             oid_codeweavers[]   = "2.5.4.10",
638             oid_wine[]          = "2.5.4.11",
639             oid_localhostAttr[] = "2.5.4.3",
640             oid_aric[]          = "1.2.840.113549.1.9.1";
641 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
642                                     { RDNA(minnesota) },
643                                     { RDNA(minneapolis) },
644                                     { RDNA(codeweavers) },
645                                     { RDNA(wine) },
646                                     { RDNA(localhostAttr) },
647                                     { RDNIA5(aric) } };
648 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
649                                            { RDNA(localhostAttr) },
650                                            { RDNA(minnesota) },
651                                            { RDNA(minneapolis) },
652                                            { RDNA(codeweavers) },
653                                            { RDNA(wine) },
654                                            { RDNIA5(aric) } };
655
656 #undef RDNIA5
657 #undef RDNA
658
659 static const BYTE encodedRDNAttrs[] = {
660 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
661 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
662 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
663 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
664 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
665 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
666 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
667 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
668 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
669 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
670 };
671
672 static void test_encodeName(DWORD dwEncoding)
673 {
674     CERT_RDN_ATTR attrs[2];
675     CERT_RDN rdn;
676     CERT_NAME_INFO info;
677     static CHAR oid_common_name[] = szOID_COMMON_NAME,
678                 oid_sur_name[]    = szOID_SUR_NAME;
679     BYTE *buf = NULL;
680     DWORD size = 0;
681     BOOL ret;
682
683     /* Test with NULL pvStructInfo */
684     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
685      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
686     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
687      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
688     /* Test with empty CERT_NAME_INFO */
689     info.cRDN = 0;
690     info.rgRDN = NULL;
691     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
692      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
693     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
694     if (buf)
695     {
696         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
697          "Got unexpected encoding for empty name\n");
698         LocalFree(buf);
699     }
700     /* Test with bogus CERT_RDN */
701     info.cRDN = 1;
702     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
703      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
704     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
705      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
706     /* Test with empty CERT_RDN */
707     rdn.cRDNAttr = 0;
708     rdn.rgRDNAttr = NULL;
709     info.cRDN = 1;
710     info.rgRDN = &rdn;
711     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
712      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
713     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
714     if (buf)
715     {
716         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
717          "Got unexpected encoding for empty RDN array\n");
718         LocalFree(buf);
719     }
720     /* Test with bogus attr array */
721     rdn.cRDNAttr = 1;
722     rdn.rgRDNAttr = NULL;
723     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
724      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
725     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
726      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
727     /* oddly, a bogus OID is accepted by Windows XP; not testing.
728     attrs[0].pszObjId = "bogus";
729     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
730     attrs[0].Value.cbData = sizeof(commonName);
731     attrs[0].Value.pbData = (BYTE *)commonName;
732     rdn.cRDNAttr = 1;
733     rdn.rgRDNAttr = attrs;
734     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
735      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
736     ok(!ret, "Expected failure, got success\n");
737      */
738     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
739      * the encoded attributes to be swapped.
740      */
741     attrs[0].pszObjId = oid_common_name;
742     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
743     attrs[0].Value.cbData = sizeof(commonName);
744     attrs[0].Value.pbData = (BYTE *)commonName;
745     attrs[1].pszObjId = oid_sur_name;
746     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
747     attrs[1].Value.cbData = sizeof(surName);
748     attrs[1].Value.pbData = (BYTE *)surName;
749     rdn.cRDNAttr = 2;
750     rdn.rgRDNAttr = attrs;
751     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
752      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
753     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
754     if (buf)
755     {
756         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
757          "Got unexpected encoding for two RDN array\n");
758         LocalFree(buf);
759     }
760     /* A name can be "encoded" with previously encoded RDN attrs. */
761     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
762     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
763     attrs[0].Value.cbData = sizeof(twoRDNs);
764     rdn.cRDNAttr = 1;
765     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
767     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768     if (buf)
769     {
770         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
771         ok(!memcmp(buf, encodedTwoRDNs, size),
772          "Unexpected value for re-endoded two RDN array\n");
773         LocalFree(buf);
774     }
775     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
776     rdn.cRDNAttr = 1;
777     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
778     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
780     ok(!ret && GetLastError() == E_INVALIDARG,
781      "Expected E_INVALIDARG, got %08x\n", GetLastError());
782     /* Test a more complex name */
783     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
784     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
785     info.cRDN = 1;
786     info.rgRDN = &rdn;
787     buf = NULL;
788     size = 0;
789     ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
790      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
791     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
792     if (ret)
793     {
794         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
795         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
796         LocalFree(buf);
797     }
798 }
799
800 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
801 static WCHAR surNameW[] = { 'L','a','n','g',0 };
802
803 static const BYTE twoRDNsNoNull[] = {
804  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
805  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
806  0x20,0x4c,0x61,0x6e,0x67 };
807 static const BYTE anyType[] = {
808  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
809  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
810  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
811  0x61,0x4c,0x67,0x6e };
812
813 static void test_encodeUnicodeName(DWORD dwEncoding)
814 {
815     CERT_RDN_ATTR attrs[2];
816     CERT_RDN rdn;
817     CERT_NAME_INFO info;
818     static CHAR oid_common_name[] = szOID_COMMON_NAME,
819                 oid_sur_name[]    = szOID_SUR_NAME;
820     BYTE *buf = NULL;
821     DWORD size = 0;
822     BOOL ret;
823
824     /* Test with NULL pvStructInfo */
825     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
826      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
827     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
828      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
829     /* Test with empty CERT_NAME_INFO */
830     info.cRDN = 0;
831     info.rgRDN = NULL;
832     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
833      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
834     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
835     if (buf)
836     {
837         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
838          "Got unexpected encoding for empty name\n");
839         LocalFree(buf);
840     }
841     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
842      * encoding (the NULL).
843      */
844     attrs[0].pszObjId = oid_common_name;
845     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
846     attrs[0].Value.cbData = sizeof(commonNameW);
847     attrs[0].Value.pbData = (BYTE *)commonNameW;
848     rdn.cRDNAttr = 1;
849     rdn.rgRDNAttr = attrs;
850     info.cRDN = 1;
851     info.rgRDN = &rdn;
852     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
853      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
854     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
855      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
856     ok(size == 9, "Unexpected error index %08x\n", size);
857     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
858      * forces the order of the encoded attributes to be swapped.
859      */
860     attrs[0].pszObjId = oid_common_name;
861     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
862     attrs[0].Value.cbData = 0;
863     attrs[0].Value.pbData = (BYTE *)commonNameW;
864     attrs[1].pszObjId = oid_sur_name;
865     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
866     attrs[1].Value.cbData = 0;
867     attrs[1].Value.pbData = (BYTE *)surNameW;
868     rdn.cRDNAttr = 2;
869     rdn.rgRDNAttr = attrs;
870     info.cRDN = 1;
871     info.rgRDN = &rdn;
872     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
873      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
874     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
875     if (buf)
876     {
877         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
878          "Got unexpected encoding for two RDN array\n");
879         LocalFree(buf);
880     }
881     /* A name can be "encoded" with previously encoded RDN attrs. */
882     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
883     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
884     attrs[0].Value.cbData = sizeof(twoRDNs);
885     rdn.cRDNAttr = 1;
886     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
887      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
888     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
889     if (buf)
890     {
891         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
892         ok(!memcmp(buf, encodedTwoRDNs, size),
893          "Unexpected value for re-endoded two RDN array\n");
894         LocalFree(buf);
895     }
896     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
897     rdn.cRDNAttr = 1;
898     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
899     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
900      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
901     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
902     if (buf)
903     {
904         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
905         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
906         LocalFree(buf);
907     }
908 }
909
910 static void compareNameValues(const CERT_NAME_VALUE *expected,
911  const CERT_NAME_VALUE *got)
912 {
913     ok(got->dwValueType == expected->dwValueType,
914      "Expected string type %d, got %d\n", expected->dwValueType,
915      got->dwValueType);
916     ok(got->Value.cbData == expected->Value.cbData,
917      "String type %d: unexpected data size, got %d, expected %d\n",
918      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
919     if (got->Value.cbData && got->Value.pbData)
920         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
921          min(got->Value.cbData, expected->Value.cbData)),
922          "String type %d: unexpected value\n", expected->dwValueType);
923 }
924
925 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
926  const CERT_RDN_ATTR *got)
927 {
928     if (expected->pszObjId && strlen(expected->pszObjId))
929     {
930         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
931          expected->pszObjId);
932         if (got->pszObjId)
933         {
934             ok(!strcmp(got->pszObjId, expected->pszObjId),
935              "Got unexpected OID %s, expected %s\n", got->pszObjId,
936              expected->pszObjId);
937         }
938     }
939     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
940      (const CERT_NAME_VALUE *)&got->dwValueType);
941 }
942
943 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
944 {
945     ok(got->cRDNAttr == expected->cRDNAttr,
946      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
947     if (got->cRDNAttr)
948     {
949         DWORD i;
950
951         for (i = 0; i < got->cRDNAttr; i++)
952             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
953     }
954 }
955
956 static void compareNames(const CERT_NAME_INFO *expected,
957  const CERT_NAME_INFO *got)
958 {
959     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
960      expected->cRDN, got->cRDN);
961     if (got->cRDN)
962     {
963         DWORD i;
964
965         for (i = 0; i < got->cRDN; i++)
966             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
967     }
968 }
969
970 static void test_decodeName(DWORD dwEncoding)
971 {
972     BYTE *buf = NULL;
973     DWORD bufSize = 0;
974     BOOL ret;
975     CERT_RDN rdn;
976     CERT_NAME_INFO info = { 1, &rdn };
977
978     /* test empty name */
979     bufSize = 0;
980     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
981      emptySequence[1] + 2,
982      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
983      (BYTE *)&buf, &bufSize);
984     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
985     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
986      * decoder works the same way, so only test the count.
987      */
988     if (buf)
989     {
990         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
991         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
992          "Expected 0 RDNs in empty info, got %d\n",
993          ((CERT_NAME_INFO *)buf)->cRDN);
994         LocalFree(buf);
995     }
996     /* test empty RDN */
997     bufSize = 0;
998     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
999      emptyRDNs[1] + 2,
1000      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1001      (BYTE *)&buf, &bufSize);
1002     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1003     if (buf)
1004     {
1005         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1006
1007         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1008          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1009          "Got unexpected value for empty RDN\n");
1010         LocalFree(buf);
1011     }
1012     /* test two RDN attrs */
1013     bufSize = 0;
1014     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1015      twoRDNs[1] + 2,
1016      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1017      (BYTE *)&buf, &bufSize);
1018     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1019     if (buf)
1020     {
1021         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1022                     oid_common_name[] = szOID_COMMON_NAME;
1023
1024         CERT_RDN_ATTR attrs[] = {
1025          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1026           (BYTE *)surName } },
1027          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1028           (BYTE *)commonName } },
1029         };
1030
1031         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1032         rdn.rgRDNAttr = attrs;
1033         compareNames(&info, (CERT_NAME_INFO *)buf);
1034         LocalFree(buf);
1035     }
1036     /* And, a slightly more complicated name */
1037     buf = NULL;
1038     bufSize = 0;
1039     ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1040      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1041     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1042     if (ret)
1043     {
1044         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1045         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1046         compareNames(&info, (CERT_NAME_INFO *)buf);
1047         LocalFree(buf);
1048     }
1049 }
1050
1051 static void test_decodeUnicodeName(DWORD dwEncoding)
1052 {
1053     BYTE *buf = NULL;
1054     DWORD bufSize = 0;
1055     BOOL ret;
1056     CERT_RDN rdn;
1057     CERT_NAME_INFO info = { 1, &rdn };
1058
1059     /* test empty name */
1060     bufSize = 0;
1061     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1062      emptySequence[1] + 2,
1063      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1064      (BYTE *)&buf, &bufSize);
1065     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1066     if (buf)
1067     {
1068         ok(bufSize == sizeof(CERT_NAME_INFO),
1069          "Got wrong bufSize %d\n", bufSize);
1070         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1071          "Expected 0 RDNs in empty info, got %d\n",
1072          ((CERT_NAME_INFO *)buf)->cRDN);
1073         LocalFree(buf);
1074     }
1075     /* test empty RDN */
1076     bufSize = 0;
1077     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1078      emptyRDNs[1] + 2,
1079      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1080      (BYTE *)&buf, &bufSize);
1081     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1082     if (buf)
1083     {
1084         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1085
1086         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1087          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1088          "Got unexpected value for empty RDN\n");
1089         LocalFree(buf);
1090     }
1091     /* test two RDN attrs */
1092     bufSize = 0;
1093     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1094      sizeof(twoRDNsNoNull),
1095      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1096      (BYTE *)&buf, &bufSize);
1097     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1098     if (buf)
1099     {
1100         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1101                     oid_common_name[] = szOID_COMMON_NAME;
1102
1103         CERT_RDN_ATTR attrs[] = {
1104          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1105          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1106          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1107          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1108         };
1109
1110         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1111         rdn.rgRDNAttr = attrs;
1112         compareNames(&info, (CERT_NAME_INFO *)buf);
1113         LocalFree(buf);
1114     }
1115 }
1116
1117 struct EncodedNameValue
1118 {
1119     CERT_NAME_VALUE value;
1120     const BYTE *encoded;
1121     DWORD encodedSize;
1122 };
1123
1124 static const char bogusIA5[] = "\x80";
1125 static const char bogusPrintable[] = "~";
1126 static const char bogusNumeric[] = "A";
1127 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1128 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1129 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1130 static BYTE octetCommonNameValue[] = {
1131  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1132 static BYTE numericCommonNameValue[] = {
1133  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1134 static BYTE printableCommonNameValue[] = {
1135  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1136 static BYTE t61CommonNameValue[] = {
1137  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1138 static BYTE videotexCommonNameValue[] = {
1139  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1140 static BYTE ia5CommonNameValue[] = {
1141  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1142 static BYTE graphicCommonNameValue[] = {
1143  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1144 static BYTE visibleCommonNameValue[] = {
1145  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1146 static BYTE generalCommonNameValue[] = {
1147  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1148 static BYTE bmpCommonNameValue[] = {
1149  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1150  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1151 static BYTE utf8CommonNameValue[] = {
1152  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1153
1154 static struct EncodedNameValue nameValues[] = {
1155  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1156      octetCommonNameValue, sizeof(octetCommonNameValue) },
1157  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1158      numericCommonNameValue, sizeof(numericCommonNameValue) },
1159  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1160      printableCommonNameValue, sizeof(printableCommonNameValue) },
1161  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1162      t61CommonNameValue, sizeof(t61CommonNameValue) },
1163  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1164      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1165  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1166      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1167  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1168      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1169  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1170      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1171  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1172      generalCommonNameValue, sizeof(generalCommonNameValue) },
1173  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1174      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1175  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1176      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1177  /* The following tests succeed under Windows, but really should fail,
1178   * they contain characters that are illegal for the encoding.  I'm
1179   * including them to justify my lazy encoding.
1180   */
1181  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1182      sizeof(bin42) },
1183  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1184      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1185  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1186      bin44, sizeof(bin44) },
1187 };
1188
1189 static void test_encodeNameValue(DWORD dwEncoding)
1190 {
1191     BYTE *buf = NULL;
1192     DWORD size = 0, i;
1193     BOOL ret;
1194     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1195
1196     value.dwValueType = 14;
1197     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1198      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1199     ok(!ret && GetLastError() == CRYPT_E_ASN1_CHOICE,
1200      "Expected CRYPT_E_ASN1_CHOICE, got %08x\n", GetLastError());
1201     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1202     value.Value.pbData = printableCommonNameValue;
1203     value.Value.cbData = sizeof(printableCommonNameValue);
1204     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1205      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1206     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1207     if (buf)
1208     {
1209         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1210          size);
1211         ok(!memcmp(buf, printableCommonNameValue, size),
1212          "Unexpected encoding\n");
1213         LocalFree(buf);
1214     }
1215     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1216     {
1217         ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1218          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1219          &size);
1220         ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1221          nameValues[i].value.dwValueType, GetLastError());
1222         if (buf)
1223         {
1224             ok(size == nameValues[i].encodedSize,
1225              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1226             ok(!memcmp(buf, nameValues[i].encoded, size),
1227              "Got unexpected encoding\n");
1228             LocalFree(buf);
1229         }
1230     }
1231 }
1232
1233 static void test_decodeNameValue(DWORD dwEncoding)
1234 {
1235     int i;
1236     BYTE *buf = NULL;
1237     DWORD bufSize = 0;
1238     BOOL ret;
1239
1240     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1241     {
1242         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1243          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1244          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1245          (BYTE *)&buf, &bufSize);
1246         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1247          nameValues[i].value.dwValueType, GetLastError());
1248         if (buf)
1249         {
1250             compareNameValues(&nameValues[i].value,
1251              (const CERT_NAME_VALUE *)buf);
1252             LocalFree(buf);
1253         }
1254     }
1255 }
1256
1257 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1258 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1259  'h','q','.','o','r','g',0 };
1260 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1261  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1262  0x6f, 0x72, 0x67 };
1263 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1264  0x575b, 0 };
1265 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1266 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1267  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1268 static const BYTE localhost[] = { 127, 0, 0, 1 };
1269 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1270  0x01 };
1271
1272 static void test_encodeAltName(DWORD dwEncoding)
1273 {
1274     CERT_ALT_NAME_INFO info = { 0 };
1275     CERT_ALT_NAME_ENTRY entry = { 0 };
1276     BYTE *buf = NULL;
1277     DWORD size = 0;
1278     BOOL ret;
1279
1280     /* Test with empty info */
1281     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1282      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1283     if (buf)
1284     {
1285         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1286         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1287         LocalFree(buf);
1288     }
1289     /* Test with an empty entry */
1290     info.cAltEntry = 1;
1291     info.rgAltEntry = &entry;
1292     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1293      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1294     ok(!ret && GetLastError() == E_INVALIDARG,
1295      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1296     /* Test with an empty pointer */
1297     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1298     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1299      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1300     if (buf)
1301     {
1302         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1303         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1304         LocalFree(buf);
1305     }
1306     /* Test with a real URL */
1307     U(entry).pwszURL = (LPWSTR)url;
1308     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1309      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1310     if (buf)
1311     {
1312         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1313         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1314         LocalFree(buf);
1315     }
1316     /* Now with the URL containing an invalid IA5 char */
1317     U(entry).pwszURL = (LPWSTR)nihongoURL;
1318     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1319      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1320     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1321      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1322     /* The first invalid character is at index 7 */
1323     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1324      "Expected invalid char at index 7, got %d\n",
1325      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1326     /* Now with the URL missing a scheme */
1327     U(entry).pwszURL = (LPWSTR)dnsName;
1328     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1329      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1330     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1331     if (buf)
1332     {
1333         /* This succeeds, but it shouldn't, so don't worry about conforming */
1334         LocalFree(buf);
1335     }
1336     /* Now with a DNS name */
1337     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1338     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1339      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1340     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1341     if (buf)
1342     {
1343         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1344         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1345         LocalFree(buf);
1346     }
1347     /* Test with an IP address */
1348     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1349     U(entry).IPAddress.cbData = sizeof(localhost);
1350     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1351     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1352      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1353     if (buf)
1354     {
1355         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1356         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1357         LocalFree(buf);
1358     }
1359 }
1360
1361 static void test_decodeAltName(DWORD dwEncoding)
1362 {
1363     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1364      0x00, 0x00, 0x01 };
1365     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1366      0x01 };
1367     BOOL ret;
1368     BYTE *buf = NULL;
1369     DWORD bufSize = 0;
1370     CERT_ALT_NAME_INFO *info;
1371
1372     /* Test some bogus ones first */
1373     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1374      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1375      NULL, (BYTE *)&buf, &bufSize);
1376     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1377      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1378     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1379      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1380      &bufSize);
1381     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1382      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1383     /* Now expected cases */
1384     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1385      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1386      &bufSize);
1387     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1388     if (buf)
1389     {
1390         info = (CERT_ALT_NAME_INFO *)buf;
1391
1392         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1393          info->cAltEntry);
1394         LocalFree(buf);
1395     }
1396     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1397      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1398      &bufSize);
1399     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1400     if (buf)
1401     {
1402         info = (CERT_ALT_NAME_INFO *)buf;
1403
1404         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1405          info->cAltEntry);
1406         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1407          "Expected CERT_ALT_NAME_URL, got %d\n",
1408          info->rgAltEntry[0].dwAltNameChoice);
1409         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1410          "Expected empty URL\n");
1411         LocalFree(buf);
1412     }
1413     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1414      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1415      &bufSize);
1416     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1417     if (buf)
1418     {
1419         info = (CERT_ALT_NAME_INFO *)buf;
1420
1421         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1422          info->cAltEntry);
1423         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1424          "Expected CERT_ALT_NAME_URL, got %d\n",
1425          info->rgAltEntry[0].dwAltNameChoice);
1426         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1427         LocalFree(buf);
1428     }
1429     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1430      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1431      &bufSize);
1432     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1433     if (buf)
1434     {
1435         info = (CERT_ALT_NAME_INFO *)buf;
1436
1437         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1438          info->cAltEntry);
1439         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1440          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1441          info->rgAltEntry[0].dwAltNameChoice);
1442         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1443          "Unexpected DNS name\n");
1444         LocalFree(buf);
1445     }
1446     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1447      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1448      &bufSize);
1449     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1450     if (buf)
1451     {
1452         info = (CERT_ALT_NAME_INFO *)buf;
1453
1454         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1455          info->cAltEntry);
1456         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1457          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1458          info->rgAltEntry[0].dwAltNameChoice);
1459         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1460          "Unexpected IP address length %d\n",
1461           U(info->rgAltEntry[0]).IPAddress.cbData);
1462         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1463          sizeof(localhost)), "Unexpected IP address value\n");
1464         LocalFree(buf);
1465     }
1466 }
1467
1468 struct UnicodeExpectedError
1469 {
1470     DWORD   valueType;
1471     LPCWSTR str;
1472     DWORD   errorIndex;
1473     DWORD   error;
1474 };
1475
1476 static const WCHAR oneW[] = { '1',0 };
1477 static const WCHAR aW[] = { 'a',0 };
1478 static const WCHAR quoteW[] = { '"', 0 };
1479
1480 static struct UnicodeExpectedError unicodeErrors[] = {
1481  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1482  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1483  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1484  { 14,                        oneW,       0, CRYPT_E_ASN1_CHOICE },
1485  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1486  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1487  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1488 };
1489
1490 struct UnicodeExpectedResult
1491 {
1492     DWORD           valueType;
1493     LPCWSTR         str;
1494     CRYPT_DATA_BLOB encoded;
1495 };
1496
1497 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1498 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1499 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1500 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1501 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1502 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1503 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1504 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1505 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1506 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1507 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1508 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1509  0x5b };
1510 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1511  0x6f,0x5b };
1512 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1513  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1514 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1515  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1516
1517 static struct UnicodeExpectedResult unicodeResults[] = {
1518  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1519  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1520  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1521  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1522  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1523  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1524  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1525  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1526  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1527  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1528  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1529  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1530  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1531 };
1532
1533 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1534  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1535  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1536 };
1537
1538 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1539 {
1540     BYTE *buf = NULL;
1541     DWORD size = 0, i;
1542     BOOL ret;
1543     CERT_NAME_VALUE value;
1544
1545     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1546      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1547     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1548      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1549     /* Have to have a string of some sort */
1550     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1551     value.Value.pbData = NULL;
1552     value.Value.cbData = 0;
1553     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1554      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1555     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1556      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1557     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1558     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1559      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1560     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1561      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1562     value.dwValueType = CERT_RDN_ANY_TYPE;
1563     value.Value.pbData = (LPBYTE)oneW;
1564     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1565      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1566     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1567      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1568     value.Value.cbData = sizeof(oneW);
1569     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1570      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1571     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1572      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1573     /* An encoded string with specified length isn't good enough either */
1574     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1575     value.Value.pbData = oneUniversal;
1576     value.Value.cbData = sizeof(oneUniversal);
1577     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1578      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1579     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1580      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1581     /* More failure checking */
1582     value.Value.cbData = 0;
1583     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1584     {
1585         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1586         value.dwValueType = unicodeErrors[i].valueType;
1587         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1588          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1589         ok(!ret && GetLastError() == unicodeErrors[i].error,
1590          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1591          unicodeErrors[i].error, GetLastError());
1592         ok(size == unicodeErrors[i].errorIndex,
1593          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1594          size);
1595     }
1596     /* cbData can be zero if the string is NULL-terminated */
1597     value.Value.cbData = 0;
1598     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1599     {
1600         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1601         value.dwValueType = unicodeResults[i].valueType;
1602         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1603          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1604         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1605         if (buf)
1606         {
1607             ok(size == unicodeResults[i].encoded.cbData,
1608              "Value type %d: expected size %d, got %d\n",
1609              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1610             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1611              "Value type %d: unexpected value\n", value.dwValueType);
1612             LocalFree(buf);
1613         }
1614     }
1615     /* These "encode," but they do so by truncating each unicode character
1616      * rather than properly encoding it.  Kept separate from the proper results,
1617      * because the encoded forms won't decode to their original strings.
1618      */
1619     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1620     {
1621         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1622         value.dwValueType = unicodeWeirdness[i].valueType;
1623         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1624          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1625         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1626         if (buf)
1627         {
1628             ok(size == unicodeWeirdness[i].encoded.cbData,
1629              "Value type %d: expected size %d, got %d\n",
1630              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1631             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1632              "Value type %d: unexpected value\n", value.dwValueType);
1633             LocalFree(buf);
1634         }
1635     }
1636 }
1637
1638 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1639 {
1640     if (n <= 0) return 0;
1641     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1642     return *str1 - *str2;
1643 }
1644
1645 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1646 {
1647     DWORD i;
1648
1649     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1650     {
1651         BYTE *buf = NULL;
1652         BOOL ret;
1653         DWORD size = 0;
1654
1655         ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1656          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1657          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1658         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1659         if (ret && buf)
1660         {
1661             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1662
1663             ok(value->dwValueType == unicodeResults[i].valueType,
1664              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1665              value->dwValueType);
1666             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1667              value->Value.cbData / sizeof(WCHAR)),
1668              "Unexpected decoded value for index %d (value type %d)\n", i,
1669              unicodeResults[i].valueType);
1670             LocalFree(buf);
1671         }
1672     }
1673 }
1674
1675 struct encodedOctets
1676 {
1677     const BYTE *val;
1678     const BYTE *encoded;
1679 };
1680
1681 static const unsigned char bin46[] = { 'h','i',0 };
1682 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1683 static const unsigned char bin48[] = {
1684      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1685 static const unsigned char bin49[] = {
1686      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1687 static const unsigned char bin50[] = { 0 };
1688 static const unsigned char bin51[] = { 0x04,0x00,0 };
1689
1690 static const struct encodedOctets octets[] = {
1691     { bin46, bin47 },
1692     { bin48, bin49 },
1693     { bin50, bin51 },
1694 };
1695
1696 static void test_encodeOctets(DWORD dwEncoding)
1697 {
1698     CRYPT_DATA_BLOB blob;
1699     DWORD i;
1700
1701     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1702     {
1703         BYTE *buf = NULL;
1704         BOOL ret;
1705         DWORD bufSize = 0;
1706
1707         blob.cbData = strlen((const char*)octets[i].val);
1708         blob.pbData = (BYTE*)octets[i].val;
1709         ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1710          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1711         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1712         if (buf)
1713         {
1714             ok(buf[0] == 4,
1715              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1716             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1717              buf[1], octets[i].encoded[1]);
1718             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1719              octets[i].encoded[1] + 1), "Got unexpected value\n");
1720             LocalFree(buf);
1721         }
1722     }
1723 }
1724
1725 static void test_decodeOctets(DWORD dwEncoding)
1726 {
1727     DWORD i;
1728
1729     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1730     {
1731         BYTE *buf = NULL;
1732         BOOL ret;
1733         DWORD bufSize = 0;
1734
1735         ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1736          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1737          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1738         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1739         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1740          "Expected size >= %d, got %d\n",
1741            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1742         ok(buf != NULL, "Expected allocated buffer\n");
1743         if (buf)
1744         {
1745             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1746
1747             if (blob->cbData)
1748                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1749                  "Unexpected value\n");
1750             LocalFree(buf);
1751         }
1752     }
1753 }
1754
1755 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1756
1757 struct encodedBits
1758 {
1759     DWORD cUnusedBits;
1760     const BYTE *encoded;
1761     DWORD cbDecoded;
1762     const BYTE *decoded;
1763 };
1764
1765 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1766 static const unsigned char bin53[] = { 0xff,0xff };
1767 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1768 static const unsigned char bin55[] = { 0xff,0xfe };
1769 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1770 static const unsigned char bin57[] = { 0xfe };
1771 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1772
1773 static const struct encodedBits bits[] = {
1774     /* normal test cases */
1775     { 0, bin52, 2, bin53 },
1776     { 1, bin54, 2, bin55 },
1777     /* strange test case, showing cUnusedBits >= 8 is allowed */
1778     { 9, bin56, 1, bin57 },
1779     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1780     { 17, bin58, 0, NULL },
1781 };
1782
1783 static void test_encodeBits(DWORD dwEncoding)
1784 {
1785     DWORD i;
1786
1787     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1788     {
1789         CRYPT_BIT_BLOB blob;
1790         BOOL ret;
1791         BYTE *buf = NULL;
1792         DWORD bufSize = 0;
1793
1794         blob.cbData = sizeof(bytesToEncode);
1795         blob.pbData = (BYTE *)bytesToEncode;
1796         blob.cUnusedBits = bits[i].cUnusedBits;
1797         ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1798          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1799         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1800         if (buf)
1801         {
1802             ok(bufSize == bits[i].encoded[1] + 2,
1803              "Got unexpected size %d, expected %d\n", bufSize,
1804              bits[i].encoded[1] + 2);
1805             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1806              "Unexpected value\n");
1807             LocalFree(buf);
1808         }
1809     }
1810 }
1811
1812 static void test_decodeBits(DWORD dwEncoding)
1813 {
1814     static const BYTE ber[] = "\x03\x02\x01\xff";
1815     static const BYTE berDecoded = 0xfe;
1816     DWORD i;
1817     BOOL ret;
1818     BYTE *buf = NULL;
1819     DWORD bufSize = 0;
1820
1821     /* normal cases */
1822     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1823     {
1824         ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1825          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1826          &bufSize);
1827         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1828         if (buf)
1829         {
1830             CRYPT_BIT_BLOB *blob;
1831
1832             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1833                "Got unexpected size %d\n", bufSize);
1834             blob = (CRYPT_BIT_BLOB *)buf;
1835             ok(blob->cbData == bits[i].cbDecoded,
1836              "Got unexpected length %d, expected %d\n", blob->cbData,
1837              bits[i].cbDecoded);
1838             if (blob->cbData && bits[i].cbDecoded)
1839                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1840                  "Unexpected value\n");
1841             LocalFree(buf);
1842         }
1843     }
1844     /* special case: check that something that's valid in BER but not in DER
1845      * decodes successfully
1846      */
1847     ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1848      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1849     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1850     if (buf)
1851     {
1852         CRYPT_BIT_BLOB *blob;
1853
1854         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1855            "Got unexpected size %d\n", bufSize);
1856         blob = (CRYPT_BIT_BLOB *)buf;
1857         ok(blob->cbData == sizeof(berDecoded),
1858            "Got unexpected length %d\n", blob->cbData);
1859         if (blob->cbData)
1860             ok(*blob->pbData == berDecoded, "Unexpected value\n");
1861         LocalFree(buf);
1862     }
1863 }
1864
1865 struct Constraints2
1866 {
1867     CERT_BASIC_CONSTRAINTS2_INFO info;
1868     const BYTE *encoded;
1869 };
1870
1871 static const unsigned char bin59[] = { 0x30,0x00 };
1872 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1873 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1874 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1875 static const struct Constraints2 constraints2[] = {
1876  /* empty constraints */
1877  { { FALSE, FALSE, 0}, bin59 },
1878  /* can be a CA */
1879  { { TRUE,  FALSE, 0}, bin60 },
1880  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1881   * but that's not the case
1882   */
1883  { { FALSE, TRUE,  0}, bin61 },
1884  /* can be a CA and has path length constraints set */
1885  { { TRUE,  TRUE,  1}, bin62 },
1886 };
1887
1888 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1889 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1890  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1891  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1892  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1893 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1894  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1895  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1896  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1897  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1898
1899 static void test_encodeBasicConstraints(DWORD dwEncoding)
1900 {
1901     DWORD i, bufSize = 0;
1902     CERT_BASIC_CONSTRAINTS_INFO info;
1903     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1904      (LPBYTE)encodedDomainName };
1905     BOOL ret;
1906     BYTE *buf = NULL;
1907
1908     /* First test with the simpler info2 */
1909     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1910     {
1911         ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1912          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1913          &bufSize);
1914         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1915         if (buf)
1916         {
1917             ok(bufSize == constraints2[i].encoded[1] + 2,
1918              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
1919              bufSize);
1920             ok(!memcmp(buf, constraints2[i].encoded,
1921              constraints2[i].encoded[1] + 2), "Unexpected value\n");
1922             LocalFree(buf);
1923         }
1924     }
1925     /* Now test with more complex basic constraints */
1926     info.SubjectType.cbData = 0;
1927     info.fPathLenConstraint = FALSE;
1928     info.cSubtreesConstraint = 0;
1929     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1930      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1931     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1932     if (buf)
1933     {
1934         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
1935         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1936          "Unexpected value\n");
1937         LocalFree(buf);
1938     }
1939     /* None of the certs I examined had any subtree constraint, but I test one
1940      * anyway just in case.
1941      */
1942     info.cSubtreesConstraint = 1;
1943     info.rgSubtreesConstraint = &nameBlob;
1944     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1945      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1946     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1947     if (buf)
1948     {
1949         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
1950         ok(!memcmp(buf, constraintWithDomainName,
1951          sizeof(constraintWithDomainName)), "Unexpected value\n");
1952         LocalFree(buf);
1953     }
1954     /* FIXME: test encoding with subject type. */
1955 }
1956
1957 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1958 static const unsigned char encodedCommonName[] = {
1959     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1960
1961 static void test_decodeBasicConstraints(DWORD dwEncoding)
1962 {
1963     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1964      0xff };
1965     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1966     DWORD i;
1967     BOOL ret;
1968     BYTE *buf = NULL;
1969     DWORD bufSize = 0;
1970
1971     /* First test with simpler info2 */
1972     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1973     {
1974         ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1975          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1976          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1977         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
1978          GetLastError());
1979         if (buf)
1980         {
1981             CERT_BASIC_CONSTRAINTS2_INFO *info =
1982              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1983
1984             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1985              "Unexpected value for item %d\n", i);
1986             LocalFree(buf);
1987         }
1988     }
1989     /* Check with the order of encoded elements inverted */
1990     buf = (PBYTE)1;
1991     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1992      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1993      &bufSize);
1994     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1995      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1996     ok(!buf, "Expected buf to be set to NULL\n");
1997     /* Check with a non-DER bool */
1998     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1999      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2000      (BYTE *)&buf, &bufSize);
2001     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2002     if (buf)
2003     {
2004         CERT_BASIC_CONSTRAINTS2_INFO *info =
2005          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2006
2007         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2008         LocalFree(buf);
2009     }
2010     /* Check with a non-basic constraints value */
2011     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2012      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2013      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2014     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2015      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2016     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2017     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2018      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2019      (BYTE *)&buf, &bufSize);
2020     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2021     if (buf)
2022     {
2023         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2024
2025         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2026         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2027         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2028         LocalFree(buf);
2029     }
2030     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2031      constraintWithDomainName, sizeof(constraintWithDomainName),
2032      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2033     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2034     if (buf)
2035     {
2036         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2037
2038         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2039         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2040         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2041         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2042         {
2043             ok(info->rgSubtreesConstraint[0].cbData ==
2044              sizeof(encodedDomainName), "Wrong size %d\n",
2045              info->rgSubtreesConstraint[0].cbData);
2046             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2047              sizeof(encodedDomainName)), "Unexpected value\n");
2048         }
2049         LocalFree(buf);
2050     }
2051 }
2052
2053 /* These are terrible public keys of course, I'm just testing encoding */
2054 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2055 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2056 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2057 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2058 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2059 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2060 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2061 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2062
2063 struct EncodedRSAPubKey
2064 {
2065     const BYTE *modulus;
2066     size_t modulusLen;
2067     const BYTE *encoded;
2068     size_t decodedModulusLen;
2069 };
2070
2071 struct EncodedRSAPubKey rsaPubKeys[] = {
2072     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2073     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2074     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2075     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2076 };
2077
2078 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2079 {
2080     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2081     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2082     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2083     BOOL ret;
2084     BYTE *buf = NULL;
2085     DWORD bufSize = 0, i;
2086
2087     /* Try with a bogus blob type */
2088     hdr->bType = 2;
2089     hdr->bVersion = CUR_BLOB_VERSION;
2090     hdr->reserved = 0;
2091     hdr->aiKeyAlg = CALG_RSA_KEYX;
2092     rsaPubKey->magic = 0x31415352;
2093     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2094     rsaPubKey->pubexp = 65537;
2095     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2096      sizeof(modulus1));
2097
2098     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2099      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2100      &bufSize);
2101     ok(!ret && GetLastError() == E_INVALIDARG,
2102      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2103     /* Now with a bogus reserved field */
2104     hdr->bType = PUBLICKEYBLOB;
2105     hdr->reserved = 1;
2106     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2107      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2108      &bufSize);
2109     if (buf)
2110     {
2111         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2112          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2113         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2114         LocalFree(buf);
2115     }
2116     /* Now with a bogus blob version */
2117     hdr->reserved = 0;
2118     hdr->bVersion = 0;
2119     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2120      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2121      &bufSize);
2122     if (buf)
2123     {
2124         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2125          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2126         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2127         LocalFree(buf);
2128     }
2129     /* And with a bogus alg ID */
2130     hdr->bVersion = CUR_BLOB_VERSION;
2131     hdr->aiKeyAlg = CALG_DES;
2132     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2133      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2134      &bufSize);
2135     if (buf)
2136     {
2137         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2138          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2139         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2140         LocalFree(buf);
2141     }
2142     /* Check a couple of RSA-related OIDs */
2143     hdr->aiKeyAlg = CALG_RSA_KEYX;
2144     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2145      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2146     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2147      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2148     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2149      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2150     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2151      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2152     /* Finally, all valid */
2153     hdr->aiKeyAlg = CALG_RSA_KEYX;
2154     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2155     {
2156         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2157          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2158         ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2159          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2160         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2161         if (buf)
2162         {
2163             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2164              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2165              bufSize);
2166             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2167              "Unexpected value\n");
2168             LocalFree(buf);
2169         }
2170     }
2171 }
2172
2173 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2174 {
2175     DWORD i;
2176     LPBYTE buf = NULL;
2177     DWORD bufSize = 0;
2178     BOOL ret;
2179
2180     /* Try with a bad length */
2181     ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2182      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2183      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2184     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2185      "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2186     /* Try with a couple of RSA-related OIDs */
2187     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2188      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2189      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2190     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2191      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2192     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2193      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2194      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2195     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2196      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2197     /* Now try success cases */
2198     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2199     {
2200         bufSize = 0;
2201         ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2202          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2203          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2204         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2205         if (buf)
2206         {
2207             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2208             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2209
2210             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2211              rsaPubKeys[i].decodedModulusLen,
2212              "Wrong size %d\n", bufSize);
2213             ok(hdr->bType == PUBLICKEYBLOB,
2214              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2215              hdr->bType);
2216             ok(hdr->bVersion == CUR_BLOB_VERSION,
2217              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2218              CUR_BLOB_VERSION, hdr->bVersion);
2219             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2220              hdr->reserved);
2221             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2222              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2223             ok(rsaPubKey->magic == 0x31415352,
2224              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2225             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2226              "Wrong bit len %d\n", rsaPubKey->bitlen);
2227             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2228              rsaPubKey->pubexp);
2229             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2230              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2231              "Unexpected modulus\n");
2232             LocalFree(buf);
2233         }
2234     }
2235 }
2236
2237 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2238  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2239  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2240
2241 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2242  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2243  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2244  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2245
2246 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2247 {
2248     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2249     CRYPT_SEQUENCE_OF_ANY seq;
2250     DWORD i;
2251     BOOL ret;
2252     BYTE *buf = NULL;
2253     DWORD bufSize = 0;
2254
2255     /* Encode a homogenous sequence */
2256     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2257     {
2258         blobs[i].cbData = ints[i].encoded[1] + 2;
2259         blobs[i].pbData = (BYTE *)ints[i].encoded;
2260     }
2261     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2262     seq.rgValue = blobs;
2263
2264     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2265      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2266     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2267     if (buf)
2268     {
2269         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2270         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2271         LocalFree(buf);
2272     }
2273     /* Change the type of the first element in the sequence, and give it
2274      * another go
2275      */
2276     blobs[0].cbData = times[0].encodedTime[1] + 2;
2277     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2278     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2279      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2280     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2281     if (buf)
2282     {
2283         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2284         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2285          "Unexpected value\n");
2286         LocalFree(buf);
2287     }
2288 }
2289
2290 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2291 {
2292     BOOL ret;
2293     BYTE *buf = NULL;
2294     DWORD bufSize = 0;
2295
2296     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2297      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2298     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2299     if (buf)
2300     {
2301         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2302         DWORD i;
2303
2304         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2305          "Wrong elements %d\n", seq->cValue);
2306         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2307         {
2308             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2309              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2310              seq->rgValue[i].cbData);
2311             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2312              ints[i].encoded[1] + 2), "Unexpected value\n");
2313         }
2314         LocalFree(buf);
2315     }
2316     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2317      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2318      &bufSize);
2319     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2320     if (buf)
2321     {
2322         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2323
2324         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2325          "Wrong elements %d\n", seq->cValue);
2326         /* Just check the first element since it's all that changed */
2327         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2328          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2329          seq->rgValue[0].cbData);
2330         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2331          times[0].encodedTime[1] + 2), "Unexpected value\n");
2332         LocalFree(buf);
2333     }
2334 }
2335
2336 struct encodedExtensions
2337 {
2338     CERT_EXTENSIONS exts;
2339     const BYTE *encoded;
2340 };
2341
2342 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2343 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2344 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2345 static CERT_EXTENSION criticalExt =
2346  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2347 static CERT_EXTENSION nonCriticalExt =
2348  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2349
2350 static const BYTE ext0[] = { 0x30,0x00 };
2351 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2352                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2353 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2354                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2355
2356 static const struct encodedExtensions exts[] = {
2357  { { 0, NULL }, ext0 },
2358  { { 1, &criticalExt }, ext1 },
2359  { { 1, &nonCriticalExt }, ext2 },
2360 };
2361
2362 static void test_encodeExtensions(DWORD dwEncoding)
2363 {
2364     DWORD i;
2365
2366     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2367     {
2368         BOOL ret;
2369         BYTE *buf = NULL;
2370         DWORD bufSize = 0;
2371
2372         ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2373          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2374         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2375         if (buf)
2376         {
2377             ok(bufSize == exts[i].encoded[1] + 2,
2378              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2379             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2380              "Unexpected value\n");
2381             LocalFree(buf);
2382         }
2383     }
2384 }
2385
2386 static void test_decodeExtensions(DWORD dwEncoding)
2387 {
2388     DWORD i;
2389
2390     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2391     {
2392         BOOL ret;
2393         BYTE *buf = NULL;
2394         DWORD bufSize = 0;
2395
2396         ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2397          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2398          NULL, (BYTE *)&buf, &bufSize);
2399         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2400         if (buf)
2401         {
2402             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2403             DWORD j;
2404
2405             ok(ext->cExtension == exts[i].exts.cExtension,
2406              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2407              ext->cExtension);
2408             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2409             {
2410                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2411                  exts[i].exts.rgExtension[j].pszObjId),
2412                  "Expected OID %s, got %s\n",
2413                  exts[i].exts.rgExtension[j].pszObjId,
2414                  ext->rgExtension[j].pszObjId);
2415                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2416                  exts[i].exts.rgExtension[j].Value.pbData,
2417                  exts[i].exts.rgExtension[j].Value.cbData),
2418                  "Unexpected value\n");
2419             }
2420             LocalFree(buf);
2421         }
2422     }
2423 }
2424
2425 /* MS encodes public key info with a NULL if the algorithm identifier's
2426  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2427  * it encodes them by omitting the algorithm parameters.  This latter approach
2428  * seems more correct, so accept either form.
2429  */
2430 struct encodedPublicKey
2431 {
2432     CERT_PUBLIC_KEY_INFO info;
2433     const BYTE *encoded;
2434     const BYTE *encodedNoNull;
2435     CERT_PUBLIC_KEY_INFO decoded;
2436 };
2437
2438 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2439  0xe, 0xf };
2440 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2441
2442 static const unsigned char bin64[] = {
2443     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2444 static const unsigned char bin65[] = {
2445     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2446 static const unsigned char bin66[] = {
2447     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2448 static const unsigned char bin67[] = {
2449     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2450 static const unsigned char bin68[] = {
2451     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2452     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2453 static const unsigned char bin69[] = {
2454     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2455     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2456 static const unsigned char bin70[] = {
2457     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2458     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2459     0x0f};
2460 static const unsigned char bin71[] = {
2461     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2462     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2463     0x0f};
2464 static unsigned char bin72[] = { 0x05,0x00};
2465
2466 static CHAR oid_bogus[] = "1.2.3",
2467             oid_rsa[]   = szOID_RSA;
2468
2469 static const struct encodedPublicKey pubKeys[] = {
2470  /* with a bogus OID */
2471  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2472   bin64, bin65,
2473   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2474  /* some normal keys */
2475  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2476   bin66, bin67,
2477   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2478  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2479   bin68, bin69,
2480   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2481  /* with add'l parameters--note they must be DER-encoded */
2482  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2483   (BYTE *)aKey, 0 } },
2484   bin70, bin71,
2485   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2486   (BYTE *)aKey, 0 } } },
2487 };
2488
2489 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2490 {
2491     DWORD i;
2492
2493     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2494     {
2495         BOOL ret;
2496         BYTE *buf = NULL;
2497         DWORD bufSize = 0;
2498
2499         ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2500          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2501          &bufSize);
2502         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2503         if (buf)
2504         {
2505             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2506              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2507              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2508              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2509             if (bufSize == pubKeys[i].encoded[1] + 2)
2510                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2511                  "Unexpected value\n");
2512             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2513                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2514                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2515             LocalFree(buf);
2516         }
2517     }
2518 }
2519
2520 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2521  const CERT_PUBLIC_KEY_INFO *got)
2522 {
2523     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2524      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2525      got->Algorithm.pszObjId);
2526     ok(expected->Algorithm.Parameters.cbData ==
2527      got->Algorithm.Parameters.cbData,
2528      "Expected parameters of %d bytes, got %d\n",
2529      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2530     if (expected->Algorithm.Parameters.cbData)
2531         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2532          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2533          "Unexpected algorithm parameters\n");
2534     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2535      "Expected public key of %d bytes, got %d\n",
2536      expected->PublicKey.cbData, got->PublicKey.cbData);
2537     if (expected->PublicKey.cbData)
2538         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2539          got->PublicKey.cbData), "Unexpected public key value\n");
2540 }
2541
2542 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2543 {
2544     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2545      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2546      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2547      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2548     DWORD i;
2549     BOOL ret;
2550     BYTE *buf = NULL;
2551     DWORD bufSize = 0;
2552
2553     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2554     {
2555         /* The NULL form decodes to the decoded member */
2556         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2557          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2558          NULL, (BYTE *)&buf, &bufSize);
2559         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2560         if (buf)
2561         {
2562             comparePublicKeyInfo(&pubKeys[i].decoded,
2563              (CERT_PUBLIC_KEY_INFO *)buf);
2564             LocalFree(buf);
2565         }
2566         /* The non-NULL form decodes to the original */
2567         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2568          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2569          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2570         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2571         if (buf)
2572         {
2573             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2574             LocalFree(buf);
2575         }
2576     }
2577     /* Test with bogus (not valid DER) parameters */
2578     ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2579      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2580      NULL, (BYTE *)&buf, &bufSize);
2581     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2582      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2583 }
2584
2585 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2586  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2587  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2588  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2589  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2590 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2591  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2592  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2593  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2594  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2595 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2596  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2597  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2598  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2599  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2600 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2601  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2602  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2603  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2604  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2605  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2606  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2607 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2608  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2609  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2610  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2611  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2612  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2613  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2614 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2615  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2616  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2617  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2618  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2619  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2620  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2621  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2622  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2623  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2624
2625 static const BYTE serialNum[] = { 0x01 };
2626
2627 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2628 {
2629     BOOL ret;
2630     BYTE *buf = NULL;
2631     DWORD size = 0;
2632     CERT_INFO info = { 0 };
2633
2634     /* Test with NULL pvStructInfo */
2635     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2636      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2637     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2638      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2639     /* Test with a V1 cert */
2640     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2641      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2642     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2643     if (buf)
2644     {
2645         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2646          v1Cert[1] + 2, size);
2647         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2648         LocalFree(buf);
2649     }
2650     /* Test v2 cert */
2651     info.dwVersion = CERT_V2;
2652     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2653      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2654     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2655     if (buf)
2656     {
2657         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2658         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2659         LocalFree(buf);
2660     }
2661     /* Test v3 cert */
2662     info.dwVersion = CERT_V3;
2663     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2664      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2665     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2666     if (buf)
2667     {
2668         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2669         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2670         LocalFree(buf);
2671     }
2672     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2673      * API doesn't prevent it)
2674      */
2675     info.dwVersion = CERT_V1;
2676     info.cExtension = 1;
2677     info.rgExtension = &criticalExt;
2678     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2679      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2680     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2681     if (buf)
2682     {
2683         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2684         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2685         LocalFree(buf);
2686     }
2687     /* test v1 cert with a serial number */
2688     info.SerialNumber.cbData = sizeof(serialNum);
2689     info.SerialNumber.pbData = (BYTE *)serialNum;
2690     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2691      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2692     if (buf)
2693     {
2694         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2695         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2696         LocalFree(buf);
2697     }
2698     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2699     info.Issuer.cbData = sizeof(encodedCommonName);
2700     info.Issuer.pbData = (BYTE *)encodedCommonName;
2701     info.Subject.cbData = sizeof(encodedCommonName);
2702     info.Subject.pbData = (BYTE *)encodedCommonName;
2703     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2704      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2705     if (buf)
2706     {
2707         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2708         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2709         LocalFree(buf);
2710     }
2711     /* for now, I let more interesting tests be done for each subcomponent,
2712      * rather than retesting them all here.
2713      */
2714 }
2715
2716 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2717 {
2718     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2719      v1CertWithConstraints, v1CertWithSerial };
2720     BOOL ret;
2721     BYTE *buf = NULL;
2722     DWORD size = 0, i;
2723
2724     /* Test with NULL pbEncoded */
2725     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2726      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2727     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2728      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2729     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2730      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2731     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2732      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2733     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2734      * minimum a cert must have a non-zero serial number, an issuer, and a
2735      * subject.
2736      */
2737     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2738     {
2739         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2740          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2741          (BYTE *)&buf, &size);
2742         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2743          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2744     }
2745     /* Now check with serial number, subject and issuer specified */
2746     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2747      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2748     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2749     if (buf)
2750     {
2751         CERT_INFO *info = (CERT_INFO *)buf;
2752
2753         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2754         ok(info->SerialNumber.cbData == 1,
2755          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2756         ok(*info->SerialNumber.pbData == *serialNum,
2757          "Expected serial number %d, got %d\n", *serialNum,
2758          *info->SerialNumber.pbData);
2759         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2760          "Wrong size %d\n", info->Issuer.cbData);
2761         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2762          "Unexpected issuer\n");
2763         ok(info->Subject.cbData == sizeof(encodedCommonName),
2764          "Wrong size %d\n", info->Subject.cbData);
2765         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2766          info->Subject.cbData), "Unexpected subject\n");
2767         LocalFree(buf);
2768     }
2769 }
2770
2771 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2772  0xe, 0xf };
2773
2774 static const BYTE signedBigCert[] = {
2775  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2776  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2777  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2778  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2779  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2780  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2781  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2782  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2783  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2784  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2785  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2786  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2787
2788 static void test_encodeCert(DWORD dwEncoding)
2789 {
2790     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
2791      * also that bigCert is a NULL-terminated string, so don't count its
2792      * last byte (otherwise the signed cert won't decode.)
2793      */
2794     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2795      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2796     BOOL ret;
2797     BYTE *buf = NULL;
2798     DWORD bufSize = 0;
2799
2800     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2801      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2802     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2803     if (buf)
2804     {
2805         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
2806         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2807         LocalFree(buf);
2808     }
2809 }
2810
2811 static void test_decodeCert(DWORD dwEncoding)
2812 {
2813     BOOL ret;
2814     BYTE *buf = NULL;
2815     DWORD size = 0;
2816
2817     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2818      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2819     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2820     if (buf)
2821     {
2822         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2823
2824         ok(info->ToBeSigned.cbData == sizeof(bigCert),
2825          "Wrong cert size %d\n", info->ToBeSigned.cbData);
2826         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2827          "Unexpected cert\n");
2828         ok(info->Signature.cbData == sizeof(hash),
2829          "Wrong signature size %d\n", info->Signature.cbData);
2830         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2831          "Unexpected signature\n");
2832         LocalFree(buf);
2833     }
2834     /* A signed cert decodes as a CERT_INFO too */
2835     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2836      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2837     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2838     if (buf)
2839     {
2840         CERT_INFO *info = (CERT_INFO *)buf;
2841
2842         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2843         ok(info->SerialNumber.cbData == 1,
2844          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2845         ok(*info->SerialNumber.pbData == *serialNum,
2846          "Expected serial number %d, got %d\n", *serialNum,
2847          *info->SerialNumber.pbData);
2848         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2849          "Wrong size %d\n", info->Issuer.cbData);
2850         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2851          "Unexpected issuer\n");
2852         ok(info->Subject.cbData == sizeof(encodedCommonName),
2853          "Wrong size %d\n", info->Subject.cbData);
2854         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2855          info->Subject.cbData), "Unexpected subject\n");
2856         LocalFree(buf);
2857     }
2858 }
2859
2860 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2861 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2862  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2863  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2864 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2865  0x00, 0x03 };
2866 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2867  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2868  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2869 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2870  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2871  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2872  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2873  0x2e, 0x6f, 0x72, 0x67 };
2874 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2875  CRL_REASON_AFFILIATION_CHANGED;
2876
2877 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2878 {
2879     CRL_DIST_POINTS_INFO info = { 0 };
2880     CRL_DIST_POINT point = { { 0 } };
2881     CERT_ALT_NAME_ENTRY entry = { 0 };
2882     BOOL ret;
2883     BYTE *buf = NULL;
2884     DWORD size = 0;
2885
2886     /* Test with an empty info */
2887     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2888      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2889     ok(!ret && GetLastError() == E_INVALIDARG,
2890      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2891     /* Test with one empty dist point */
2892     info.cDistPoint = 1;
2893     info.rgDistPoint = &point;
2894     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2895      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2896     if (buf)
2897     {
2898         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
2899         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2900         LocalFree(buf);
2901     }
2902     /* A dist point with an invalid name */
2903     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2904     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2905     U(entry).pwszURL = (LPWSTR)nihongoURL;
2906     U(point.DistPointName).FullName.cAltEntry = 1;
2907     U(point.DistPointName).FullName.rgAltEntry = &entry;
2908     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2909      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2910     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2911      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
2912     /* The first invalid character is at index 7 */
2913     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2914      "Expected invalid char at index 7, got %d\n",
2915      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2916     /* A dist point with (just) a valid name */
2917     U(entry).pwszURL = (LPWSTR)url;
2918     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2919      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2920     if (buf)
2921     {
2922         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
2923         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2924         LocalFree(buf);
2925     }
2926     /* A dist point with (just) reason flags */
2927     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2928     point.ReasonFlags.cbData = sizeof(crlReason);
2929     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2930     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2931      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2932     if (buf)
2933     {
2934         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
2935         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2936         LocalFree(buf);
2937     }
2938     /* A dist point with just an issuer */
2939     point.ReasonFlags.cbData = 0;
2940     point.CRLIssuer.cAltEntry = 1;
2941     point.CRLIssuer.rgAltEntry = &entry;
2942     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2943      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2944     if (buf)
2945     {
2946         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
2947         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2948         LocalFree(buf);
2949     }
2950     /* A dist point with both a name and an issuer */
2951     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2952     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2953      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2954     if (buf)
2955     {
2956         ok(size == sizeof(distPointWithUrlAndIssuer),
2957          "Wrong size %d\n", size);
2958         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2959         LocalFree(buf);
2960     }
2961 }
2962
2963 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2964 {
2965     BOOL ret;
2966     BYTE *buf = NULL;
2967     DWORD size = 0;
2968     PCRL_DIST_POINTS_INFO info;
2969     PCRL_DIST_POINT point;
2970     PCERT_ALT_NAME_ENTRY entry;
2971
2972     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2973      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2974      (BYTE *)&buf, &size);
2975     if (ret)
2976     {
2977         info = (PCRL_DIST_POINTS_INFO)buf;
2978         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2979          "Wrong size %d\n", size);
2980         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
2981          info->cDistPoint);
2982         point = info->rgDistPoint;
2983         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2984          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
2985          point->DistPointName.dwDistPointNameChoice);
2986         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2987         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2988         LocalFree(buf);
2989     }
2990     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2991      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2992      (BYTE *)&buf, &size);
2993     if (ret)
2994     {
2995         info = (PCRL_DIST_POINTS_INFO)buf;
2996         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2997          "Wrong size %d\n", size);
2998         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
2999          info->cDistPoint);
3000         point = info->rgDistPoint;
3001         ok(point->DistPointName.dwDistPointNameChoice ==
3002          CRL_DIST_POINT_FULL_NAME,
3003          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3004          point->DistPointName.dwDistPointNameChoice);
3005         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3006          "Expected 1 name entry, got %d\n",
3007          U(point->DistPointName).FullName.cAltEntry);
3008         entry = U(point->DistPointName).FullName.rgAltEntry;
3009         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3010          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3011         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3012         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3013         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3014         LocalFree(buf);
3015     }
3016     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3017      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3018      NULL, (BYTE *)&buf, &size);
3019     if (ret)
3020     {
3021         info = (PCRL_DIST_POINTS_INFO)buf;
3022         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3023          "Wrong size %d\n", size);
3024         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3025          info->cDistPoint);
3026         point = info->rgDistPoint;
3027         ok(point->DistPointName.dwDistPointNameChoice ==
3028          CRL_DIST_POINT_NO_NAME,
3029          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3030          point->DistPointName.dwDistPointNameChoice);
3031         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3032          "Expected reason length\n");
3033         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3034          "Unexpected reason\n");
3035         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3036         LocalFree(buf);
3037     }
3038     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3039      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3040      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3041     if (ret)
3042     {
3043         info = (PCRL_DIST_POINTS_INFO)buf;
3044         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3045          "Wrong size %d\n", size);
3046         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3047          info->cDistPoint);
3048         point = info->rgDistPoint;
3049         ok(point->DistPointName.dwDistPointNameChoice ==
3050          CRL_DIST_POINT_FULL_NAME,
3051          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3052          point->DistPointName.dwDistPointNameChoice);
3053         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3054          "Expected 1 name entry, got %d\n",
3055          U(point->DistPointName).FullName.cAltEntry);
3056         entry = U(point->DistPointName).FullName.rgAltEntry;
3057         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3058          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3059         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3060         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3061         ok(point->CRLIssuer.cAltEntry == 1,
3062          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3063         entry = point->CRLIssuer.rgAltEntry;
3064         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3065          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3066         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3067         LocalFree(buf);
3068     }
3069 }
3070
3071 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3072 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3073 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3074  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3075  0x67 };
3076
3077 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3078 {
3079     BOOL ret;
3080     BYTE *buf = NULL;
3081     DWORD size = 0;
3082     CRL_ISSUING_DIST_POINT point = { { 0 } };
3083     CERT_ALT_NAME_ENTRY entry;
3084
3085     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3086      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3087     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3088      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3089     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3090      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3091     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3092     if (buf)
3093     {
3094         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3095         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3096         LocalFree(buf);
3097     }
3098     /* nonsensical flags */
3099     point.fOnlyContainsUserCerts = TRUE;
3100     point.fOnlyContainsCACerts = TRUE;
3101     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3102      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3103     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3104     if (buf)
3105     {
3106         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3107         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3108         LocalFree(buf);
3109     }
3110     /* unimplemented name type */
3111     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3112     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3113     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3114      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3115     ok(!ret && GetLastError() == E_INVALIDARG,
3116      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3117     /* empty name */
3118     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3119     U(point.DistPointName).FullName.cAltEntry = 0;
3120     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3121      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3122     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3123     if (buf)
3124     {
3125         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3126         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3127         LocalFree(buf);
3128     }
3129     /* name with URL entry */
3130     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3131     U(entry).pwszURL = (LPWSTR)url;
3132     U(point.DistPointName).FullName.cAltEntry = 1;
3133     U(point.DistPointName).FullName.rgAltEntry = &entry;
3134     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3135      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3136     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3137     if (buf)
3138     {
3139         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3140         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3141         LocalFree(buf);
3142     }
3143 }
3144
3145 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3146  const CERT_ALT_NAME_ENTRY *got)
3147 {
3148     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3149      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3150      got->dwAltNameChoice);
3151     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3152     {
3153         switch (got->dwAltNameChoice)
3154         {
3155         case CERT_ALT_NAME_RFC822_NAME:
3156         case CERT_ALT_NAME_DNS_NAME:
3157         case CERT_ALT_NAME_EDI_PARTY_NAME:
3158         case CERT_ALT_NAME_URL:
3159         case CERT_ALT_NAME_REGISTERED_ID:
3160             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3161                !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
3162             break;
3163         case CERT_ALT_NAME_X400_ADDRESS:
3164         case CERT_ALT_NAME_DIRECTORY_NAME:
3165         case CERT_ALT_NAME_IP_ADDRESS:
3166             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3167                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3168             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3169                        U(*got).IPAddress.cbData), "Unexpected value\n");
3170             break;
3171         }
3172     }
3173 }
3174
3175 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3176  const CERT_ALT_NAME_INFO *got)
3177 {
3178     DWORD i;
3179
3180     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3181      expected->cAltEntry, got->cAltEntry);
3182     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3183         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3184 }
3185
3186 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3187  const CRL_DIST_POINT_NAME *got)
3188 {
3189     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3190      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3191     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3192         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3193 }
3194
3195 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3196  const CRL_ISSUING_DIST_POINT *got)
3197 {
3198     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3199     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3200      "Unexpected fOnlyContainsUserCerts\n");
3201     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3202      "Unexpected fOnlyContainsCACerts\n");
3203     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3204      "Unexpected reason flags\n");
3205     ok(got->fIndirectCRL == expected->fIndirectCRL,
3206      "Unexpected fIndirectCRL\n");
3207 }
3208
3209 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3210 {
3211     BOOL ret;
3212     BYTE *buf = NULL;
3213     DWORD size = 0;
3214     CRL_ISSUING_DIST_POINT point = { { 0 } };
3215
3216     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3217      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3218      (BYTE *)&buf, &size);
3219     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3220     if (ret)
3221     {
3222         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3223         LocalFree(buf);
3224     }
3225     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3226      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3227      (BYTE *)&buf, &size);
3228     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3229     if (ret)
3230     {
3231         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3232         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3233         LocalFree(buf);
3234     }
3235     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3236      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3237      (BYTE *)&buf, &size);
3238     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3239     if (ret)
3240     {
3241         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3242         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3243         U(point.DistPointName).FullName.cAltEntry = 0;
3244         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3245         LocalFree(buf);
3246     }
3247     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3248      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3249     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3250     if (ret)
3251     {
3252         CERT_ALT_NAME_ENTRY entry;
3253
3254         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3255         U(entry).pwszURL = (LPWSTR)url;
3256         U(point.DistPointName).FullName.cAltEntry = 1;
3257         U(point.DistPointName).FullName.rgAltEntry = &entry;
3258         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3259         LocalFree(buf);
3260     }
3261 }
3262
3263 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3264  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3265  0x30, 0x5a };
3266 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3267  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3268  0x30, 0x30, 0x30, 0x30, 0x5a };
3269 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3270  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3271  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3272  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3273  0x5a };
3274 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3275  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3276  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3277  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3278  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3279  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3280 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3281  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3282  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3283  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3284  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3285  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3286 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3287  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3288  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3289  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3290  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3291  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3292  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3293 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3294  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3295  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3296  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3297  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3298  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3299  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3300 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3301  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3302  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3303  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3304  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3305  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3306  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3307 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3308  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3309  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3310  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3311  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3312  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3313  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3314
3315 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3316 {
3317     BOOL ret;
3318     BYTE *buf = NULL;
3319     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3320     DWORD size = 0;
3321     CRL_INFO info = { 0 };
3322     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3323     CERT_EXTENSION ext;
3324
3325     /* Test with a V1 CRL */
3326     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3327      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3328     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3329     if (buf)
3330     {
3331         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3332         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3333         LocalFree(buf);
3334     }
3335     /* Test v2 CRL */
3336     info.dwVersion = CRL_V2;
3337     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3338      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3339     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3340     if (buf)
3341     {
3342         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3343          v2CRL[1] + 2, size);
3344         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3345         LocalFree(buf);
3346     }
3347     /* v1 CRL with a name */
3348     info.dwVersion = CRL_V1;
3349     info.Issuer.cbData = sizeof(encodedCommonName);
3350     info.Issuer.pbData = (BYTE *)encodedCommonName;
3351     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3352      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3353     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3354     if (buf)
3355     {
3356         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3357         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3358         LocalFree(buf);
3359     }
3360     /* v1 CRL with a name and a NULL entry pointer */
3361     info.cCRLEntry = 1;
3362     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3363      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3364     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3365      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3366     /* now set an empty entry */
3367     info.rgCRLEntry = &entry;
3368     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3369      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3370     if (buf)
3371     {
3372         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3373          "Wrong size %d\n", size);
3374         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3375          "Got unexpected value\n");
3376         LocalFree(buf);
3377     }
3378     /* an entry with a serial number */
3379     entry.SerialNumber.cbData = sizeof(serialNum);
3380     entry.SerialNumber.pbData = (BYTE *)serialNum;
3381     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3382      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3383     if (buf)
3384     {
3385         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3386          "Wrong size %d\n", size);
3387         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3388          "Got unexpected value\n");
3389         LocalFree(buf);
3390     }
3391     /* an entry with an extension */
3392     entry.cExtension = 1;
3393     entry.rgExtension = &criticalExt;
3394     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3395      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3396     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3397     if (buf)
3398     {
3399         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3400         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3401         LocalFree(buf);
3402     }
3403     /* a CRL with an extension */
3404     entry.cExtension = 0;
3405     info.cExtension = 1;
3406     info.rgExtension = &criticalExt;
3407     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3408      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3409     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3410     if (buf)
3411     {
3412         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3413         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3414         LocalFree(buf);
3415     }
3416     /* a v2 CRL with an extension, this time non-critical */
3417     info.dwVersion = CRL_V2;
3418     info.rgExtension = &nonCriticalExt;
3419     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3420      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3421     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3422     if (buf)
3423     {
3424         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3425         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3426         LocalFree(buf);
3427     }
3428     /* a v2 CRL with an issuing dist point extension */
3429     ext.pszObjId = oid_issuing_dist_point;
3430     ext.fCritical = TRUE;
3431     ext.Value.cbData = sizeof(urlIDP);
3432     ext.Value.pbData = (LPBYTE)urlIDP;
3433     entry.rgExtension = &ext;
3434     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3435      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3436     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3437     if (buf)
3438     {
3439         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3440         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3441         LocalFree(buf);
3442     }
3443 }
3444
3445 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3446  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3447  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3448  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3449  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3450  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3451  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3452  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3453  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3454  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3455  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3456  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3457  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3458  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3459  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3460  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3461  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3462  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3463  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3464  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3465  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3466  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3467  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3468  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3469  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3470  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3471  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3472  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3473  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3474  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3475  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3476  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3477  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3478  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3479  0xcd };
3480 static const BYTE verisignCRLWithLotsOfEntries[] = {
3481 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3482 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3483 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3484 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3485 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3486 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3487 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3488 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3489 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3490 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3491 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3492 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3493 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3494 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3495 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3496 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3497 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3498 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3499 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3500 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3501 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3502 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3503 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3504 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3505 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3506 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3507 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3508 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3509 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3510 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3511 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3512 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3513 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3514 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3515 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3516 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3517 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3518 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3519 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3520 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3521 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3522 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3523 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3524 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3525 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3526 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3527 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3528 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3529 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3530 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3531 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3532 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3533 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3534 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3535 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3536 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3537 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3538 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3539 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3540 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3541 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3542 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3543 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3544 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3545 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3546 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3547 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3548 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3549 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3550 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3551 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3552 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3553 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3554 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3555 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3556 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3557 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3558 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3559 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3560 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3561 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3562 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3563 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3564 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3565 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3566 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3567 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3568 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3569 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3570 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3571 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3572 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3573 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3574 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3575 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3576 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3577 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3578 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3579 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3580 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3581 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3582 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3583 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3584 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3585 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3586 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3587 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3588 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3589 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3590 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3591 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3592 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3593 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3594 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3595 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3596 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3597 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3598 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3599 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3600 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3601 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3602 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3603 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3604 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3605 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3606 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3607 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3608 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3609 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3610 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3611 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3612 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3613 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3614 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3615 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3616 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3617 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3618 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3619 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3620 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3621 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3622 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3623 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3624 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3625 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3626 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3627 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3628 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3629 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3630 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3631 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3632 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3633 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3634 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3635 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3636 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3637 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3638 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3639 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3640 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3641 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3642 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3643 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3644 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3645 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3646 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3647 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3648 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3649 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3650 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3651 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3652 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3653 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3654 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3655 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3656 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3657 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3658 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3659 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3660 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3661 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3662 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3663 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3664 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3665 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3666 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3667 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3668 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3669 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3670 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3671 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3672 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3673 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3674 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3675 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3676 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3677 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3678 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3679 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3680 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3681 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3682 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3683 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3684 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3685 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3686 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3687 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3688 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3689 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3690 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3691 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3692 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3693 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3694 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3695 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3696 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3697 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3698 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3699 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3700 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3701 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3702 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3703 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3704 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3705 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3706 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3707 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3708 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3709 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3710 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3711 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3712 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3713 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3714 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3715 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3716 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3717 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3718 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3719 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3720 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3721 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3722 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3723 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3724 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3725 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3726 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3727 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3728 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3729 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3730 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3731 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3732 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3733 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3734 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3735 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3736 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3737 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3738 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3739 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3740 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3741 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3742 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3743 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3744 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3745 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3746 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3747 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3748 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3749 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3750 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3751 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3752 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3753 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3754 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
3755 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
3756 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
3757 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
3758 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
3759 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
3760 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
3761 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
3762 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
3763 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
3764 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
3765 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
3766 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
3767 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
3768 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
3769 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
3770 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
3771 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
3772 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
3773 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
3774 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
3775 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
3776 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
3777 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
3778 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
3779 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
3780 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
3781 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
3782 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
3783 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
3784 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
3785 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
3786 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
3787 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
3788 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
3789 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
3790 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
3791 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
3792 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
3793 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
3794 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
3795 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
3796 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
3797 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
3798 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
3799 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
3800 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
3801 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
3802 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
3803 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
3804 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
3805 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
3806 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
3807 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
3808 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
3809 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
3810 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
3811 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
3812 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
3813 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
3814 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
3815 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
3816 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
3817 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
3818 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
3819 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
3820 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
3821 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
3822 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
3823 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
3824 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
3825 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
3826 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
3827 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
3828 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
3829 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
3830 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
3831 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
3832 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
3833 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
3834 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
3835 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
3836 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
3837 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
3838 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
3839 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
3840 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
3841 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
3842 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
3843 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
3844 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
3845 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
3846 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
3847 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
3848 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
3849 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
3850 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
3851 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
3852 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
3853 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
3854 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
3855 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
3856 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
3857 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
3858 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
3859 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
3860 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
3861 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
3862 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
3863 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
3864 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
3865 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
3866 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
3867 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
3868 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
3869 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
3870 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
3871 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
3872 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
3873 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
3874 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
3875 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
3876 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
3877 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
3878 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
3879 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
3880 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
3881 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
3882 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
3883 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
3884 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
3885 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
3886 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
3887 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
3888 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
3889 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
3890 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
3891 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
3892 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
3893 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
3894 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
3895 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
3896 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
3897 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
3898 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
3899 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
3900 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
3901 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
3902 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
3903 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
3904 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
3905 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
3906 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
3907 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
3908 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
3909 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
3910 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
3911 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
3912 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
3913 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
3914 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
3915 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
3916 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
3917 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
3918 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
3919 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
3920 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
3921 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
3922 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
3923 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
3924 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
3925 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
3926 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
3927 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
3928 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
3929 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
3930 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
3931 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
3932 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
3933 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
3934 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
3935 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
3936 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
3937 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
3938 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
3939 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
3940 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
3941 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
3942 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
3943 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3944 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
3945 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
3946 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
3947 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
3948 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
3949 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
3950 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
3951 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
3952 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
3953 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
3954 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
3955 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
3956 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
3957 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
3958 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
3959 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
3960 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
3961 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
3962 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
3963 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
3964 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
3965 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
3966 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
3967 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
3968 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
3969 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
3970 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
3971 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
3972 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
3973 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
3974 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
3975 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
3976 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
3977 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
3978 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
3979 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
3980 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
3981 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
3982 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
3983 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
3984 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
3985 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
3986 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
3987 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
3988 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
3989
3990 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
3991 {
3992     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
3993     BOOL ret;
3994     BYTE *buf = NULL;
3995     DWORD size = 0, i;
3996
3997     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
3998     {
3999         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4000          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4001          (BYTE *)&buf, &size);
4002         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4003          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4004     }
4005     /* at a minimum, a CRL must contain an issuer: */
4006     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4007      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4008      (BYTE *)&buf, &size);
4009     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4010     if (buf)
4011     {
4012         CRL_INFO *info = (CRL_INFO *)buf;
4013
4014         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4015         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4016          info->cCRLEntry);
4017         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4018          "Wrong issuer size %d\n", info->Issuer.cbData);
4019         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4020          "Unexpected issuer\n");
4021         LocalFree(buf);
4022     }
4023     /* check decoding with an empty CRL entry */
4024     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4025      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4026      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4027     todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4028      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4029     /* with a real CRL entry */
4030     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4031      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4032      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4033     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4034     if (buf)
4035     {
4036         CRL_INFO *info = (CRL_INFO *)buf;
4037         CRL_ENTRY *entry;
4038
4039         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4040         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4041          info->cCRLEntry);
4042         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4043         entry = info->rgCRLEntry;
4044         ok(entry->SerialNumber.cbData == 1,
4045          "Expected serial number size 1, got %d\n",
4046          entry->SerialNumber.cbData);
4047         ok(*entry->SerialNumber.pbData == *serialNum,
4048          "Expected serial number %d, got %d\n", *serialNum,
4049          *entry->SerialNumber.pbData);
4050         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4051          "Wrong issuer size %d\n", info->Issuer.cbData);
4052         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4053          "Unexpected issuer\n");
4054     }
4055     /* a real CRL from verisign that has extensions */
4056     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4057      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4058      NULL, (BYTE *)&buf, &size);
4059     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4060     if (buf)
4061     {
4062         CRL_INFO *info = (CRL_INFO *)buf;
4063         CRL_ENTRY *entry;
4064
4065         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4066         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4067          info->cCRLEntry);
4068         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4069         entry = info->rgCRLEntry;
4070         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4071          info->cExtension);
4072         LocalFree(buf);
4073     }
4074     /* another real CRL from verisign that has lots of entries */
4075     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4076      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4077      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4078     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4079     if (buf)
4080     {
4081         CRL_INFO *info = (CRL_INFO *)buf;
4082
4083         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4084         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4085          info->cCRLEntry);
4086         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4087          info->cExtension);
4088         LocalFree(buf);
4089     }
4090     /* and finally, with an extension */
4091     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4092      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4093      NULL, (BYTE *)&buf, &size);
4094     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4095     if (buf)
4096     {
4097         CRL_INFO *info = (CRL_INFO *)buf;
4098         CRL_ENTRY *entry;
4099
4100         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4101         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4102          info->cCRLEntry);
4103         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4104         entry = info->rgCRLEntry;
4105         ok(entry->SerialNumber.cbData == 1,
4106          "Expected serial number size 1, got %d\n",
4107          entry->SerialNumber.cbData);
4108         ok(*entry->SerialNumber.pbData == *serialNum,
4109          "Expected serial number %d, got %d\n", *serialNum,
4110          *entry->SerialNumber.pbData);
4111         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4112          "Wrong issuer size %d\n", info->Issuer.cbData);
4113         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4114          "Unexpected issuer\n");
4115         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4116          info->cExtension);
4117     }
4118     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4119      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4120      NULL, (BYTE *)&buf, &size);
4121     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4122     if (buf)
4123     {
4124         CRL_INFO *info = (CRL_INFO *)buf;
4125
4126         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4127          info->cExtension);
4128         LocalFree(buf);
4129     }
4130     /* And again, with an issuing dist point */
4131     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4132      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4133      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4134     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4135     if (buf)
4136     {
4137         CRL_INFO *info = (CRL_INFO *)buf;
4138
4139         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4140          info->cExtension);
4141         LocalFree(buf);
4142     }
4143 }
4144
4145 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4146  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4147 static const BYTE encodedUsage[] = {
4148  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4149  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4150  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4151
4152 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4153 {
4154     BOOL ret;
4155     BYTE *buf = NULL;
4156     DWORD size = 0;
4157     CERT_ENHKEY_USAGE usage;
4158
4159     /* Test with empty usage */
4160     usage.cUsageIdentifier = 0;
4161     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4162      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4163     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4164     if (buf)
4165     {
4166         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4167         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4168         LocalFree(buf);
4169     }
4170     /* Test with a few usages */
4171     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4172     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4173     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4174      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4175     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4176     if (buf)
4177     {
4178         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4179         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4180         LocalFree(buf);
4181     }
4182 }
4183
4184 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4185 {
4186     BOOL ret;
4187     LPBYTE buf = NULL;
4188     DWORD size = 0;
4189
4190     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4191      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4192      (BYTE *)&buf, &size);
4193     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4194     if (buf)
4195     {
4196         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4197
4198         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4199          "Wrong size %d\n", size);
4200         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4201          usage->cUsageIdentifier);
4202         LocalFree(buf);
4203     }
4204     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4205      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4206      (BYTE *)&buf, &size);
4207     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4208     if (buf)
4209     {
4210         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4211         DWORD i;
4212
4213         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4214          "Wrong size %d\n", size);
4215         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4216          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4217         for (i = 0; i < usage->cUsageIdentifier; i++)
4218             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4219              "Expected OID %s, got %s\n", keyUsages[i],
4220              usage->rgpszUsageIdentifier[i]);
4221         LocalFree(buf);
4222     }
4223 }
4224
4225 static const BYTE authorityKeyIdWithId[] = { 0x30,0x03,0x80,0x01,0x01 };
4226 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4227  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4228  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4229 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4230
4231 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4232 {
4233     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4234     BOOL ret;
4235     BYTE *buf = NULL;
4236     DWORD size = 0;
4237
4238     /* Test with empty id */
4239     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4240      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4241     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4242     if (buf)
4243     {
4244         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4245         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4246         LocalFree(buf);
4247     }
4248     /* With just a key id */
4249     info.KeyId.cbData = sizeof(serialNum);
4250     info.KeyId.pbData = (BYTE *)serialNum;
4251     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4252      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4253     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4254     if (buf)
4255     {
4256         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4257         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4258         LocalFree(buf);
4259     }
4260     /* With just an issuer */
4261     info.KeyId.cbData = 0;
4262     info.CertIssuer.cbData = sizeof(encodedCommonName);
4263     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4264     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4265      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4266     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4267     if (buf)
4268     {
4269         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4270          size);
4271         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4272         LocalFree(buf);
4273     }
4274     /* With just a serial number */
4275     info.CertIssuer.cbData = 0;
4276     info.CertSerialNumber.cbData = sizeof(serialNum);
4277     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4278     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4279      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4280     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4281     if (buf)
4282     {
4283         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4284          size);
4285         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4286         LocalFree(buf);
4287     }
4288 }
4289
4290 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4291 {
4292     BOOL ret;
4293     LPBYTE buf = NULL;
4294     DWORD size = 0;
4295
4296     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4297      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4298      (BYTE *)&buf, &size);
4299     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4300     if (buf)
4301     {
4302         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4303
4304         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4305          size);
4306         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4307         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4308         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4309         LocalFree(buf);
4310     }
4311     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4312      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4313      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4314     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4315     if (buf)
4316     {
4317         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4318
4319         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4320          size);
4321         ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4322         ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4323          "Unexpected key id\n");
4324         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4325         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4326         LocalFree(buf);
4327     }
4328     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4329      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4330      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4331     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4332     if (buf)
4333     {
4334         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4335
4336         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4337          size);
4338         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4339         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4340          "Unexpected issuer len\n");
4341         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4342          sizeof(encodedCommonName)), "Unexpected issuer\n");
4343         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4344         LocalFree(buf);
4345     }
4346     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4347      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4348      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4349     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4350     if (buf)
4351     {
4352         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4353
4354         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4355          size);
4356         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4357         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4358         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4359          "Unexpected serial number len\n");
4360         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4361          "Unexpected serial number\n");
4362         LocalFree(buf);
4363     }
4364 }
4365
4366 /* Free *pInfo with HeapFree */
4367 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
4368 {
4369     BOOL ret;
4370     DWORD size = 0;
4371     HCRYPTKEY key;
4372
4373     /* This crashes
4374     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
4375      */
4376     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
4377     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4378      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4379     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
4380      &size);
4381     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4382      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4383     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
4384      NULL, &size);
4385     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4386      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4387     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
4388      0, NULL, NULL, &size);
4389     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4390      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4391     /* Test with no key */
4392     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
4393      0, NULL, NULL, &size);
4394     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
4395      GetLastError());
4396     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
4397     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
4398     if (ret)
4399     {
4400         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
4401          NULL, 0, NULL, NULL, &size);
4402         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
4403         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
4404         if (*pInfo)
4405         {
4406             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
4407              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
4408             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
4409              GetLastError());
4410             if (ret)
4411             {
4412                 /* By default (we passed NULL as the OID) the OID is
4413                  * szOID_RSA_RSA.
4414                  */
4415                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
4416                  "Expected %s, got %s\n", szOID_RSA_RSA,
4417                  (*pInfo)->Algorithm.pszObjId);
4418             }
4419         }
4420     }
4421 }
4422
4423 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
4424  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
4425  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
4426  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
4427  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
4428  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
4429  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
4430  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
4431  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
4432  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
4433  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
4434  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4435  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
4436  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
4437  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
4438  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
4439  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
4440  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
4441  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
4442  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
4443  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
4444  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
4445  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
4446  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
4447  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
4448
4449 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
4450 {
4451     BOOL ret;
4452     HCRYPTKEY key;
4453     PCCERT_CONTEXT context;
4454
4455     /* These crash
4456     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
4457     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
4458     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
4459     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
4460      NULL);
4461      */
4462     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
4463     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
4464      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
4465     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
4466     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
4467      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
4468     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
4469      &key);
4470     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4471      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4472     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
4473      &key);
4474     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
4475     CryptDestroyKey(key);
4476
4477     /* Test importing a public key from a certificate context */
4478     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
4479      sizeof(expiredCert));
4480     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
4481      GetLastError());
4482     if (context)
4483     {
4484         ok(!strcmp(szOID_RSA_RSA,
4485          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
4486          "Expected %s, got %s\n", szOID_RSA_RSA,
4487          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
4488         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
4489          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
4490         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
4491         CryptDestroyKey(key);
4492         CertFreeCertificateContext(context);
4493     }
4494 }
4495
4496 static const char cspName[] = "WineCryptTemp";
4497
4498 static void testPortPublicKeyInfo(void)
4499 {
4500     HCRYPTPROV csp;
4501     BOOL ret;
4502     PCERT_PUBLIC_KEY_INFO info = NULL;
4503
4504     /* Just in case a previous run failed, delete this thing */
4505     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4506      CRYPT_DELETEKEYSET);
4507     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4508      CRYPT_NEWKEYSET);
4509
4510     testExportPublicKey(csp, &info);
4511     testImportPublicKey(csp, info);
4512
4513     HeapFree(GetProcessHeap(), 0, info);
4514     CryptReleaseContext(csp, 0);
4515     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4516      CRYPT_DELETEKEYSET);
4517 }
4518
4519 START_TEST(encode)
4520 {
4521     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
4522      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
4523     DWORD i;
4524
4525     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
4526     {
4527         test_encodeInt(encodings[i]);
4528         test_decodeInt(encodings[i]);
4529         test_encodeEnumerated(encodings[i]);
4530         test_decodeEnumerated(encodings[i]);
4531         test_encodeFiletime(encodings[i]);
4532         test_decodeFiletime(encodings[i]);
4533         test_encodeName(encodings[i]);
4534         test_decodeName(encodings[i]);
4535         test_encodeUnicodeName(encodings[i]);
4536         test_decodeUnicodeName(encodings[i]);
4537         test_encodeNameValue(encodings[i]);
4538         test_decodeNameValue(encodings[i]);
4539         test_encodeUnicodeNameValue(encodings[i]);
4540         test_decodeUnicodeNameValue(encodings[i]);
4541         test_encodeAltName(encodings[i]);
4542         test_decodeAltName(encodings[i]);
4543         test_encodeOctets(encodings[i]);
4544         test_decodeOctets(encodings[i]);
4545         test_encodeBits(encodings[i]);
4546         test_decodeBits(encodings[i]);
4547         test_encodeBasicConstraints(encodings[i]);
4548         test_decodeBasicConstraints(encodings[i]);
4549         test_encodeRsaPublicKey(encodings[i]);
4550         test_decodeRsaPublicKey(encodings[i]);
4551         test_encodeSequenceOfAny(encodings[i]);
4552         test_decodeSequenceOfAny(encodings[i]);
4553         test_encodeExtensions(encodings[i]);
4554         test_decodeExtensions(encodings[i]);
4555         test_encodePublicKeyInfo(encodings[i]);
4556         test_decodePublicKeyInfo(encodings[i]);
4557         test_encodeCertToBeSigned(encodings[i]);
4558         test_decodeCertToBeSigned(encodings[i]);
4559         test_encodeCert(encodings[i]);
4560         test_decodeCert(encodings[i]);
4561         test_encodeCRLDistPoints(encodings[i]);
4562         test_decodeCRLDistPoints(encodings[i]);
4563         test_encodeCRLIssuingDistPoint(encodings[i]);
4564         test_decodeCRLIssuingDistPoint(encodings[i]);
4565         test_encodeCRLToBeSigned(encodings[i]);
4566         test_decodeCRLToBeSigned(encodings[i]);
4567         test_encodeEnhancedKeyUsage(encodings[i]);
4568         test_decodeEnhancedKeyUsage(encodings[i]);
4569         test_encodeAuthorityKeyId(encodings[i]);
4570         test_decodeAuthorityKeyId(encodings[i]);
4571     }
4572     testPortPublicKeyInfo();
4573 }