crypt32: Allow either NULL or empty strings where one or the other is expected.
[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     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
204     BYTE *buf = NULL;
205     DWORD bufSize = 0;
206     int i;
207     BOOL ret;
208
209     /* CryptDecodeObjectEx with NULL bufSize crashes..
210     ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded, 
211      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
212      */
213     /* check bogus encoding */
214     ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded, 
215      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
216     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
217      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
218     /* check with NULL integer buffer */
219     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
220      &bufSize);
221     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
222      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
223     /* check with a valid, but too large, integer */
224     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
225      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
226     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
227      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
228     /* check with a DER-encoded string */
229     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
230      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
231     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
232      "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError());
233     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
234     {
235         /* When the output buffer is NULL, this always succeeds */
236         SetLastError(0xdeadbeef);
237         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
238          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
239          &bufSize);
240         ok(ret && GetLastError() == NOERROR,
241          "Expected success and NOERROR, got %d\n", GetLastError());
242         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
243          ints[i].encoded, ints[i].encoded[1] + 2,
244          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
245         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
246         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
247         ok(buf != NULL, "Expected allocated buffer\n");
248         if (buf)
249         {
250             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
251              ints[i].val, *(int *)buf);
252             LocalFree(buf);
253         }
254     }
255     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
256     {
257         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
258          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
259          &bufSize);
260         ok(ret && GetLastError() == NOERROR,
261          "Expected success and NOERROR, got %d\n", GetLastError());
262         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
263          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
264          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
265         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
266         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
267         ok(buf != NULL, "Expected allocated buffer\n");
268         if (buf)
269         {
270             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
271
272             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
273              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
274              blob->cbData);
275             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
276              "Unexpected value\n");
277             LocalFree(buf);
278         }
279     }
280     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
281     {
282         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
283          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
284          &bufSize);
285         ok(ret && GetLastError() == NOERROR,
286          "Expected success and NOERROR, got %d\n", GetLastError());
287         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
288          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
289          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
290         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
291         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
292         ok(buf != NULL, "Expected allocated buffer\n");
293         if (buf)
294         {
295             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
296
297             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
298              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
299              blob->cbData);
300             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
301              "Unexpected value\n");
302             LocalFree(buf);
303         }
304     }
305     /* Decode the value 1 with long-form length */
306     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
307      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
308     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
309     if (buf)
310     {
311         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
312         LocalFree(buf);
313     }
314     /* check with extra bytes at the end */
315     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
316      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
317     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
318     if (buf)
319     {
320         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
321         LocalFree(buf);
322     }
323     /* Try to decode some bogus large items */
324     /* The buffer size is smaller than the encoded length, so this should fail
325      * with CRYPT_E_ASN1_EOD if it's being decoded.
326      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
327      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
328      * So this test unfortunately isn't useful.
329     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
330      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
331     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
332      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
333      */
334     /* This will try to decode the buffer and overflow it, check that it's
335      * caught.
336      */
337     if (0)
338     {
339     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
340     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
341      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
342     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
343      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
344     }
345 }
346
347 static const BYTE bin18[] = {0x0a,0x01,0x01};
348 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
349
350 /* These are always encoded unsigned, and aren't constrained to be any
351  * particular value
352  */
353 static const struct encodedInt enums[] = {
354  { 1,    bin18 },
355  { -128, bin19 },
356 };
357
358 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
359  * X509_ENUMERATED.
360  */
361 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
362  szOID_CRL_REASON_CODE };
363
364 static void test_encodeEnumerated(DWORD dwEncoding)
365 {
366     DWORD i, j;
367
368     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
369     {
370         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
371         {
372             BOOL ret;
373             BYTE *buf = NULL;
374             DWORD bufSize = 0;
375
376             ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
377              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
378              &bufSize);
379             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
380             if (buf)
381             {
382                 ok(buf[0] == 0xa,
383                  "Got unexpected type %d for enumerated (expected 0xa)\n",
384                  buf[0]);
385                 ok(buf[1] == enums[j].encoded[1],
386                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
387                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
388                  enums[j].encoded[1] + 1),
389                  "Encoded value of 0x%08x didn't match expected\n",
390                  enums[j].val);
391                 LocalFree(buf);
392             }
393         }
394     }
395 }
396
397 static void test_decodeEnumerated(DWORD dwEncoding)
398 {
399     DWORD i, j;
400
401     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
402     {
403         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
404         {
405             BOOL ret;
406             DWORD bufSize = sizeof(int);
407             int val;
408
409             ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
410              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
411              (BYTE *)&val, &bufSize);
412             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
413             ok(bufSize == sizeof(int),
414              "Got unexpected size %d for enumerated\n", bufSize);
415             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
416              val, enums[j].val);
417         }
418     }
419 }
420
421 struct encodedFiletime
422 {
423     SYSTEMTIME sysTime;
424     const BYTE *encodedTime;
425 };
426
427 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
428  const struct encodedFiletime *time)
429 {
430     FILETIME ft = { 0 };
431     BYTE *buf = NULL;
432     DWORD bufSize = 0;
433     BOOL ret;
434
435     ret = SystemTimeToFileTime(&time->sysTime, &ft);
436     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
437     ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
438      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
439     /* years other than 1950-2050 are not allowed for encodings other than
440      * X509_CHOICE_OF_TIME.
441      */
442     if (structType == X509_CHOICE_OF_TIME ||
443      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
444     {
445         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
446          GetLastError());
447         ok(buf != NULL, "Expected an allocated buffer\n");
448         if (buf)
449         {
450             ok(buf[0] == time->encodedTime[0],
451              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
452              buf[0]);
453             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
454              time->encodedTime[1], bufSize);
455             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
456              "Got unexpected value for time encoding\n");
457             LocalFree(buf);
458         }
459     }
460     else
461         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
462          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
463 }
464
465 static const char *printSystemTime(const SYSTEMTIME *st)
466 {
467     static char buf[25];
468
469     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
470      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
471     return buf;
472 }
473
474 static const char *printFileTime(const FILETIME *ft)
475 {
476     static char buf[25];
477     SYSTEMTIME st;
478
479     FileTimeToSystemTime(ft, &st);
480     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
481      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
482     return buf;
483 }
484
485 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
486 {
487     SYSTEMTIME st;
488
489     FileTimeToSystemTime(got, &st);
490     ok(expected->wYear == st.wYear &&
491      expected->wMonth == st.wMonth &&
492      expected->wDay == st.wDay &&
493      expected->wHour == st.wHour &&
494      expected->wMinute == st.wMinute &&
495      expected->wSecond == st.wSecond &&
496      abs(expected->wMilliseconds - st.wMilliseconds) <= 1,
497      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
498      printSystemTime(expected), printFileTime(got));
499 }
500
501 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
502  const struct encodedFiletime *time)
503 {
504     FILETIME ft = { 0 };
505     DWORD size = sizeof(ft);
506     BOOL ret;
507
508     ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
509      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
510     /* years other than 1950-2050 are not allowed for encodings other than
511      * X509_CHOICE_OF_TIME.
512      */
513     if (structType == X509_CHOICE_OF_TIME ||
514      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
515     {
516         ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
517          GetLastError());
518         compareTime(&time->sysTime, &ft);
519     }
520     else
521         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
522          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
523 }
524
525 static const BYTE bin20[] = {
526     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
527 static const BYTE bin21[] = {
528     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
529 static const BYTE bin22[] = {
530     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
531
532 static const struct encodedFiletime times[] = {
533  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
534  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
535  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
536 };
537
538 static void test_encodeFiletime(DWORD dwEncoding)
539 {
540     DWORD i;
541
542     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
543     {
544         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
545         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
546         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
547     }
548 }
549
550 static const BYTE bin23[] = {
551     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
552 static const BYTE bin24[] = {
553     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
554 static const BYTE bin25[] = {
555     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
556 static const BYTE bin26[] = {
557     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
558 static const BYTE bin27[] = {
559     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
560 static const BYTE bin28[] = {
561     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
562 static const BYTE bin29[] = {
563     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
564 static const BYTE bin30[] = {
565     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
566 static const BYTE bin31[] = {
567     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
568 static const BYTE bin32[] = {
569     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
570 static const BYTE bin33[] = {
571     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
572 static const BYTE bin34[] = {
573     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
574 static const BYTE bin35[] = {
575     0x17,0x08, '4','5','0','6','0','6','1','6'};
576 static const BYTE bin36[] = {
577     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
578 static const BYTE bin37[] = {
579     0x18,0x04, '2','1','4','5'};
580 static const BYTE bin38[] = {
581     0x18,0x08, '2','1','4','5','0','6','0','6'};
582
583 static void test_decodeFiletime(DWORD dwEncoding)
584 {
585     static const struct encodedFiletime otherTimes[] = {
586      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
587      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
588      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
589      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
590      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
591      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
592      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
593      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
594      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
595      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
596      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
597      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
598     };
599     /* An oddball case that succeeds in Windows, but doesn't seem correct
600      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
601      */
602     static const unsigned char *bogusTimes[] = {
603      /* oddly, this succeeds on Windows, with year 2765
604      "\x18" "\x0f" "21r50606161000Z",
605       */
606      bin35,
607      bin36,
608      bin37,
609      bin38,
610     };
611     DWORD i, size;
612     FILETIME ft1 = { 0 }, ft2 = { 0 };
613     BOOL ret;
614
615     /* Check bogus length with non-NULL buffer */
616     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
617     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
618     size = 1;
619     ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
620      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
621     ok(!ret && GetLastError() == ERROR_MORE_DATA,
622      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
623     /* Normal tests */
624     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
625     {
626         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
627         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
628         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
629     }
630     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
631     {
632         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
633         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
634         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
635     }
636     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
637     {
638         size = sizeof(ft1);
639         ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
640          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
641         ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
642          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
643     }
644 }
645
646 static const char commonName[] = "Juan Lang";
647 static const char surName[] = "Lang";
648
649 static const BYTE emptySequence[] = { 0x30, 0 };
650 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
651 static const BYTE twoRDNs[] = {
652     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
653     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
654     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
655 static const BYTE encodedTwoRDNs[] = {
656 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
657 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
658 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
659 0x6e,0x67,0x00,
660 };
661
662 static const BYTE us[] = { 0x55, 0x53 };
663 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
664  0x74, 0x61 };
665 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
666  0x6f, 0x6c, 0x69, 0x73 };
667 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
668  0x76, 0x65, 0x72, 0x73 };
669 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
670  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
671 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
672  0x73, 0x74 };
673 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
674  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
675
676 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
677 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
678
679 static CHAR oid_us[]            = "2.5.4.6",
680             oid_minnesota[]     = "2.5.4.8",
681             oid_minneapolis[]   = "2.5.4.7",
682             oid_codeweavers[]   = "2.5.4.10",
683             oid_wine[]          = "2.5.4.11",
684             oid_localhostAttr[] = "2.5.4.3",
685             oid_aric[]          = "1.2.840.113549.1.9.1";
686 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
687                                     { RDNA(minnesota) },
688                                     { RDNA(minneapolis) },
689                                     { RDNA(codeweavers) },
690                                     { RDNA(wine) },
691                                     { RDNA(localhostAttr) },
692                                     { RDNIA5(aric) } };
693 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
694                                            { RDNA(localhostAttr) },
695                                            { RDNA(minnesota) },
696                                            { RDNA(minneapolis) },
697                                            { RDNA(codeweavers) },
698                                            { RDNA(wine) },
699                                            { RDNIA5(aric) } };
700
701 #undef RDNIA5
702 #undef RDNA
703
704 static const BYTE encodedRDNAttrs[] = {
705 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
706 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
707 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
708 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
709 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
710 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
711 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
712 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
713 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
714 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
715 };
716
717 static void test_encodeName(DWORD dwEncoding)
718 {
719     CERT_RDN_ATTR attrs[2];
720     CERT_RDN rdn;
721     CERT_NAME_INFO info;
722     static CHAR oid_common_name[] = szOID_COMMON_NAME,
723                 oid_sur_name[]    = szOID_SUR_NAME;
724     BYTE *buf = NULL;
725     DWORD size = 0;
726     BOOL ret;
727
728     /* Test with NULL pvStructInfo */
729     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
730      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
731     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
732      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
733     /* Test with empty CERT_NAME_INFO */
734     info.cRDN = 0;
735     info.rgRDN = NULL;
736     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
737      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
738     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
739     if (buf)
740     {
741         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
742          "Got unexpected encoding for empty name\n");
743         LocalFree(buf);
744     }
745     /* Test with bogus CERT_RDN */
746     info.cRDN = 1;
747     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
748      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
749     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
750      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
751     /* Test with empty CERT_RDN */
752     rdn.cRDNAttr = 0;
753     rdn.rgRDNAttr = NULL;
754     info.cRDN = 1;
755     info.rgRDN = &rdn;
756     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
757      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
758     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
759     if (buf)
760     {
761         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
762          "Got unexpected encoding for empty RDN array\n");
763         LocalFree(buf);
764     }
765     /* Test with bogus attr array */
766     rdn.cRDNAttr = 1;
767     rdn.rgRDNAttr = NULL;
768     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
769      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
770     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
771      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
772     /* oddly, a bogus OID is accepted by Windows XP; not testing.
773     attrs[0].pszObjId = "bogus";
774     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
775     attrs[0].Value.cbData = sizeof(commonName);
776     attrs[0].Value.pbData = (BYTE *)commonName;
777     rdn.cRDNAttr = 1;
778     rdn.rgRDNAttr = attrs;
779     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
780      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
781     ok(!ret, "Expected failure, got success\n");
782      */
783     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
784      * the encoded attributes to be swapped.
785      */
786     attrs[0].pszObjId = oid_common_name;
787     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
788     attrs[0].Value.cbData = sizeof(commonName);
789     attrs[0].Value.pbData = (BYTE *)commonName;
790     attrs[1].pszObjId = oid_sur_name;
791     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
792     attrs[1].Value.cbData = sizeof(surName);
793     attrs[1].Value.pbData = (BYTE *)surName;
794     rdn.cRDNAttr = 2;
795     rdn.rgRDNAttr = attrs;
796     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
797      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
798     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
799     if (buf)
800     {
801         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
802          "Got unexpected encoding for two RDN array\n");
803         LocalFree(buf);
804     }
805     /* A name can be "encoded" with previously encoded RDN attrs. */
806     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
807     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
808     attrs[0].Value.cbData = sizeof(twoRDNs);
809     rdn.cRDNAttr = 1;
810     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
811      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
812     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
813     if (buf)
814     {
815         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
816         ok(!memcmp(buf, encodedTwoRDNs, size),
817          "Unexpected value for re-endoded two RDN array\n");
818         LocalFree(buf);
819     }
820     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
821     rdn.cRDNAttr = 1;
822     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
823     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
824      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
825     ok(!ret && GetLastError() == E_INVALIDARG,
826      "Expected E_INVALIDARG, got %08x\n", GetLastError());
827     /* Test a more complex name */
828     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
829     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
830     info.cRDN = 1;
831     info.rgRDN = &rdn;
832     buf = NULL;
833     size = 0;
834     ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
835      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
836     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
837     if (ret)
838     {
839         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
840         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
841         LocalFree(buf);
842     }
843 }
844
845 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
846 static WCHAR surNameW[] = { 'L','a','n','g',0 };
847
848 static const BYTE twoRDNsNoNull[] = {
849  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
850  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
851  0x20,0x4c,0x61,0x6e,0x67 };
852 static const BYTE anyType[] = {
853  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
854  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
855  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
856  0x61,0x4c,0x67,0x6e };
857
858 static void test_encodeUnicodeName(DWORD dwEncoding)
859 {
860     CERT_RDN_ATTR attrs[2];
861     CERT_RDN rdn;
862     CERT_NAME_INFO info;
863     static CHAR oid_common_name[] = szOID_COMMON_NAME,
864                 oid_sur_name[]    = szOID_SUR_NAME;
865     BYTE *buf = NULL;
866     DWORD size = 0;
867     BOOL ret;
868
869     /* Test with NULL pvStructInfo */
870     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
871      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
872     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
873      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
874     /* Test with empty CERT_NAME_INFO */
875     info.cRDN = 0;
876     info.rgRDN = NULL;
877     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
878      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
879     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
880     if (buf)
881     {
882         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
883          "Got unexpected encoding for empty name\n");
884         LocalFree(buf);
885     }
886     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
887      * encoding (the NULL).
888      */
889     attrs[0].pszObjId = oid_common_name;
890     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
891     attrs[0].Value.cbData = sizeof(commonNameW);
892     attrs[0].Value.pbData = (BYTE *)commonNameW;
893     rdn.cRDNAttr = 1;
894     rdn.rgRDNAttr = attrs;
895     info.cRDN = 1;
896     info.rgRDN = &rdn;
897     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
898      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
899     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
900      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
901     ok(size == 9, "Unexpected error index %08x\n", size);
902     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
903      * forces the order of the encoded attributes to be swapped.
904      */
905     attrs[0].pszObjId = oid_common_name;
906     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
907     attrs[0].Value.cbData = 0;
908     attrs[0].Value.pbData = (BYTE *)commonNameW;
909     attrs[1].pszObjId = oid_sur_name;
910     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
911     attrs[1].Value.cbData = 0;
912     attrs[1].Value.pbData = (BYTE *)surNameW;
913     rdn.cRDNAttr = 2;
914     rdn.rgRDNAttr = attrs;
915     info.cRDN = 1;
916     info.rgRDN = &rdn;
917     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
918      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
919     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
920     if (buf)
921     {
922         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
923          "Got unexpected encoding for two RDN array\n");
924         LocalFree(buf);
925     }
926     /* A name can be "encoded" with previously encoded RDN attrs. */
927     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
928     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
929     attrs[0].Value.cbData = sizeof(twoRDNs);
930     rdn.cRDNAttr = 1;
931     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
932      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
933     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
934     if (buf)
935     {
936         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
937         ok(!memcmp(buf, encodedTwoRDNs, size),
938          "Unexpected value for re-endoded two RDN array\n");
939         LocalFree(buf);
940     }
941     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
942     rdn.cRDNAttr = 1;
943     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
944     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
945      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
946     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
947     if (buf)
948     {
949         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
950         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
951         LocalFree(buf);
952     }
953 }
954
955 static void compareNameValues(const CERT_NAME_VALUE *expected,
956  const CERT_NAME_VALUE *got)
957 {
958     ok(got->dwValueType == expected->dwValueType,
959      "Expected string type %d, got %d\n", expected->dwValueType,
960      got->dwValueType);
961     ok(got->Value.cbData == expected->Value.cbData,
962      "String type %d: unexpected data size, got %d, expected %d\n",
963      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
964     if (got->Value.cbData && got->Value.pbData)
965         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
966          min(got->Value.cbData, expected->Value.cbData)),
967          "String type %d: unexpected value\n", expected->dwValueType);
968 }
969
970 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
971  const CERT_RDN_ATTR *got)
972 {
973     if (expected->pszObjId && strlen(expected->pszObjId))
974     {
975         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
976          expected->pszObjId);
977         if (got->pszObjId)
978         {
979             ok(!strcmp(got->pszObjId, expected->pszObjId),
980              "Got unexpected OID %s, expected %s\n", got->pszObjId,
981              expected->pszObjId);
982         }
983     }
984     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
985      (const CERT_NAME_VALUE *)&got->dwValueType);
986 }
987
988 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
989 {
990     ok(got->cRDNAttr == expected->cRDNAttr,
991      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
992     if (got->cRDNAttr)
993     {
994         DWORD i;
995
996         for (i = 0; i < got->cRDNAttr; i++)
997             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
998     }
999 }
1000
1001 static void compareNames(const CERT_NAME_INFO *expected,
1002  const CERT_NAME_INFO *got)
1003 {
1004     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1005      expected->cRDN, got->cRDN);
1006     if (got->cRDN)
1007     {
1008         DWORD i;
1009
1010         for (i = 0; i < got->cRDN; i++)
1011             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1012     }
1013 }
1014
1015 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1016 static const BYTE twoRDNsExtraBytes[] = {
1017     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1018     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1019     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1020
1021 static void test_decodeName(DWORD dwEncoding)
1022 {
1023     BYTE *buf = NULL;
1024     DWORD bufSize = 0;
1025     BOOL ret;
1026     CERT_RDN rdn;
1027     CERT_NAME_INFO info = { 1, &rdn };
1028
1029     /* test empty name */
1030     bufSize = 0;
1031     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1032      emptySequence[1] + 2,
1033      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1034      (BYTE *)&buf, &bufSize);
1035     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1036     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1037      * decoder works the same way, so only test the count.
1038      */
1039     if (buf)
1040     {
1041         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1042         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1043          "Expected 0 RDNs in empty info, got %d\n",
1044          ((CERT_NAME_INFO *)buf)->cRDN);
1045         LocalFree(buf);
1046     }
1047     /* test empty name with indefinite-length encoding */
1048     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1049      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1050      (BYTE *)&buf, &bufSize);
1051     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1052     if (ret)
1053     {
1054         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1055         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1056          "Expected 0 RDNs in empty info, got %d\n",
1057          ((CERT_NAME_INFO *)buf)->cRDN);
1058         LocalFree(buf);
1059     }
1060     /* test empty RDN */
1061     bufSize = 0;
1062     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1063      emptyRDNs[1] + 2,
1064      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1065      (BYTE *)&buf, &bufSize);
1066     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1067     if (buf)
1068     {
1069         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1070
1071         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1072          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1073          "Got unexpected value for empty RDN\n");
1074         LocalFree(buf);
1075     }
1076     /* test two RDN attrs */
1077     bufSize = 0;
1078     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1079      twoRDNs[1] + 2,
1080      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1081      (BYTE *)&buf, &bufSize);
1082     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1083     if (buf)
1084     {
1085         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1086                     oid_common_name[] = szOID_COMMON_NAME;
1087
1088         CERT_RDN_ATTR attrs[] = {
1089          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1090           (BYTE *)surName } },
1091          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1092           (BYTE *)commonName } },
1093         };
1094
1095         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1096         rdn.rgRDNAttr = attrs;
1097         compareNames(&info, (CERT_NAME_INFO *)buf);
1098         LocalFree(buf);
1099     }
1100     /* test that two RDN attrs with extra bytes succeeds */
1101     bufSize = 0;
1102     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1103      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1104     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1105     /* And, a slightly more complicated name */
1106     buf = NULL;
1107     bufSize = 0;
1108     ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1109      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1110     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1111     if (ret)
1112     {
1113         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1114         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1115         compareNames(&info, (CERT_NAME_INFO *)buf);
1116         LocalFree(buf);
1117     }
1118 }
1119
1120 static void test_decodeUnicodeName(DWORD dwEncoding)
1121 {
1122     BYTE *buf = NULL;
1123     DWORD bufSize = 0;
1124     BOOL ret;
1125     CERT_RDN rdn;
1126     CERT_NAME_INFO info = { 1, &rdn };
1127
1128     /* test empty name */
1129     bufSize = 0;
1130     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1131      emptySequence[1] + 2,
1132      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1133      (BYTE *)&buf, &bufSize);
1134     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1135     if (buf)
1136     {
1137         ok(bufSize == sizeof(CERT_NAME_INFO),
1138          "Got wrong bufSize %d\n", bufSize);
1139         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1140          "Expected 0 RDNs in empty info, got %d\n",
1141          ((CERT_NAME_INFO *)buf)->cRDN);
1142         LocalFree(buf);
1143     }
1144     /* test empty RDN */
1145     bufSize = 0;
1146     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1147      emptyRDNs[1] + 2,
1148      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1149      (BYTE *)&buf, &bufSize);
1150     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1151     if (buf)
1152     {
1153         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1154
1155         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1156          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1157          "Got unexpected value for empty RDN\n");
1158         LocalFree(buf);
1159     }
1160     /* test two RDN attrs */
1161     bufSize = 0;
1162     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1163      sizeof(twoRDNsNoNull),
1164      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1165      (BYTE *)&buf, &bufSize);
1166     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1167     if (buf)
1168     {
1169         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1170                     oid_common_name[] = szOID_COMMON_NAME;
1171
1172         CERT_RDN_ATTR attrs[] = {
1173          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1174          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1175          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1176          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1177         };
1178
1179         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1180         rdn.rgRDNAttr = attrs;
1181         compareNames(&info, (CERT_NAME_INFO *)buf);
1182         LocalFree(buf);
1183     }
1184 }
1185
1186 struct EncodedNameValue
1187 {
1188     CERT_NAME_VALUE value;
1189     const BYTE *encoded;
1190     DWORD encodedSize;
1191 };
1192
1193 static const char bogusIA5[] = "\x80";
1194 static const char bogusPrintable[] = "~";
1195 static const char bogusNumeric[] = "A";
1196 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1197 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1198 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1199 static BYTE octetCommonNameValue[] = {
1200  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1201 static BYTE numericCommonNameValue[] = {
1202  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1203 static BYTE printableCommonNameValue[] = {
1204  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1205 static BYTE t61CommonNameValue[] = {
1206  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1207 static BYTE videotexCommonNameValue[] = {
1208  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1209 static BYTE ia5CommonNameValue[] = {
1210  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1211 static BYTE graphicCommonNameValue[] = {
1212  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1213 static BYTE visibleCommonNameValue[] = {
1214  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1215 static BYTE generalCommonNameValue[] = {
1216  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1217 static BYTE bmpCommonNameValue[] = {
1218  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1219  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1220 static BYTE utf8CommonNameValue[] = {
1221  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1222
1223 static struct EncodedNameValue nameValues[] = {
1224  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1225      octetCommonNameValue, sizeof(octetCommonNameValue) },
1226  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1227      numericCommonNameValue, sizeof(numericCommonNameValue) },
1228  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1229      printableCommonNameValue, sizeof(printableCommonNameValue) },
1230  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1231      t61CommonNameValue, sizeof(t61CommonNameValue) },
1232  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1233      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1234  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1235      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1236  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1237      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1238  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1239      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1240  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1241      generalCommonNameValue, sizeof(generalCommonNameValue) },
1242  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1243      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1244  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1245      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1246  /* The following tests succeed under Windows, but really should fail,
1247   * they contain characters that are illegal for the encoding.  I'm
1248   * including them to justify my lazy encoding.
1249   */
1250  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1251      sizeof(bin42) },
1252  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1253      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1254  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1255      bin44, sizeof(bin44) },
1256 };
1257
1258 static void test_encodeNameValue(DWORD dwEncoding)
1259 {
1260     BYTE *buf = NULL;
1261     DWORD size = 0, i;
1262     BOOL ret;
1263     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1264
1265     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1266     value.Value.pbData = printableCommonNameValue;
1267     value.Value.cbData = sizeof(printableCommonNameValue);
1268     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1269      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1270     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1271     if (buf)
1272     {
1273         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1274          size);
1275         ok(!memcmp(buf, printableCommonNameValue, size),
1276          "Unexpected encoding\n");
1277         LocalFree(buf);
1278     }
1279     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1280     {
1281         ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1282          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1283          &size);
1284         ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1285          nameValues[i].value.dwValueType, GetLastError());
1286         if (buf)
1287         {
1288             ok(size == nameValues[i].encodedSize,
1289              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1290             ok(!memcmp(buf, nameValues[i].encoded, size),
1291              "Got unexpected encoding\n");
1292             LocalFree(buf);
1293         }
1294     }
1295 }
1296
1297 static void test_decodeNameValue(DWORD dwEncoding)
1298 {
1299     int i;
1300     BYTE *buf = NULL;
1301     DWORD bufSize = 0;
1302     BOOL ret;
1303
1304     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1305     {
1306         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1307          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1308          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1309          (BYTE *)&buf, &bufSize);
1310         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1311          nameValues[i].value.dwValueType, GetLastError());
1312         if (buf)
1313         {
1314             compareNameValues(&nameValues[i].value,
1315              (const CERT_NAME_VALUE *)buf);
1316             LocalFree(buf);
1317         }
1318     }
1319 }
1320
1321 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1322 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1323 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1324  'h','q','.','o','r','g',0 };
1325 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1326  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1327  0x6f, 0x72, 0x67 };
1328 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1329  0x575b, 0 };
1330 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1331 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1332  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1333 static const BYTE localhost[] = { 127, 0, 0, 1 };
1334 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1335  0x01 };
1336 static const unsigned char encodedCommonName[] = {
1337     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1338 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1339 static const BYTE encodedDirectoryName[] = {
1340 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1341 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1342
1343 static void test_encodeAltName(DWORD dwEncoding)
1344 {
1345     CERT_ALT_NAME_INFO info = { 0 };
1346     CERT_ALT_NAME_ENTRY entry = { 0 };
1347     BYTE *buf = NULL;
1348     DWORD size = 0;
1349     BOOL ret;
1350     char oid[] = "1.2.3";
1351
1352     /* Test with empty info */
1353     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1354      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1355     if (buf)
1356     {
1357         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1358         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1359         LocalFree(buf);
1360     }
1361     /* Test with an empty entry */
1362     info.cAltEntry = 1;
1363     info.rgAltEntry = &entry;
1364     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1365      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1366     ok(!ret && GetLastError() == E_INVALIDARG,
1367      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1368     /* Test with an empty pointer */
1369     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1370     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1371      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1372     if (buf)
1373     {
1374         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1375         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1376         LocalFree(buf);
1377     }
1378     /* Test with a real URL */
1379     U(entry).pwszURL = (LPWSTR)url;
1380     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1381      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1382     if (buf)
1383     {
1384         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1385         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1386         LocalFree(buf);
1387     }
1388     /* Now with the URL containing an invalid IA5 char */
1389     U(entry).pwszURL = (LPWSTR)nihongoURL;
1390     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1391      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1392     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1393      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1394     /* The first invalid character is at index 7 */
1395     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1396      "Expected invalid char at index 7, got %d\n",
1397      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1398     /* Now with the URL missing a scheme */
1399     U(entry).pwszURL = (LPWSTR)dnsName;
1400     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1401      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1402     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1403     if (buf)
1404     {
1405         /* This succeeds, but it shouldn't, so don't worry about conforming */
1406         LocalFree(buf);
1407     }
1408     /* Now with a DNS name */
1409     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1410     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1411      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1412     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1413     if (buf)
1414     {
1415         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1416         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1417         LocalFree(buf);
1418     }
1419     /* Test with an IP address */
1420     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1421     U(entry).IPAddress.cbData = sizeof(localhost);
1422     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1423     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1424      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1425     if (buf)
1426     {
1427         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1428         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1429         LocalFree(buf);
1430     }
1431     /* Test with OID */
1432     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1433     U(entry).pszRegisteredID = oid;
1434     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1435      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1436     if (buf)
1437     {
1438         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1439         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1440         LocalFree(buf);
1441     }
1442     /* Test with directory name */
1443     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1444     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1445     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1446     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1447      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1448     if (buf)
1449     {
1450         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1451         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1452         LocalFree(buf);
1453     }
1454 }
1455
1456 static void test_decodeAltName(DWORD dwEncoding)
1457 {
1458     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1459      0x00, 0x00, 0x01 };
1460     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1461      0x01 };
1462     BOOL ret;
1463     BYTE *buf = NULL;
1464     DWORD bufSize = 0;
1465     CERT_ALT_NAME_INFO *info;
1466
1467     /* Test some bogus ones first */
1468     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1469      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1470      NULL, (BYTE *)&buf, &bufSize);
1471     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1472      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1473     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1474      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1475      &bufSize);
1476     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1477      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1478     /* Now expected cases */
1479     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1480      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1481      &bufSize);
1482     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1483     if (buf)
1484     {
1485         info = (CERT_ALT_NAME_INFO *)buf;
1486
1487         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1488          info->cAltEntry);
1489         LocalFree(buf);
1490     }
1491     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1492      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1493      &bufSize);
1494     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1495     if (buf)
1496     {
1497         info = (CERT_ALT_NAME_INFO *)buf;
1498
1499         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1500          info->cAltEntry);
1501         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1502          "Expected CERT_ALT_NAME_URL, got %d\n",
1503          info->rgAltEntry[0].dwAltNameChoice);
1504         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1505          "Expected empty URL\n");
1506         LocalFree(buf);
1507     }
1508     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1509      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1510     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1511     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1512      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1513      &bufSize);
1514     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1515     if (buf)
1516     {
1517         info = (CERT_ALT_NAME_INFO *)buf;
1518
1519         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1520          info->cAltEntry);
1521         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1522          "Expected CERT_ALT_NAME_URL, got %d\n",
1523          info->rgAltEntry[0].dwAltNameChoice);
1524         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1525         LocalFree(buf);
1526     }
1527     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1528      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1529      &bufSize);
1530     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1531     if (buf)
1532     {
1533         info = (CERT_ALT_NAME_INFO *)buf;
1534
1535         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1536          info->cAltEntry);
1537         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1538          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1539          info->rgAltEntry[0].dwAltNameChoice);
1540         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1541          "Unexpected DNS name\n");
1542         LocalFree(buf);
1543     }
1544     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1545      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1546      &bufSize);
1547     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1548     if (buf)
1549     {
1550         info = (CERT_ALT_NAME_INFO *)buf;
1551
1552         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1553          info->cAltEntry);
1554         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1555          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1556          info->rgAltEntry[0].dwAltNameChoice);
1557         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1558          "Unexpected IP address length %d\n",
1559           U(info->rgAltEntry[0]).IPAddress.cbData);
1560         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1561          sizeof(localhost)), "Unexpected IP address value\n");
1562         LocalFree(buf);
1563     }
1564     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1565      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1566      &bufSize);
1567     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1568     if (buf)
1569     {
1570         info = (CERT_ALT_NAME_INFO *)buf;
1571
1572         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1573          info->cAltEntry);
1574         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1575          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1576          info->rgAltEntry[0].dwAltNameChoice);
1577         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1578            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1579         LocalFree(buf);
1580     }
1581     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1582      encodedDirectoryName, sizeof(encodedDirectoryName),
1583      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1584     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1585     if (buf)
1586     {
1587         info = (CERT_ALT_NAME_INFO *)buf;
1588
1589         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1590          info->cAltEntry);
1591         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1592          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1593          info->rgAltEntry[0].dwAltNameChoice);
1594         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1595          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1596           U(info->rgAltEntry[0]).DirectoryName.cbData);
1597         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1598          encodedCommonName, sizeof(encodedCommonName)),
1599          "Unexpected directory name value\n");
1600         LocalFree(buf);
1601     }
1602 }
1603
1604 struct UnicodeExpectedError
1605 {
1606     DWORD   valueType;
1607     LPCWSTR str;
1608     DWORD   errorIndex;
1609     DWORD   error;
1610 };
1611
1612 static const WCHAR oneW[] = { '1',0 };
1613 static const WCHAR aW[] = { 'a',0 };
1614 static const WCHAR quoteW[] = { '"', 0 };
1615
1616 static struct UnicodeExpectedError unicodeErrors[] = {
1617  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1618  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1619  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1620  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1621  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1622  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1623 };
1624
1625 struct UnicodeExpectedResult
1626 {
1627     DWORD           valueType;
1628     LPCWSTR         str;
1629     CRYPT_DATA_BLOB encoded;
1630 };
1631
1632 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1633 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1634 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1635 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1636 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1637 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1638 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1639 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1640 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1641 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1642 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1643 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1644  0x5b };
1645 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1646  0x6f,0x5b };
1647 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1648  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1649 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1650  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1651
1652 static struct UnicodeExpectedResult unicodeResults[] = {
1653  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1654  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1655  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1656  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1657  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1658  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1659  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1660  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1661  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1662  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1663  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1664  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1665  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1666 };
1667
1668 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1669  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1670  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1671 };
1672
1673 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1674 {
1675     BYTE *buf = NULL;
1676     DWORD size = 0, i;
1677     BOOL ret;
1678     CERT_NAME_VALUE value;
1679
1680     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1681      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1682     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1683      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1684     /* Have to have a string of some sort */
1685     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1686     value.Value.pbData = NULL;
1687     value.Value.cbData = 0;
1688     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1689      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1690     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1691      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1692     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1693     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1694      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1695     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1696      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1697     value.dwValueType = CERT_RDN_ANY_TYPE;
1698     value.Value.pbData = (LPBYTE)oneW;
1699     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1700      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1701     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1702      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1703     value.Value.cbData = sizeof(oneW);
1704     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1705      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1706     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1707      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1708     /* An encoded string with specified length isn't good enough either */
1709     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1710     value.Value.pbData = oneUniversal;
1711     value.Value.cbData = sizeof(oneUniversal);
1712     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1713      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1714     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1715      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1716     /* More failure checking */
1717     value.Value.cbData = 0;
1718     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1719     {
1720         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1721         value.dwValueType = unicodeErrors[i].valueType;
1722         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1723          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1724         ok(!ret && GetLastError() == unicodeErrors[i].error,
1725          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1726          unicodeErrors[i].error, GetLastError());
1727         ok(size == unicodeErrors[i].errorIndex,
1728          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1729          size);
1730     }
1731     /* cbData can be zero if the string is NULL-terminated */
1732     value.Value.cbData = 0;
1733     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1734     {
1735         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1736         value.dwValueType = unicodeResults[i].valueType;
1737         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1738          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1739         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1740         if (buf)
1741         {
1742             ok(size == unicodeResults[i].encoded.cbData,
1743              "Value type %d: expected size %d, got %d\n",
1744              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1745             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1746              "Value type %d: unexpected value\n", value.dwValueType);
1747             LocalFree(buf);
1748         }
1749     }
1750     /* These "encode," but they do so by truncating each unicode character
1751      * rather than properly encoding it.  Kept separate from the proper results,
1752      * because the encoded forms won't decode to their original strings.
1753      */
1754     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1755     {
1756         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1757         value.dwValueType = unicodeWeirdness[i].valueType;
1758         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1759          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1760         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1761         if (buf)
1762         {
1763             ok(size == unicodeWeirdness[i].encoded.cbData,
1764              "Value type %d: expected size %d, got %d\n",
1765              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1766             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1767              "Value type %d: unexpected value\n", value.dwValueType);
1768             LocalFree(buf);
1769         }
1770     }
1771 }
1772
1773 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1774 {
1775     if (n <= 0) return 0;
1776     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1777     return *str1 - *str2;
1778 }
1779
1780 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1781 {
1782     DWORD i;
1783
1784     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1785     {
1786         BYTE *buf = NULL;
1787         BOOL ret;
1788         DWORD size = 0;
1789
1790         ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1791          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1792          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1793         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1794         if (ret && buf)
1795         {
1796             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1797
1798             ok(value->dwValueType == unicodeResults[i].valueType,
1799              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1800              value->dwValueType);
1801             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1802              value->Value.cbData / sizeof(WCHAR)),
1803              "Unexpected decoded value for index %d (value type %d)\n", i,
1804              unicodeResults[i].valueType);
1805             LocalFree(buf);
1806         }
1807     }
1808 }
1809
1810 struct encodedOctets
1811 {
1812     const BYTE *val;
1813     const BYTE *encoded;
1814 };
1815
1816 static const unsigned char bin46[] = { 'h','i',0 };
1817 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1818 static const unsigned char bin48[] = {
1819      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1820 static const unsigned char bin49[] = {
1821      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1822 static const unsigned char bin50[] = { 0 };
1823 static const unsigned char bin51[] = { 0x04,0x00,0 };
1824
1825 static const struct encodedOctets octets[] = {
1826     { bin46, bin47 },
1827     { bin48, bin49 },
1828     { bin50, bin51 },
1829 };
1830
1831 static void test_encodeOctets(DWORD dwEncoding)
1832 {
1833     CRYPT_DATA_BLOB blob;
1834     DWORD i;
1835
1836     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1837     {
1838         BYTE *buf = NULL;
1839         BOOL ret;
1840         DWORD bufSize = 0;
1841
1842         blob.cbData = strlen((const char*)octets[i].val);
1843         blob.pbData = (BYTE*)octets[i].val;
1844         ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1845          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1846         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1847         if (buf)
1848         {
1849             ok(buf[0] == 4,
1850              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1851             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1852              buf[1], octets[i].encoded[1]);
1853             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1854              octets[i].encoded[1] + 1), "Got unexpected value\n");
1855             LocalFree(buf);
1856         }
1857     }
1858 }
1859
1860 static void test_decodeOctets(DWORD dwEncoding)
1861 {
1862     DWORD i;
1863
1864     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1865     {
1866         BYTE *buf = NULL;
1867         BOOL ret;
1868         DWORD bufSize = 0;
1869
1870         ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1871          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1872          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1873         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1874         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1875          "Expected size >= %d, got %d\n",
1876            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1877         ok(buf != NULL, "Expected allocated buffer\n");
1878         if (buf)
1879         {
1880             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1881
1882             if (blob->cbData)
1883                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1884                  "Unexpected value\n");
1885             LocalFree(buf);
1886         }
1887     }
1888 }
1889
1890 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1891
1892 struct encodedBits
1893 {
1894     DWORD cUnusedBits;
1895     const BYTE *encoded;
1896     DWORD cbDecoded;
1897     const BYTE *decoded;
1898 };
1899
1900 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1901 static const unsigned char bin53[] = { 0xff,0xff };
1902 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1903 static const unsigned char bin55[] = { 0xff,0xfe };
1904 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1905 static const unsigned char bin57[] = { 0xfe };
1906 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1907
1908 static const struct encodedBits bits[] = {
1909     /* normal test cases */
1910     { 0, bin52, 2, bin53 },
1911     { 1, bin54, 2, bin55 },
1912     /* strange test case, showing cUnusedBits >= 8 is allowed */
1913     { 9, bin56, 1, bin57 },
1914     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1915     { 17, bin58, 0, NULL },
1916 };
1917
1918 static void test_encodeBits(DWORD dwEncoding)
1919 {
1920     DWORD i;
1921
1922     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1923     {
1924         CRYPT_BIT_BLOB blob;
1925         BOOL ret;
1926         BYTE *buf = NULL;
1927         DWORD bufSize = 0;
1928
1929         blob.cbData = sizeof(bytesToEncode);
1930         blob.pbData = (BYTE *)bytesToEncode;
1931         blob.cUnusedBits = bits[i].cUnusedBits;
1932         ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1933          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1934         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1935         if (buf)
1936         {
1937             ok(bufSize == bits[i].encoded[1] + 2,
1938              "Got unexpected size %d, expected %d\n", bufSize,
1939              bits[i].encoded[1] + 2);
1940             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1941              "Unexpected value\n");
1942             LocalFree(buf);
1943         }
1944     }
1945 }
1946
1947 static void test_decodeBits(DWORD dwEncoding)
1948 {
1949     static const BYTE ber[] = "\x03\x02\x01\xff";
1950     static const BYTE berDecoded = 0xfe;
1951     DWORD i;
1952     BOOL ret;
1953     BYTE *buf = NULL;
1954     DWORD bufSize = 0;
1955
1956     /* normal cases */
1957     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1958     {
1959         ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1960          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1961          &bufSize);
1962         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1963         if (buf)
1964         {
1965             CRYPT_BIT_BLOB *blob;
1966
1967             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1968                "Got unexpected size %d\n", bufSize);
1969             blob = (CRYPT_BIT_BLOB *)buf;
1970             ok(blob->cbData == bits[i].cbDecoded,
1971              "Got unexpected length %d, expected %d\n", blob->cbData,
1972              bits[i].cbDecoded);
1973             if (blob->cbData && bits[i].cbDecoded)
1974                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1975                  "Unexpected value\n");
1976             LocalFree(buf);
1977         }
1978     }
1979     /* special case: check that something that's valid in BER but not in DER
1980      * decodes successfully
1981      */
1982     ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1983      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1984     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1985     if (buf)
1986     {
1987         CRYPT_BIT_BLOB *blob;
1988
1989         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1990            "Got unexpected size %d\n", bufSize);
1991         blob = (CRYPT_BIT_BLOB *)buf;
1992         ok(blob->cbData == sizeof(berDecoded),
1993            "Got unexpected length %d\n", blob->cbData);
1994         if (blob->cbData)
1995             ok(*blob->pbData == berDecoded, "Unexpected value\n");
1996         LocalFree(buf);
1997     }
1998 }
1999
2000 struct Constraints2
2001 {
2002     CERT_BASIC_CONSTRAINTS2_INFO info;
2003     const BYTE *encoded;
2004 };
2005
2006 static const unsigned char bin59[] = { 0x30,0x00 };
2007 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2008 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2009 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2010 static const struct Constraints2 constraints2[] = {
2011  /* empty constraints */
2012  { { FALSE, FALSE, 0}, bin59 },
2013  /* can be a CA */
2014  { { TRUE,  FALSE, 0}, bin60 },
2015  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2016   * but that's not the case
2017   */
2018  { { FALSE, TRUE,  0}, bin61 },
2019  /* can be a CA and has path length constraints set */
2020  { { TRUE,  TRUE,  1}, bin62 },
2021 };
2022
2023 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2024 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2025  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2026  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2027  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2028 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2029  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2030  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2031  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2032  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2033
2034 static void test_encodeBasicConstraints(DWORD dwEncoding)
2035 {
2036     DWORD i, bufSize = 0;
2037     CERT_BASIC_CONSTRAINTS_INFO info;
2038     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2039      (LPBYTE)encodedDomainName };
2040     BOOL ret;
2041     BYTE *buf = NULL;
2042
2043     /* First test with the simpler info2 */
2044     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2045     {
2046         ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2047          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2048          &bufSize);
2049         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2050         if (buf)
2051         {
2052             ok(bufSize == constraints2[i].encoded[1] + 2,
2053              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2054              bufSize);
2055             ok(!memcmp(buf, constraints2[i].encoded,
2056              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2057             LocalFree(buf);
2058         }
2059     }
2060     /* Now test with more complex basic constraints */
2061     info.SubjectType.cbData = 0;
2062     info.fPathLenConstraint = FALSE;
2063     info.cSubtreesConstraint = 0;
2064     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2065      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2066     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2067     if (buf)
2068     {
2069         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2070         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2071          "Unexpected value\n");
2072         LocalFree(buf);
2073     }
2074     /* None of the certs I examined had any subtree constraint, but I test one
2075      * anyway just in case.
2076      */
2077     info.cSubtreesConstraint = 1;
2078     info.rgSubtreesConstraint = &nameBlob;
2079     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2080      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2081     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2082     if (buf)
2083     {
2084         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2085         ok(!memcmp(buf, constraintWithDomainName,
2086          sizeof(constraintWithDomainName)), "Unexpected value\n");
2087         LocalFree(buf);
2088     }
2089     /* FIXME: test encoding with subject type. */
2090 }
2091
2092 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2093
2094 static void test_decodeBasicConstraints(DWORD dwEncoding)
2095 {
2096     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2097      0xff };
2098     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2099     DWORD i;
2100     BOOL ret;
2101     BYTE *buf = NULL;
2102     DWORD bufSize = 0;
2103
2104     /* First test with simpler info2 */
2105     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2106     {
2107         ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2108          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2109          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2110         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2111          GetLastError());
2112         if (buf)
2113         {
2114             CERT_BASIC_CONSTRAINTS2_INFO *info =
2115              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2116
2117             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2118              "Unexpected value for item %d\n", i);
2119             LocalFree(buf);
2120         }
2121     }
2122     /* Check with the order of encoded elements inverted */
2123     buf = (PBYTE)1;
2124     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2125      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2126      &bufSize);
2127     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2128      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2129     ok(!buf, "Expected buf to be set to NULL\n");
2130     /* Check with a non-DER bool */
2131     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2132      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2133      (BYTE *)&buf, &bufSize);
2134     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2135     if (buf)
2136     {
2137         CERT_BASIC_CONSTRAINTS2_INFO *info =
2138          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2139
2140         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2141         LocalFree(buf);
2142     }
2143     /* Check with a non-basic constraints value */
2144     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2145      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2146      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2147     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2148      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2149     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2150     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2151      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2152      (BYTE *)&buf, &bufSize);
2153     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2154     if (buf)
2155     {
2156         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2157
2158         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2159         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2160         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2161         LocalFree(buf);
2162     }
2163     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2164      constraintWithDomainName, sizeof(constraintWithDomainName),
2165      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2166     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2167     if (buf)
2168     {
2169         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2170
2171         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2172         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2173         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2174         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2175         {
2176             ok(info->rgSubtreesConstraint[0].cbData ==
2177              sizeof(encodedDomainName), "Wrong size %d\n",
2178              info->rgSubtreesConstraint[0].cbData);
2179             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2180              sizeof(encodedDomainName)), "Unexpected value\n");
2181         }
2182         LocalFree(buf);
2183     }
2184 }
2185
2186 /* These are terrible public keys of course, I'm just testing encoding */
2187 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2188 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2189 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2190 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2191 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2192 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2193 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2194 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2195
2196 struct EncodedRSAPubKey
2197 {
2198     const BYTE *modulus;
2199     size_t modulusLen;
2200     const BYTE *encoded;
2201     size_t decodedModulusLen;
2202 };
2203
2204 struct EncodedRSAPubKey rsaPubKeys[] = {
2205     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2206     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2207     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2208     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2209 };
2210
2211 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2212 {
2213     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2214     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2215     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2216     BOOL ret;
2217     BYTE *buf = NULL;
2218     DWORD bufSize = 0, i;
2219
2220     /* Try with a bogus blob type */
2221     hdr->bType = 2;
2222     hdr->bVersion = CUR_BLOB_VERSION;
2223     hdr->reserved = 0;
2224     hdr->aiKeyAlg = CALG_RSA_KEYX;
2225     rsaPubKey->magic = 0x31415352;
2226     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2227     rsaPubKey->pubexp = 65537;
2228     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2229      sizeof(modulus1));
2230
2231     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2232      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2233      &bufSize);
2234     ok(!ret && GetLastError() == E_INVALIDARG,
2235      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2236     /* Now with a bogus reserved field */
2237     hdr->bType = PUBLICKEYBLOB;
2238     hdr->reserved = 1;
2239     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2240      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2241      &bufSize);
2242     if (buf)
2243     {
2244         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2245          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2246         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2247         LocalFree(buf);
2248     }
2249     /* Now with a bogus blob version */
2250     hdr->reserved = 0;
2251     hdr->bVersion = 0;
2252     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2253      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2254      &bufSize);
2255     if (buf)
2256     {
2257         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2258          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2259         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2260         LocalFree(buf);
2261     }
2262     /* And with a bogus alg ID */
2263     hdr->bVersion = CUR_BLOB_VERSION;
2264     hdr->aiKeyAlg = CALG_DES;
2265     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2266      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2267      &bufSize);
2268     if (buf)
2269     {
2270         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2271          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2272         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2273         LocalFree(buf);
2274     }
2275     /* Check a couple of RSA-related OIDs */
2276     hdr->aiKeyAlg = CALG_RSA_KEYX;
2277     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2278      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2279     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2280      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2281     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2282      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2283     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2284      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2285     /* Finally, all valid */
2286     hdr->aiKeyAlg = CALG_RSA_KEYX;
2287     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2288     {
2289         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2290          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2291         ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2292          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2293         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2294         if (buf)
2295         {
2296             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2297              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2298              bufSize);
2299             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2300              "Unexpected value\n");
2301             LocalFree(buf);
2302         }
2303     }
2304 }
2305
2306 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2307 {
2308     DWORD i;
2309     LPBYTE buf = NULL;
2310     DWORD bufSize = 0;
2311     BOOL ret;
2312
2313     /* Try with a bad length */
2314     ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2315      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2316      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2317     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2318      "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2319     /* Try with a couple of RSA-related OIDs */
2320     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2321      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2322      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2323     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2324      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2325     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2326      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2327      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2328     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2329      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2330     /* Now try success cases */
2331     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2332     {
2333         bufSize = 0;
2334         ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2335          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2336          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2337         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2338         if (buf)
2339         {
2340             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2341             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2342
2343             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2344              rsaPubKeys[i].decodedModulusLen,
2345              "Wrong size %d\n", bufSize);
2346             ok(hdr->bType == PUBLICKEYBLOB,
2347              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2348              hdr->bType);
2349             ok(hdr->bVersion == CUR_BLOB_VERSION,
2350              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2351              CUR_BLOB_VERSION, hdr->bVersion);
2352             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2353              hdr->reserved);
2354             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2355              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2356             ok(rsaPubKey->magic == 0x31415352,
2357              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2358             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2359              "Wrong bit len %d\n", rsaPubKey->bitlen);
2360             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2361              rsaPubKey->pubexp);
2362             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2363              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2364              "Unexpected modulus\n");
2365             LocalFree(buf);
2366         }
2367     }
2368 }
2369
2370 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2371  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2372  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2373
2374 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2375  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2376  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2377  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2378
2379 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2380 {
2381     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2382     CRYPT_SEQUENCE_OF_ANY seq;
2383     DWORD i;
2384     BOOL ret;
2385     BYTE *buf = NULL;
2386     DWORD bufSize = 0;
2387
2388     /* Encode a homogenous sequence */
2389     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2390     {
2391         blobs[i].cbData = ints[i].encoded[1] + 2;
2392         blobs[i].pbData = (BYTE *)ints[i].encoded;
2393     }
2394     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2395     seq.rgValue = blobs;
2396
2397     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2398      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2399     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2400     if (buf)
2401     {
2402         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2403         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2404         LocalFree(buf);
2405     }
2406     /* Change the type of the first element in the sequence, and give it
2407      * another go
2408      */
2409     blobs[0].cbData = times[0].encodedTime[1] + 2;
2410     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2411     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2412      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2413     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2414     if (buf)
2415     {
2416         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2417         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2418          "Unexpected value\n");
2419         LocalFree(buf);
2420     }
2421 }
2422
2423 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2424 {
2425     BOOL ret;
2426     BYTE *buf = NULL;
2427     DWORD bufSize = 0;
2428
2429     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2430      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2431     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2432     if (buf)
2433     {
2434         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2435         DWORD i;
2436
2437         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2438          "Wrong elements %d\n", seq->cValue);
2439         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2440         {
2441             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2442              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2443              seq->rgValue[i].cbData);
2444             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2445              ints[i].encoded[1] + 2), "Unexpected value\n");
2446         }
2447         LocalFree(buf);
2448     }
2449     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2450      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2451      &bufSize);
2452     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2453     if (buf)
2454     {
2455         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2456
2457         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2458          "Wrong elements %d\n", seq->cValue);
2459         /* Just check the first element since it's all that changed */
2460         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2461          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2462          seq->rgValue[0].cbData);
2463         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2464          times[0].encodedTime[1] + 2), "Unexpected value\n");
2465         LocalFree(buf);
2466     }
2467 }
2468
2469 struct encodedExtensions
2470 {
2471     CERT_EXTENSIONS exts;
2472     const BYTE *encoded;
2473 };
2474
2475 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2476 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2477 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2478 static CERT_EXTENSION criticalExt =
2479  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2480 static CERT_EXTENSION nonCriticalExt =
2481  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2482
2483 static const BYTE ext0[] = { 0x30,0x00 };
2484 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2485                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2486 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2487                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2488
2489 static const struct encodedExtensions exts[] = {
2490  { { 0, NULL }, ext0 },
2491  { { 1, &criticalExt }, ext1 },
2492  { { 1, &nonCriticalExt }, ext2 },
2493 };
2494
2495 static void test_encodeExtensions(DWORD dwEncoding)
2496 {
2497     DWORD i;
2498
2499     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2500     {
2501         BOOL ret;
2502         BYTE *buf = NULL;
2503         DWORD bufSize = 0;
2504
2505         ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2506          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2507         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2508         if (buf)
2509         {
2510             ok(bufSize == exts[i].encoded[1] + 2,
2511              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2512             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2513              "Unexpected value\n");
2514             LocalFree(buf);
2515         }
2516     }
2517 }
2518
2519 static void test_decodeExtensions(DWORD dwEncoding)
2520 {
2521     DWORD i;
2522
2523     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2524     {
2525         BOOL ret;
2526         BYTE *buf = NULL;
2527         DWORD bufSize = 0;
2528
2529         ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2530          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2531          NULL, (BYTE *)&buf, &bufSize);
2532         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2533         if (buf)
2534         {
2535             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2536             DWORD j;
2537
2538             ok(ext->cExtension == exts[i].exts.cExtension,
2539              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2540              ext->cExtension);
2541             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2542             {
2543                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2544                  exts[i].exts.rgExtension[j].pszObjId),
2545                  "Expected OID %s, got %s\n",
2546                  exts[i].exts.rgExtension[j].pszObjId,
2547                  ext->rgExtension[j].pszObjId);
2548                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2549                  exts[i].exts.rgExtension[j].Value.pbData,
2550                  exts[i].exts.rgExtension[j].Value.cbData),
2551                  "Unexpected value\n");
2552             }
2553             LocalFree(buf);
2554         }
2555     }
2556 }
2557
2558 /* MS encodes public key info with a NULL if the algorithm identifier's
2559  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2560  * it encodes them by omitting the algorithm parameters.  This latter approach
2561  * seems more correct, so accept either form.
2562  */
2563 struct encodedPublicKey
2564 {
2565     CERT_PUBLIC_KEY_INFO info;
2566     const BYTE *encoded;
2567     const BYTE *encodedNoNull;
2568     CERT_PUBLIC_KEY_INFO decoded;
2569 };
2570
2571 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2572  0xe, 0xf };
2573 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2574
2575 static const unsigned char bin64[] = {
2576     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2577 static const unsigned char bin65[] = {
2578     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2579 static const unsigned char bin66[] = {
2580     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2581 static const unsigned char bin67[] = {
2582     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2583 static const unsigned char bin68[] = {
2584     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2585     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2586 static const unsigned char bin69[] = {
2587     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2588     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2589 static const unsigned char bin70[] = {
2590     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2591     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2592     0x0f};
2593 static const unsigned char bin71[] = {
2594     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2595     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2596     0x0f};
2597 static unsigned char bin72[] = { 0x05,0x00};
2598
2599 static CHAR oid_bogus[] = "1.2.3",
2600             oid_rsa[]   = szOID_RSA;
2601
2602 static const struct encodedPublicKey pubKeys[] = {
2603  /* with a bogus OID */
2604  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2605   bin64, bin65,
2606   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2607  /* some normal keys */
2608  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2609   bin66, bin67,
2610   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2611  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2612   bin68, bin69,
2613   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2614  /* with add'l parameters--note they must be DER-encoded */
2615  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2616   (BYTE *)aKey, 0 } },
2617   bin70, bin71,
2618   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2619   (BYTE *)aKey, 0 } } },
2620 };
2621
2622 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2623 {
2624     DWORD i;
2625
2626     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2627     {
2628         BOOL ret;
2629         BYTE *buf = NULL;
2630         DWORD bufSize = 0;
2631
2632         ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2633          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2634          &bufSize);
2635         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2636         if (buf)
2637         {
2638             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2639              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2640              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2641              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2642             if (bufSize == pubKeys[i].encoded[1] + 2)
2643                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2644                  "Unexpected value\n");
2645             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2646                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2647                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2648             LocalFree(buf);
2649         }
2650     }
2651 }
2652
2653 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2654  const CERT_PUBLIC_KEY_INFO *got)
2655 {
2656     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2657      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2658      got->Algorithm.pszObjId);
2659     ok(expected->Algorithm.Parameters.cbData ==
2660      got->Algorithm.Parameters.cbData,
2661      "Expected parameters of %d bytes, got %d\n",
2662      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2663     if (expected->Algorithm.Parameters.cbData)
2664         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2665          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2666          "Unexpected algorithm parameters\n");
2667     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2668      "Expected public key of %d bytes, got %d\n",
2669      expected->PublicKey.cbData, got->PublicKey.cbData);
2670     if (expected->PublicKey.cbData)
2671         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2672          got->PublicKey.cbData), "Unexpected public key value\n");
2673 }
2674
2675 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2676 {
2677     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2678      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2679      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2680      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2681     DWORD i;
2682     BOOL ret;
2683     BYTE *buf = NULL;
2684     DWORD bufSize = 0;
2685
2686     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2687     {
2688         /* The NULL form decodes to the decoded member */
2689         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2690          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2691          NULL, (BYTE *)&buf, &bufSize);
2692         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2693         if (buf)
2694         {
2695             comparePublicKeyInfo(&pubKeys[i].decoded,
2696              (CERT_PUBLIC_KEY_INFO *)buf);
2697             LocalFree(buf);
2698         }
2699         /* The non-NULL form decodes to the original */
2700         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2701          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2702          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2703         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2704         if (buf)
2705         {
2706             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2707             LocalFree(buf);
2708         }
2709     }
2710     /* Test with bogus (not valid DER) parameters */
2711     ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2712      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2713      NULL, (BYTE *)&buf, &bufSize);
2714     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2715      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2716 }
2717
2718 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2719  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2720  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2721  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2722  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2723 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2724  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2725  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2726  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2727  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2728 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2729  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2730  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2731  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2732  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2733 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2734  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2735  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2736  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2737  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2738  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2739  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2740 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2741  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2742  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2743  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2744  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2745  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2746  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2747 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2748  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2749  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2750  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2751  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2752  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2753  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2754  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2755  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2756  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2757 static const BYTE v1CertWithPubKey[] = {
2758 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2759 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2760 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2761 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2762 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2763 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2764 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2765 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2766 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2767 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2768 0x01,0x01 };
2769 static const BYTE v1CertWithPubKeyNoNull[] = {
2770 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2771 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2772 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2773 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2774 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2775 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2776 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2777 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2778 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2779 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2780 static const BYTE v1CertWithSubjectKeyId[] = {
2781 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2782 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2783 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2784 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2785 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2786 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2787 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2788 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2789 0x4c,0x61,0x6e,0x67,0x00 };
2790
2791 static const BYTE serialNum[] = { 0x01 };
2792
2793 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2794 {
2795     BOOL ret;
2796     BYTE *buf = NULL;
2797     DWORD size = 0;
2798     CERT_INFO info = { 0 };
2799     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2800     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2801     CERT_EXTENSION ext;
2802
2803     /* Test with NULL pvStructInfo */
2804     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2805      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2806     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2807      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2808     /* Test with a V1 cert */
2809     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2810      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2811     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2812     if (buf)
2813     {
2814         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2815          v1Cert[1] + 2, size);
2816         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2817         LocalFree(buf);
2818     }
2819     /* Test v2 cert */
2820     info.dwVersion = CERT_V2;
2821     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2822      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2823     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2824     if (buf)
2825     {
2826         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2827         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2828         LocalFree(buf);
2829     }
2830     /* Test v3 cert */
2831     info.dwVersion = CERT_V3;
2832     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2833      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2834     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2835     if (buf)
2836     {
2837         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2838         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2839         LocalFree(buf);
2840     }
2841     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2842      * API doesn't prevent it)
2843      */
2844     info.dwVersion = CERT_V1;
2845     info.cExtension = 1;
2846     info.rgExtension = &criticalExt;
2847     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2848      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2849     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2850     if (buf)
2851     {
2852         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2853         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2854         LocalFree(buf);
2855     }
2856     /* test v1 cert with a serial number */
2857     info.SerialNumber.cbData = sizeof(serialNum);
2858     info.SerialNumber.pbData = (BYTE *)serialNum;
2859     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2860      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2861     if (buf)
2862     {
2863         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2864         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2865         LocalFree(buf);
2866     }
2867     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2868     info.Issuer.cbData = sizeof(encodedCommonName);
2869     info.Issuer.pbData = (BYTE *)encodedCommonName;
2870     info.Subject.cbData = sizeof(encodedCommonName);
2871     info.Subject.pbData = (BYTE *)encodedCommonName;
2872     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2873      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2874     if (buf)
2875     {
2876         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2877         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2878         LocalFree(buf);
2879     }
2880     /* Add a public key */
2881     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2882     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2883     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2884     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2885      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2886     if (buf)
2887     {
2888         ok(size == sizeof(v1CertWithPubKey) ||
2889          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2890         if (size == sizeof(v1CertWithPubKey))
2891             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2892         else if (size == sizeof(v1CertWithPubKeyNoNull))
2893             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2894              "Got unexpected value\n");
2895         LocalFree(buf);
2896     }
2897     /* Remove the public key, and add a subject key identifier extension */
2898     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2899     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2900     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2901     ext.pszObjId = oid_subject_key_identifier;
2902     ext.fCritical = FALSE;
2903     ext.Value.cbData = sizeof(octetCommonNameValue);
2904     ext.Value.pbData = (BYTE *)octetCommonNameValue;
2905     info.cExtension = 1;
2906     info.rgExtension = &ext;
2907     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2908      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2909     if (buf)
2910     {
2911         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2912         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2913         LocalFree(buf);
2914     }
2915 }
2916
2917 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2918 {
2919     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2920      v1CertWithConstraints, v1CertWithSerial };
2921     BOOL ret;
2922     BYTE *buf = NULL;
2923     DWORD size = 0, i;
2924
2925     /* Test with NULL pbEncoded */
2926     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2927      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2928     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2929      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2930     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2931      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2932     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2933      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2934     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2935      * minimum a cert must have a non-zero serial number, an issuer, and a
2936      * subject.
2937      */
2938     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2939     {
2940         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2941          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2942          (BYTE *)&buf, &size);
2943         ok(!ret, "Expected failure\n");
2944     }
2945     /* Now check with serial number, subject and issuer specified */
2946     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2947      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2948     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2949     if (buf)
2950     {
2951         CERT_INFO *info = (CERT_INFO *)buf;
2952
2953         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2954         ok(info->SerialNumber.cbData == 1,
2955          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2956         ok(*info->SerialNumber.pbData == *serialNum,
2957          "Expected serial number %d, got %d\n", *serialNum,
2958          *info->SerialNumber.pbData);
2959         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2960          "Wrong size %d\n", info->Issuer.cbData);
2961         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2962          "Unexpected issuer\n");
2963         ok(info->Subject.cbData == sizeof(encodedCommonName),
2964          "Wrong size %d\n", info->Subject.cbData);
2965         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2966          info->Subject.cbData), "Unexpected subject\n");
2967         LocalFree(buf);
2968     }
2969     /* Check again with pub key specified */
2970     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2971      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
2972      (BYTE *)&buf, &size);
2973     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2974     if (buf)
2975     {
2976         CERT_INFO *info = (CERT_INFO *)buf;
2977
2978         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2979         ok(info->SerialNumber.cbData == 1,
2980          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2981         ok(*info->SerialNumber.pbData == *serialNum,
2982          "Expected serial number %d, got %d\n", *serialNum,
2983          *info->SerialNumber.pbData);
2984         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2985          "Wrong size %d\n", info->Issuer.cbData);
2986         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2987          "Unexpected issuer\n");
2988         ok(info->Subject.cbData == sizeof(encodedCommonName),
2989          "Wrong size %d\n", info->Subject.cbData);
2990         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2991          info->Subject.cbData), "Unexpected subject\n");
2992         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
2993          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
2994          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
2995         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
2996          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
2997         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
2998          sizeof(aKey)), "Unexpected public key\n");
2999         LocalFree(buf);
3000     }
3001 }
3002
3003 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3004  0xe, 0xf };
3005
3006 static const BYTE signedBigCert[] = {
3007  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3008  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3009  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3010  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3011  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3012  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3013  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3014  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3015  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3016  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3017  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3018  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3019
3020 static void test_encodeCert(DWORD dwEncoding)
3021 {
3022     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3023      * also that bigCert is a NULL-terminated string, so don't count its
3024      * last byte (otherwise the signed cert won't decode.)
3025      */
3026     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3027      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3028     BOOL ret;
3029     BYTE *buf = NULL;
3030     DWORD bufSize = 0;
3031
3032     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3033      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
3034     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3035     if (buf)
3036     {
3037         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3038         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3039         LocalFree(buf);
3040     }
3041 }
3042
3043 static void test_decodeCert(DWORD dwEncoding)
3044 {
3045     BOOL ret;
3046     BYTE *buf = NULL;
3047     DWORD size = 0;
3048
3049     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3050      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3051     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3052     if (buf)
3053     {
3054         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3055
3056         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3057          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3058         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3059          "Unexpected cert\n");
3060         ok(info->Signature.cbData == sizeof(hash),
3061          "Wrong signature size %d\n", info->Signature.cbData);
3062         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3063          "Unexpected signature\n");
3064         LocalFree(buf);
3065     }
3066     /* A signed cert decodes as a CERT_INFO too */
3067     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3068      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3069     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3070     if (buf)
3071     {
3072         CERT_INFO *info = (CERT_INFO *)buf;
3073
3074         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3075         ok(info->SerialNumber.cbData == 1,
3076          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3077         ok(*info->SerialNumber.pbData == *serialNum,
3078          "Expected serial number %d, got %d\n", *serialNum,
3079          *info->SerialNumber.pbData);
3080         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3081          "Wrong size %d\n", info->Issuer.cbData);
3082         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3083          "Unexpected issuer\n");
3084         ok(info->Subject.cbData == sizeof(encodedCommonName),
3085          "Wrong size %d\n", info->Subject.cbData);
3086         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3087          info->Subject.cbData), "Unexpected subject\n");
3088         LocalFree(buf);
3089     }
3090 }
3091
3092 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3093 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3094  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3095  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3096 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3097  0x00, 0x03 };
3098 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3099  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3100  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3101 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3102  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3103  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3104  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3105  0x2e, 0x6f, 0x72, 0x67 };
3106 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3107  CRL_REASON_AFFILIATION_CHANGED;
3108
3109 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3110 {
3111     CRL_DIST_POINTS_INFO info = { 0 };
3112     CRL_DIST_POINT point = { { 0 } };
3113     CERT_ALT_NAME_ENTRY entry = { 0 };
3114     BOOL ret;
3115     BYTE *buf = NULL;
3116     DWORD size = 0;
3117
3118     /* Test with an empty info */
3119     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3120      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3121     ok(!ret && GetLastError() == E_INVALIDARG,
3122      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3123     /* Test with one empty dist point */
3124     info.cDistPoint = 1;
3125     info.rgDistPoint = &point;
3126     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3127      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3128     if (buf)
3129     {
3130         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3131         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3132         LocalFree(buf);
3133     }
3134     /* A dist point with an invalid name */
3135     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3136     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3137     U(entry).pwszURL = (LPWSTR)nihongoURL;
3138     U(point.DistPointName).FullName.cAltEntry = 1;
3139     U(point.DistPointName).FullName.rgAltEntry = &entry;
3140     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3141      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3142     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3143      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3144     /* The first invalid character is at index 7 */
3145     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3146      "Expected invalid char at index 7, got %d\n",
3147      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3148     /* A dist point with (just) a valid name */
3149     U(entry).pwszURL = (LPWSTR)url;
3150     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3151      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3152     if (buf)
3153     {
3154         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3155         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3156         LocalFree(buf);
3157     }
3158     /* A dist point with (just) reason flags */
3159     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3160     point.ReasonFlags.cbData = sizeof(crlReason);
3161     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3162     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3163      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3164     if (buf)
3165     {
3166         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3167         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3168         LocalFree(buf);
3169     }
3170     /* A dist point with just an issuer */
3171     point.ReasonFlags.cbData = 0;
3172     point.CRLIssuer.cAltEntry = 1;
3173     point.CRLIssuer.rgAltEntry = &entry;
3174     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3175      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3176     if (buf)
3177     {
3178         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3179         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3180         LocalFree(buf);
3181     }
3182     /* A dist point with both a name and an issuer */
3183     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3184     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3185      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3186     if (buf)
3187     {
3188         ok(size == sizeof(distPointWithUrlAndIssuer),
3189          "Wrong size %d\n", size);
3190         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3191         LocalFree(buf);
3192     }
3193 }
3194
3195 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3196 {
3197     BOOL ret;
3198     BYTE *buf = NULL;
3199     DWORD size = 0;
3200     PCRL_DIST_POINTS_INFO info;
3201     PCRL_DIST_POINT point;
3202     PCERT_ALT_NAME_ENTRY entry;
3203
3204     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3205      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3206      (BYTE *)&buf, &size);
3207     if (ret)
3208     {
3209         info = (PCRL_DIST_POINTS_INFO)buf;
3210         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3211          "Wrong size %d\n", size);
3212         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3213          info->cDistPoint);
3214         point = info->rgDistPoint;
3215         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3216          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3217          point->DistPointName.dwDistPointNameChoice);
3218         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3219         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3220         LocalFree(buf);
3221     }
3222     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3223      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3224      (BYTE *)&buf, &size);
3225     if (ret)
3226     {
3227         info = (PCRL_DIST_POINTS_INFO)buf;
3228         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3229          "Wrong size %d\n", size);
3230         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3231          info->cDistPoint);
3232         point = info->rgDistPoint;
3233         ok(point->DistPointName.dwDistPointNameChoice ==
3234          CRL_DIST_POINT_FULL_NAME,
3235          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3236          point->DistPointName.dwDistPointNameChoice);
3237         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3238          "Expected 1 name entry, got %d\n",
3239          U(point->DistPointName).FullName.cAltEntry);
3240         entry = U(point->DistPointName).FullName.rgAltEntry;
3241         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3242          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3243         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3244         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3245         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3246         LocalFree(buf);
3247     }
3248     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3249      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3250      NULL, (BYTE *)&buf, &size);
3251     if (ret)
3252     {
3253         info = (PCRL_DIST_POINTS_INFO)buf;
3254         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3255          "Wrong size %d\n", size);
3256         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3257          info->cDistPoint);
3258         point = info->rgDistPoint;
3259         ok(point->DistPointName.dwDistPointNameChoice ==
3260          CRL_DIST_POINT_NO_NAME,
3261          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3262          point->DistPointName.dwDistPointNameChoice);
3263         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3264          "Expected reason length\n");
3265         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3266          "Unexpected reason\n");
3267         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3268         LocalFree(buf);
3269     }
3270     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3271      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3272      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3273     if (ret)
3274     {
3275         info = (PCRL_DIST_POINTS_INFO)buf;
3276         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3277          "Wrong size %d\n", size);
3278         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3279          info->cDistPoint);
3280         point = info->rgDistPoint;
3281         ok(point->DistPointName.dwDistPointNameChoice ==
3282          CRL_DIST_POINT_FULL_NAME,
3283          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3284          point->DistPointName.dwDistPointNameChoice);
3285         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3286          "Expected 1 name entry, got %d\n",
3287          U(point->DistPointName).FullName.cAltEntry);
3288         entry = U(point->DistPointName).FullName.rgAltEntry;
3289         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3290          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3291         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3292         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3293         ok(point->CRLIssuer.cAltEntry == 1,
3294          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3295         entry = point->CRLIssuer.rgAltEntry;
3296         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3297          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3298         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3299         LocalFree(buf);
3300     }
3301 }
3302
3303 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3304 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3305 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3306  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3307  0x67 };
3308
3309 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3310 {
3311     BOOL ret;
3312     BYTE *buf = NULL;
3313     DWORD size = 0;
3314     CRL_ISSUING_DIST_POINT point = { { 0 } };
3315     CERT_ALT_NAME_ENTRY entry;
3316
3317     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3318      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3319     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3320     {
3321         skip("no X509_ISSUING_DIST_POINT encode support\n");
3322         return;
3323     }
3324     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3325      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3326     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
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(emptySequence), "Unexpected size %d\n", size);
3332         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3333         LocalFree(buf);
3334     }
3335     /* nonsensical flags */
3336     point.fOnlyContainsUserCerts = TRUE;
3337     point.fOnlyContainsCACerts = TRUE;
3338     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3339      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3340     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3341     if (buf)
3342     {
3343         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3344         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3345         LocalFree(buf);
3346     }
3347     /* unimplemented name type */
3348     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3349     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3350     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3351      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3352     ok(!ret && GetLastError() == E_INVALIDARG,
3353      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3354     /* empty name */
3355     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3356     U(point.DistPointName).FullName.cAltEntry = 0;
3357     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3358      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3359     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3360     if (buf)
3361     {
3362         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3363         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3364         LocalFree(buf);
3365     }
3366     /* name with URL entry */
3367     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3368     U(entry).pwszURL = (LPWSTR)url;
3369     U(point.DistPointName).FullName.cAltEntry = 1;
3370     U(point.DistPointName).FullName.rgAltEntry = &entry;
3371     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3372      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3373     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3374     if (buf)
3375     {
3376         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3377         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3378         LocalFree(buf);
3379     }
3380 }
3381
3382 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3383  const CERT_ALT_NAME_ENTRY *got)
3384 {
3385     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3386      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3387      got->dwAltNameChoice);
3388     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3389     {
3390         switch (got->dwAltNameChoice)
3391         {
3392         case CERT_ALT_NAME_RFC822_NAME:
3393         case CERT_ALT_NAME_DNS_NAME:
3394         case CERT_ALT_NAME_EDI_PARTY_NAME:
3395         case CERT_ALT_NAME_URL:
3396         case CERT_ALT_NAME_REGISTERED_ID:
3397             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3398              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3399              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3400              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3401              "Unexpected name\n");
3402             break;
3403         case CERT_ALT_NAME_X400_ADDRESS:
3404         case CERT_ALT_NAME_DIRECTORY_NAME:
3405         case CERT_ALT_NAME_IP_ADDRESS:
3406             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3407                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3408             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3409                        U(*got).IPAddress.cbData), "Unexpected value\n");
3410             break;
3411         }
3412     }
3413 }
3414
3415 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3416  const CERT_ALT_NAME_INFO *got)
3417 {
3418     DWORD i;
3419
3420     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3421      expected->cAltEntry, got->cAltEntry);
3422     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3423         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3424 }
3425
3426 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3427  const CRL_DIST_POINT_NAME *got)
3428 {
3429     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3430      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3431     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3432         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3433 }
3434
3435 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3436  const CRL_ISSUING_DIST_POINT *got)
3437 {
3438     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3439     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3440      "Unexpected fOnlyContainsUserCerts\n");
3441     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3442      "Unexpected fOnlyContainsCACerts\n");
3443     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3444      "Unexpected reason flags\n");
3445     ok(got->fIndirectCRL == expected->fIndirectCRL,
3446      "Unexpected fIndirectCRL\n");
3447 }
3448
3449 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3450 {
3451     BOOL ret;
3452     BYTE *buf = NULL;
3453     DWORD size = 0;
3454     CRL_ISSUING_DIST_POINT point = { { 0 } };
3455
3456     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3457      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3458      (BYTE *)&buf, &size);
3459     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3460     {
3461         skip("no X509_ISSUING_DIST_POINT decode support\n");
3462         return;
3463     }
3464     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3465     if (ret)
3466     {
3467         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3468         LocalFree(buf);
3469     }
3470     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3471      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3472      (BYTE *)&buf, &size);
3473     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3474     if (ret)
3475     {
3476         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3477         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3478         LocalFree(buf);
3479     }
3480     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3481      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3482      (BYTE *)&buf, &size);
3483     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3484     if (ret)
3485     {
3486         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3487         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3488         U(point.DistPointName).FullName.cAltEntry = 0;
3489         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3490         LocalFree(buf);
3491     }
3492     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3493      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3494     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3495     if (ret)
3496     {
3497         CERT_ALT_NAME_ENTRY entry;
3498
3499         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3500         U(entry).pwszURL = (LPWSTR)url;
3501         U(point.DistPointName).FullName.cAltEntry = 1;
3502         U(point.DistPointName).FullName.rgAltEntry = &entry;
3503         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3504         LocalFree(buf);
3505     }
3506 }
3507
3508 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3509  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3510  0x30, 0x5a };
3511 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3512  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3513  0x30, 0x30, 0x30, 0x30, 0x5a };
3514 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3515  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3516  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3517  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3518  0x5a };
3519 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3520  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3521  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3522  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3523  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3524  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3525 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3526  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3527  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3528  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3529  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3530  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3531 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3532  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3533  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3534  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3535  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3536  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3537  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3538 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3539  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3540  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3541  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3542  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3543  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3544  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3545 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3546  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3547  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3548  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3549  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3550  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3551  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3552 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3553  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3554  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3555  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3556  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3557  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3558  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3559
3560 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3561 {
3562     BOOL ret;
3563     BYTE *buf = NULL;
3564     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3565     DWORD size = 0;
3566     CRL_INFO info = { 0 };
3567     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3568     CERT_EXTENSION ext;
3569
3570     /* Test with a V1 CRL */
3571     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3572      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3573     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3574     if (buf)
3575     {
3576         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3577         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3578         LocalFree(buf);
3579     }
3580     /* Test v2 CRL */
3581     info.dwVersion = CRL_V2;
3582     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3583      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3584     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3585     if (buf)
3586     {
3587         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3588          v2CRL[1] + 2, size);
3589         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3590         LocalFree(buf);
3591     }
3592     /* v1 CRL with a name */
3593     info.dwVersion = CRL_V1;
3594     info.Issuer.cbData = sizeof(encodedCommonName);
3595     info.Issuer.pbData = (BYTE *)encodedCommonName;
3596     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3597      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3598     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3599     if (buf)
3600     {
3601         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3602         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3603         LocalFree(buf);
3604     }
3605     /* v1 CRL with a name and a NULL entry pointer */
3606     info.cCRLEntry = 1;
3607     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3608      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3609     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3610      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3611     /* now set an empty entry */
3612     info.rgCRLEntry = &entry;
3613     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3614      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3615     if (buf)
3616     {
3617         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3618          "Wrong size %d\n", size);
3619         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3620          "Got unexpected value\n");
3621         LocalFree(buf);
3622     }
3623     /* an entry with a serial number */
3624     entry.SerialNumber.cbData = sizeof(serialNum);
3625     entry.SerialNumber.pbData = (BYTE *)serialNum;
3626     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3627      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3628     if (buf)
3629     {
3630         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3631          "Wrong size %d\n", size);
3632         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3633          "Got unexpected value\n");
3634         LocalFree(buf);
3635     }
3636     /* an entry with an extension */
3637     entry.cExtension = 1;
3638     entry.rgExtension = &criticalExt;
3639     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3640      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3641     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3642     if (buf)
3643     {
3644         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3645         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3646         LocalFree(buf);
3647     }
3648     /* a CRL with an extension */
3649     entry.cExtension = 0;
3650     info.cExtension = 1;
3651     info.rgExtension = &criticalExt;
3652     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3653      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3654     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3655     if (buf)
3656     {
3657         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3658         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3659         LocalFree(buf);
3660     }
3661     /* a v2 CRL with an extension, this time non-critical */
3662     info.dwVersion = CRL_V2;
3663     info.rgExtension = &nonCriticalExt;
3664     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3665      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3666     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3667     if (buf)
3668     {
3669         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3670         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3671         LocalFree(buf);
3672     }
3673     /* a v2 CRL with an issuing dist point extension */
3674     ext.pszObjId = oid_issuing_dist_point;
3675     ext.fCritical = TRUE;
3676     ext.Value.cbData = sizeof(urlIDP);
3677     ext.Value.pbData = (LPBYTE)urlIDP;
3678     entry.rgExtension = &ext;
3679     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3680      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3681     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3682     if (buf)
3683     {
3684         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3685         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3686         LocalFree(buf);
3687     }
3688 }
3689
3690 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3691  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3692  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3693  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3694  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3695  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3696  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3697  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3698  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3699  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3700  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3701  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3702  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3703  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3704  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3705  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3706  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3707  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3708  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3709  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3710  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3711  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3712  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3713  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3714  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3715  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3716  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3717  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3718  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3719  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3720  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3721  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3722  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3723  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3724  0xcd };
3725 static const BYTE verisignCRLWithLotsOfEntries[] = {
3726 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3727 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3728 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3729 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3730 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3731 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3732 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3733 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3734 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3735 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3736 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3737 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3738 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3739 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3740 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3741 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3742 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3743 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3744 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3745 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3746 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3747 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3748 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3749 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3750 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3751 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3752 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3753 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3754 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3755 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3756 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3757 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3758 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3759 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3760 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3761 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3762 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3763 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3764 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3765 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3766 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3767 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3768 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3769 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3770 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3771 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3772 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3773 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3774 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3775 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3776 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3777 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3778 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3779 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3780 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3781 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3782 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3783 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3784 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3785 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3786 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3787 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3788 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3789 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3790 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3791 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3792 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3793 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3794 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3795 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3796 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3797 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3798 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3799 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3800 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3801 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3802 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3803 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3804 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3805 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3806 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3807 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3808 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3809 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3810 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3811 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3812 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3813 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3814 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3815 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3816 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3817 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3818 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3819 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3820 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3821 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3822 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3823 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3824 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3825 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3826 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3827 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3828 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3829 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3830 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3831 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3832 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3833 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3834 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3835 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3836 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3837 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3838 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3839 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3840 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3841 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3842 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3843 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3844 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3845 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3846 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3847 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3848 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3849 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3850 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3851 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3852 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3853 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3854 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3855 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3856 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3857 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3858 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3859 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3860 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3861 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3862 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3863 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3864 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3865 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3866 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3867 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3868 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3869 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3870 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3871 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3872 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3873 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3874 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3875 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3876 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3877 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3878 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3879 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3880 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3881 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3882 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3883 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3884 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3885 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3886 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3887 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3888 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3889 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3890 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3891 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3892 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3893 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3894 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3895 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3896 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3897 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3898 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3899 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3900 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3901 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3902 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3903 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3904 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3905 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3906 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3907 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3908 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3909 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3910 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3911 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3912 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3913 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3914 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3915 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3916 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3917 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3918 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3919 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3920 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3921 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3922 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3923 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3924 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3925 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3926 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3927 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3928 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3929 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3930 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3931 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3932 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3933 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3934 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3935 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3936 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3937 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3938 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3939 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3940 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3941 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3942 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3943 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3944 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3945 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3946 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3947 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3948 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3949 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3950 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3951 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3952 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3953 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3954 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3955 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3956 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3957 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3958 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3959 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3960 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3961 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3962 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3963 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3964 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3965 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3966 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3967 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3968 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3969 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3970 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3971 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3972 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3973 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3974 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3975 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3976 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3977 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3978 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3979 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3980 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3981 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3982 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3983 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3984 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3985 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3986 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3987 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3988 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3989 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3990 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3991 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3992 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3993 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3994 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3995 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3996 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3997 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3998 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3999 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4000 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4001 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4002 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4003 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4004 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4005 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4006 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4007 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4008 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4009 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4010 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4011 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4012 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4013 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4014 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4015 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4016 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4017 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4018 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4019 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4020 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4021 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4022 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4023 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4024 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4025 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4026 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4027 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4028 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4029 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4030 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4031 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4032 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4033 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4034 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4035 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4036 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4037 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4038 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4039 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4040 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4041 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4042 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4043 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4044 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4045 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4046 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4047 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4048 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4049 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4050 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4051 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4052 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4053 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4054 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4055 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4056 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4057 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4058 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4059 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4060 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4061 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4062 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4063 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4064 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4065 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4066 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4067 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4068 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4069 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4070 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4071 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4072 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4073 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4074 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4075 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4076 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4077 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4078 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4079 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4080 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4081 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4082 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4083 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4084 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4085 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4086 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4087 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4088 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4089 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4090 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4091 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4092 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4093 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4094 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4095 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4096 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4097 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4098 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4099 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4100 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4101 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4102 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4103 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4104 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4105 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4106 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4107 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4108 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4109 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4110 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4111 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4112 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4113 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4114 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4115 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4116 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4117 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4118 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4119 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4120 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4121 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4122 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4123 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4124 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4125 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4126 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4127 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4128 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4129 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4130 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4131 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4132 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4133 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4134 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4135 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4136 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4137 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4138 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4139 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4140 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4141 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4142 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4143 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4144 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4145 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4146 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4147 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4148 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4149 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4150 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4151 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4152 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4153 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4154 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4155 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4156 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4157 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4158 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4159 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4160 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4161 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4162 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4163 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4164 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4165 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4166 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4167 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4168 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4169 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4170 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4171 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4172 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4173 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4174 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4175 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4176 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4177 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4178 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4179 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4180 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4181 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4182 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4183 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4184 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4185 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4186 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4187 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4188 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4189 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4190 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4191 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4192 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4193 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4194 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4195 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4196 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4197 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4198 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4199 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4200 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4201 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4202 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4203 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4204 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4205 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4206 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4207 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4208 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4209 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4210 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4211 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4212 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4213 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4214 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4215 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4216 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4217 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4218 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4219 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4220 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4221 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4222 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4223 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4224 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4225 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4226 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4227 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4228 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4229 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4230 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4231 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4232 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4233 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4234
4235 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4236 {
4237     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4238     BOOL ret;
4239     BYTE *buf = NULL;
4240     DWORD size = 0, i;
4241
4242     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4243     {
4244         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4245          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4246          (BYTE *)&buf, &size);
4247         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4248          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4249     }
4250     /* at a minimum, a CRL must contain an issuer: */
4251     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4252      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4253      (BYTE *)&buf, &size);
4254     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4255     if (buf)
4256     {
4257         CRL_INFO *info = (CRL_INFO *)buf;
4258
4259         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4260         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4261          info->cCRLEntry);
4262         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4263          "Wrong issuer size %d\n", info->Issuer.cbData);
4264         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4265          "Unexpected issuer\n");
4266         LocalFree(buf);
4267     }
4268     /* check decoding with an empty CRL entry */
4269     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4270      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4271      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4272     todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4273      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4274     /* with a real CRL entry */
4275     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4276      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4277      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4278     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4279     if (buf)
4280     {
4281         CRL_INFO *info = (CRL_INFO *)buf;
4282         CRL_ENTRY *entry;
4283
4284         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4285         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4286          info->cCRLEntry);
4287         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4288         entry = info->rgCRLEntry;
4289         ok(entry->SerialNumber.cbData == 1,
4290          "Expected serial number size 1, got %d\n",
4291          entry->SerialNumber.cbData);
4292         ok(*entry->SerialNumber.pbData == *serialNum,
4293          "Expected serial number %d, got %d\n", *serialNum,
4294          *entry->SerialNumber.pbData);
4295         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4296          "Wrong issuer size %d\n", info->Issuer.cbData);
4297         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4298          "Unexpected issuer\n");
4299     }
4300     /* a real CRL from verisign that has extensions */
4301     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4302      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4303      NULL, (BYTE *)&buf, &size);
4304     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4305     if (buf)
4306     {
4307         CRL_INFO *info = (CRL_INFO *)buf;
4308         CRL_ENTRY *entry;
4309
4310         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4311         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4312          info->cCRLEntry);
4313         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4314         entry = info->rgCRLEntry;
4315         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4316          info->cExtension);
4317         LocalFree(buf);
4318     }
4319     /* another real CRL from verisign that has lots of entries */
4320     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4321      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4322      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4323     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4324     if (buf)
4325     {
4326         CRL_INFO *info = (CRL_INFO *)buf;
4327
4328         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4329         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4330          info->cCRLEntry);
4331         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4332          info->cExtension);
4333         LocalFree(buf);
4334     }
4335     /* and finally, with an extension */
4336     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4337      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4338      NULL, (BYTE *)&buf, &size);
4339     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4340     if (buf)
4341     {
4342         CRL_INFO *info = (CRL_INFO *)buf;
4343         CRL_ENTRY *entry;
4344
4345         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4346         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4347          info->cCRLEntry);
4348         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4349         entry = info->rgCRLEntry;
4350         ok(entry->SerialNumber.cbData == 1,
4351          "Expected serial number size 1, got %d\n",
4352          entry->SerialNumber.cbData);
4353         ok(*entry->SerialNumber.pbData == *serialNum,
4354          "Expected serial number %d, got %d\n", *serialNum,
4355          *entry->SerialNumber.pbData);
4356         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4357          "Wrong issuer size %d\n", info->Issuer.cbData);
4358         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4359          "Unexpected issuer\n");
4360         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4361          info->cExtension);
4362     }
4363     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4364      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4365      NULL, (BYTE *)&buf, &size);
4366     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4367     if (buf)
4368     {
4369         CRL_INFO *info = (CRL_INFO *)buf;
4370
4371         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4372          info->cExtension);
4373         LocalFree(buf);
4374     }
4375     /* And again, with an issuing dist point */
4376     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4377      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4378      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4379     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4380     if (buf)
4381     {
4382         CRL_INFO *info = (CRL_INFO *)buf;
4383
4384         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4385          info->cExtension);
4386         LocalFree(buf);
4387     }
4388 }
4389
4390 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4391  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4392 static const BYTE encodedUsage[] = {
4393  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4394  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4395  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4396
4397 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4398 {
4399     BOOL ret;
4400     BYTE *buf = NULL;
4401     DWORD size = 0;
4402     CERT_ENHKEY_USAGE usage;
4403
4404     /* Test with empty usage */
4405     usage.cUsageIdentifier = 0;
4406     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4407      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4408     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4409     if (buf)
4410     {
4411         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4412         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4413         LocalFree(buf);
4414     }
4415     /* Test with a few usages */
4416     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4417     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4418     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4419      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4420     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4421     if (buf)
4422     {
4423         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4424         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4425         LocalFree(buf);
4426     }
4427 }
4428
4429 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4430 {
4431     BOOL ret;
4432     LPBYTE buf = NULL;
4433     DWORD size = 0;
4434
4435     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4436      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4437      (BYTE *)&buf, &size);
4438     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4439     if (buf)
4440     {
4441         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4442
4443         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4444          "Wrong size %d\n", size);
4445         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4446          usage->cUsageIdentifier);
4447         LocalFree(buf);
4448     }
4449     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4450      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4451      (BYTE *)&buf, &size);
4452     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4453     if (buf)
4454     {
4455         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4456         DWORD i;
4457
4458         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4459          "Wrong size %d\n", size);
4460         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4461          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4462         for (i = 0; i < usage->cUsageIdentifier; i++)
4463             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4464              "Expected OID %s, got %s\n", keyUsages[i],
4465              usage->rgpszUsageIdentifier[i]);
4466         LocalFree(buf);
4467     }
4468 }
4469
4470 static BYTE keyId[] = { 1,2,3,4 };
4471 static const BYTE authorityKeyIdWithId[] = {
4472  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4473 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4474  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4475  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4476 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4477
4478 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4479 {
4480     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4481     BOOL ret;
4482     BYTE *buf = NULL;
4483     DWORD size = 0;
4484
4485     /* Test with empty id */
4486     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4487      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4488     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4489     if (buf)
4490     {
4491         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4492         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4493         LocalFree(buf);
4494     }
4495     /* With just a key id */
4496     info.KeyId.cbData = sizeof(keyId);
4497     info.KeyId.pbData = keyId;
4498     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4499      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4500     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4501     if (buf)
4502     {
4503         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4504         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4505         LocalFree(buf);
4506     }
4507     /* With just an issuer */
4508     info.KeyId.cbData = 0;
4509     info.CertIssuer.cbData = sizeof(encodedCommonName);
4510     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4511     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4512      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4513     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4514     if (buf)
4515     {
4516         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4517          size);
4518         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4519         LocalFree(buf);
4520     }
4521     /* With just a serial number */
4522     info.CertIssuer.cbData = 0;
4523     info.CertSerialNumber.cbData = sizeof(serialNum);
4524     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4525     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4526      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4527     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4528     if (buf)
4529     {
4530         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4531          size);
4532         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4533         LocalFree(buf);
4534     }
4535 }
4536
4537 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4538 {
4539     BOOL ret;
4540     LPBYTE buf = NULL;
4541     DWORD size = 0;
4542
4543     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4544      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4545      (BYTE *)&buf, &size);
4546     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4547     if (buf)
4548     {
4549         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4550
4551         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4552          size);
4553         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4554         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4555         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4556         LocalFree(buf);
4557     }
4558     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4559      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4560      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4561     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4562     if (buf)
4563     {
4564         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4565
4566         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4567          size);
4568         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4569         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4570          "Unexpected key id\n");
4571         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4572         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4573         LocalFree(buf);
4574     }
4575     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4576      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4577      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4578     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4579     if (buf)
4580     {
4581         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4582
4583         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4584          size);
4585         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4586         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4587          "Unexpected issuer len\n");
4588         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4589          sizeof(encodedCommonName)), "Unexpected issuer\n");
4590         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4591         LocalFree(buf);
4592     }
4593     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4594      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4595      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4596     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4597     if (buf)
4598     {
4599         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4600
4601         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4602          size);
4603         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4604         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4605         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4606          "Unexpected serial number len\n");
4607         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4608          "Unexpected serial number\n");
4609         LocalFree(buf);
4610     }
4611 }
4612
4613 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4614  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4615  0x6f,0x72,0x67 };
4616
4617 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4618 {
4619     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4620     CERT_ALT_NAME_ENTRY entry = { 0 };
4621     BOOL ret;
4622     BYTE *buf = NULL;
4623     DWORD size = 0;
4624
4625     /* Test with empty id */
4626     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4627      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4628     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4629     if (buf)
4630     {
4631         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4632         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4633         LocalFree(buf);
4634     }
4635     /* With just a key id */
4636     info.KeyId.cbData = sizeof(keyId);
4637     info.KeyId.pbData = keyId;
4638     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4639      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4640     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4641     if (buf)
4642     {
4643         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4644          size);
4645         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4646         LocalFree(buf);
4647     }
4648     /* With a bogus issuer name */
4649     info.KeyId.cbData = 0;
4650     info.AuthorityCertIssuer.cAltEntry = 1;
4651     info.AuthorityCertIssuer.rgAltEntry = &entry;
4652     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4653      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4654     ok(!ret && GetLastError() == E_INVALIDARG,
4655      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4656     /* With an issuer name */
4657     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4658     U(entry).pwszURL = (LPWSTR)url;
4659     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4660      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4661     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4662     if (buf)
4663     {
4664         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4665          size);
4666         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4667          "Unexpected value\n");
4668         LocalFree(buf);
4669     }
4670     /* With just a serial number */
4671     info.AuthorityCertIssuer.cAltEntry = 0;
4672     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4673     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4674     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4675      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4676     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4677     if (buf)
4678     {
4679         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4680          size);
4681         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4682         LocalFree(buf);
4683     }
4684 }
4685
4686 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4687 {
4688     BOOL ret;
4689     LPBYTE buf = NULL;
4690     DWORD size = 0;
4691
4692     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4693      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4694      (BYTE *)&buf, &size);
4695     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4696     if (buf)
4697     {
4698         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4699
4700         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4701          size);
4702         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4703         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4704          "Expected no issuer name entries\n");
4705         ok(info->AuthorityCertSerialNumber.cbData == 0,
4706          "Expected no serial number\n");
4707         LocalFree(buf);
4708     }
4709     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4710      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4711      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4712     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4713     if (buf)
4714     {
4715         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4716
4717         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4718          size);
4719         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4720         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4721          "Unexpected key id\n");
4722         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4723          "Expected no issuer name entries\n");
4724         ok(info->AuthorityCertSerialNumber.cbData == 0,
4725          "Expected no serial number\n");
4726         LocalFree(buf);
4727     }
4728     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4729      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4730      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4731     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4732     if (buf)
4733     {
4734         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4735
4736         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4737          size);
4738         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4739         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4740          "Expected 1 issuer entry, got %d\n",
4741          info->AuthorityCertIssuer.cAltEntry);
4742         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4743          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4744          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4745         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4746          url), "Unexpected URL\n");
4747         ok(info->AuthorityCertSerialNumber.cbData == 0,
4748          "Expected no serial number\n");
4749         LocalFree(buf);
4750     }
4751     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4752      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4753      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4754     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4755     if (buf)
4756     {
4757         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4758
4759         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4760          size);
4761         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4762         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4763          "Expected no issuer name entries\n");
4764         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4765          "Unexpected serial number len\n");
4766         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4767          sizeof(serialNum)), "Unexpected serial number\n");
4768         LocalFree(buf);
4769     }
4770 }
4771
4772 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
4773 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
4774  0x03,0,0,0,0,0,0 };
4775 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
4776  0xa0,0x01,0x01 };
4777 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
4778  0x03,0x02,0x01,0x01 };
4779 static BYTE bogusDER[] = { 1 };
4780
4781 static void test_encodePKCSContentInfo(DWORD dwEncoding)
4782 {
4783     BOOL ret;
4784     BYTE *buf = NULL;
4785     DWORD size = 0;
4786     CRYPT_CONTENT_INFO info = { 0 };
4787     char oid1[] = "1.2.3";
4788
4789     SetLastError(0xdeadbeef);
4790     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
4791      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4792     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4793      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4794     SetLastError(0xdeadbeef);
4795     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4796      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4797     ok(!ret && GetLastError() == E_INVALIDARG,
4798      "Expected E_INVALIDARG, got %x\n", GetLastError());
4799     info.pszObjId = oid1;
4800     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4801      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4802     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4803     if (buf)
4804     {
4805         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
4806         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
4807         LocalFree(buf);
4808     }
4809     info.Content.pbData = bogusDER;
4810     info.Content.cbData = sizeof(bogusDER);
4811     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4812      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4813     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
4814     if (buf)
4815     {
4816         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
4817         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
4818         LocalFree(buf);
4819     }
4820     info.Content.pbData = (BYTE *)ints[0].encoded;
4821     info.Content.cbData = ints[0].encoded[1] + 2;
4822     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4823      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4824     if (buf)
4825     {
4826         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
4827         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
4828         LocalFree(buf);
4829     }
4830 }
4831
4832 static const BYTE indefiniteSignedPKCSContent[] = {
4833 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
4834 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
4835 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
4836 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
4837 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
4838 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
4839 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
4840 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4841 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
4842 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
4843 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
4844 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
4845 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
4846 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
4847 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
4848 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
4849 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
4850 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
4851 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
4852 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
4853 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
4854 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
4855 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
4856 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
4857 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
4858 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
4859 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
4860 0x00,0x00,0x00,0x00,0x00,0x00 };
4861
4862 static void test_decodePKCSContentInfo(DWORD dwEncoding)
4863 {
4864     BOOL ret;
4865     LPBYTE buf = NULL;
4866     DWORD size = 0;
4867     CRYPT_CONTENT_INFO *info;
4868
4869     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4870      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
4871      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4872     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4873     if (buf)
4874     {
4875         info = (CRYPT_CONTENT_INFO *)buf;
4876
4877         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4878          info->pszObjId);
4879         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
4880          info->Content.cbData);
4881         LocalFree(buf);
4882     }
4883     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4884      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
4885      0, NULL, NULL, &size);
4886     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4887     SetLastError(0xdeadbeef);
4888     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4889      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
4890      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4891     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4892      * I doubt an app depends on that.
4893      */
4894     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4895      GetLastError() == CRYPT_E_ASN1_CORRUPT),
4896      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4897      GetLastError());
4898     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4899      intPKCSContentInfo, sizeof(intPKCSContentInfo),
4900      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4901     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4902     if (buf)
4903     {
4904         info = (CRYPT_CONTENT_INFO *)buf;
4905
4906         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4907          info->pszObjId);
4908         ok(info->Content.cbData == ints[0].encoded[1] + 2,
4909          "Unexpected size %d\n", info->Content.cbData);
4910         ok(!memcmp(info->Content.pbData, ints[0].encoded,
4911          info->Content.cbData), "Unexpected value\n");
4912         LocalFree(buf);
4913     }
4914     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4915      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
4916      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4917     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4918     if (buf)
4919     {
4920         info = (CRYPT_CONTENT_INFO *)buf;
4921
4922         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
4923          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
4924         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
4925          info->Content.cbData);
4926         LocalFree(buf);
4927     }
4928 }
4929
4930 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
4931  0x00 };
4932 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
4933  0x01 };
4934 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
4935  0x02,0x01,0x01 };
4936
4937 static void test_encodePKCSAttribute(DWORD dwEncoding)
4938 {
4939     CRYPT_ATTRIBUTE attr = { 0 };
4940     BOOL ret;
4941     LPBYTE buf = NULL;
4942     DWORD size = 0;
4943     CRYPT_ATTR_BLOB blob;
4944     char oid[] = "1.2.3";
4945
4946     SetLastError(0xdeadbeef);
4947     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
4948      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4949     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4950      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4951     SetLastError(0xdeadbeef);
4952     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4953      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4954     ok(!ret && GetLastError() == E_INVALIDARG,
4955      "Expected E_INVALIDARG, got %x\n", GetLastError());
4956     attr.pszObjId = oid;
4957     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4958      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4959     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4960     if (buf)
4961     {
4962         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
4963         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
4964         LocalFree(buf);
4965     }
4966     blob.cbData = sizeof(bogusDER);
4967     blob.pbData = bogusDER;
4968     attr.cValue = 1;
4969     attr.rgValue = &blob;
4970     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4971      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4972     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4973     if (buf)
4974     {
4975         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
4976         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
4977         LocalFree(buf);
4978     }
4979     blob.pbData = (BYTE *)ints[0].encoded;
4980     blob.cbData = ints[0].encoded[1] + 2;
4981     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4982      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4983     if (buf)
4984     {
4985         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
4986         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
4987         LocalFree(buf);
4988     }
4989 }
4990
4991 static void test_decodePKCSAttribute(DWORD dwEncoding)
4992 {
4993     BOOL ret;
4994     LPBYTE buf = NULL;
4995     DWORD size = 0;
4996     CRYPT_ATTRIBUTE *attr;
4997
4998     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4999      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5000      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5001     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5002     if (buf)
5003     {
5004         attr = (CRYPT_ATTRIBUTE *)buf;
5005
5006         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5007          attr->pszObjId);
5008         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5009         LocalFree(buf);
5010     }
5011     SetLastError(0xdeadbeef);
5012     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5013      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5014      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5015     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5016      * I doubt an app depends on that.
5017      */
5018     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5019      GetLastError() == CRYPT_E_ASN1_CORRUPT),
5020      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5021      GetLastError());
5022     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5023      intPKCSAttr, sizeof(intPKCSAttr),
5024      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5025     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5026     if (buf)
5027     {
5028         attr = (CRYPT_ATTRIBUTE *)buf;
5029
5030         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5031          attr->pszObjId);
5032         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5033         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5034          "Unexpected size %d\n", attr->rgValue[0].cbData);
5035         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5036          attr->rgValue[0].cbData), "Unexpected value\n");
5037     }
5038 }
5039
5040 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5041 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5042  0x2a,0x03,0x31,0x00 };
5043 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5044  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5045
5046 static void test_encodePKCSAttributes(DWORD dwEncoding)
5047 {
5048     CRYPT_ATTRIBUTES attributes = { 0 };
5049     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5050     CRYPT_ATTR_BLOB blob;
5051     BOOL ret;
5052     LPBYTE buf = NULL;
5053     DWORD size = 0;
5054     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5055
5056     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5057      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5058     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5059     if (buf)
5060     {
5061         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5062         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5063         LocalFree(buf);
5064     }
5065     attributes.cAttr = 1;
5066     attributes.rgAttr = attr;
5067     SetLastError(0xdeadbeef);
5068     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5069      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5070     ok(!ret && GetLastError() == E_INVALIDARG,
5071      "Expected E_INVALIDARG, got %x\n", GetLastError());
5072     attr[0].pszObjId = oid1;
5073     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5074      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5075     if (buf)
5076     {
5077         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5078         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5079         LocalFree(buf);
5080     }
5081     attr[1].pszObjId = oid2;
5082     attr[1].cValue = 1;
5083     attr[1].rgValue = &blob;
5084     blob.pbData = (BYTE *)ints[0].encoded;
5085     blob.cbData = ints[0].encoded[1] + 2;
5086     attributes.cAttr = 2;
5087     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5088      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5089     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5090     if (buf)
5091     {
5092         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5093         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5094         LocalFree(buf);
5095     }
5096 }
5097
5098 static void test_decodePKCSAttributes(DWORD dwEncoding)
5099 {
5100     BOOL ret;
5101     LPBYTE buf = NULL;
5102     DWORD size = 0;
5103     CRYPT_ATTRIBUTES *attributes;
5104
5105     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5106      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5107      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5108     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5109     if (buf)
5110     {
5111         attributes = (CRYPT_ATTRIBUTES *)buf;
5112         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5113          attributes->cAttr);
5114         LocalFree(buf);
5115     }
5116     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5117      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5118      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5119     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5120     if (buf)
5121     {
5122         attributes = (CRYPT_ATTRIBUTES *)buf;
5123         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5124          attributes->cAttr);
5125         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5126          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5127         ok(attributes->rgAttr[0].cValue == 0,
5128          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5129         LocalFree(buf);
5130     }
5131     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5132      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5133      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5134     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5135     if (buf)
5136     {
5137         attributes = (CRYPT_ATTRIBUTES *)buf;
5138         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5139          attributes->cAttr);
5140         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5141          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5142         ok(attributes->rgAttr[0].cValue == 0,
5143          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5144         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5145          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5146         ok(attributes->rgAttr[1].cValue == 1,
5147          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5148         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5149          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5150         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5151          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5152         LocalFree(buf);
5153     }
5154 }
5155
5156 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
5157  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5158  0x67 };
5159 static const BYTE minimalPKCSSigner[] = {
5160  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5161  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5162  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
5163 static const BYTE PKCSSignerWithSerial[] = {
5164  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5165  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5166  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5167  0x00 };
5168 static const BYTE PKCSSignerWithHashAlgo[] = {
5169  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5170  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5171  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5172  0x00,0x04,0x00 };
5173 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
5174  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5175  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5176  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
5177  0x06,0x05,0x00,0x04,0x00 };
5178 static const BYTE PKCSSignerWithHash[] = {
5179  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5180  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5181  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
5182  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
5183  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
5184 static const BYTE PKCSSignerWithAuthAttr[] = {
5185 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5186 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5187 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
5188 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
5189 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
5190 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
5191 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
5192
5193 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
5194 {
5195     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
5196     BOOL ret;
5197     LPBYTE buf = NULL;
5198     DWORD size = 0;
5199     CMSG_SIGNER_INFO info = { 0 };
5200     char oid_common_name[] = szOID_COMMON_NAME;
5201     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
5202      (LPBYTE)encodedCommonName };
5203     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
5204
5205     SetLastError(0xdeadbeef);
5206     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5207      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5208     ok(!ret && GetLastError() == E_INVALIDARG,
5209      "Expected E_INVALIDARG, got %08x\n", GetLastError());
5210     /* To be encoded, a signer must have an issuer at least, and the encoding
5211      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
5212      * see decoding tests.)
5213      */
5214     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
5215     info.Issuer.pbData = encodedCommonNameNoNull;
5216     SetLastError(0xdeadbeef);
5217     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5218      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5219     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5220         ok(!ret && GetLastError() == E_INVALIDARG,
5221          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5222     else
5223     {
5224         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5225         if (buf)
5226         {
5227             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
5228             if (size == sizeof(minimalPKCSSigner))
5229                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
5230             else
5231                 ok(0, "Unexpected value\n");
5232             LocalFree(buf);
5233         }
5234     }
5235     info.SerialNumber.cbData = sizeof(serialNum);
5236     info.SerialNumber.pbData = (BYTE *)serialNum;
5237     SetLastError(0xdeadbeef);
5238     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5239      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5240     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5241         ok(!ret && GetLastError() == E_INVALIDARG,
5242          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5243     else
5244     {
5245         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5246         if (buf)
5247         {
5248             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
5249              size);
5250             if (size == sizeof(PKCSSignerWithSerial))
5251                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
5252                  "Unexpected value\n");
5253             else
5254                 ok(0, "Unexpected value\n");
5255             LocalFree(buf);
5256         }
5257     }
5258     info.HashAlgorithm.pszObjId = oid1;
5259     SetLastError(0xdeadbeef);
5260     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5261      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5262     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5263         ok(!ret && GetLastError() == E_INVALIDARG,
5264          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5265     else
5266     {
5267         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5268         if (buf)
5269         {
5270             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
5271              size);
5272             if (size == sizeof(PKCSSignerWithHashAlgo))
5273                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
5274                  "Unexpected value\n");
5275             else
5276                 ok(0, "Unexpected value\n");
5277             LocalFree(buf);
5278         }
5279     }
5280     info.HashEncryptionAlgorithm.pszObjId = oid2;
5281     SetLastError(0xdeadbeef);
5282     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5283      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5284     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5285         ok(!ret && GetLastError() == E_INVALIDARG,
5286          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5287     else
5288     {
5289         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5290         if (buf)
5291         {
5292             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
5293              "Unexpected size %d\n", size);
5294             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
5295                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
5296                  "Unexpected value\n");
5297             else
5298                 ok(0, "Unexpected value\n");
5299             LocalFree(buf);
5300         }
5301     }
5302     info.EncryptedHash.cbData = sizeof(hash);
5303     info.EncryptedHash.pbData = (BYTE *)hash;
5304     SetLastError(0xdeadbeef);
5305     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5306      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5307     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5308         ok(!ret && GetLastError() == E_INVALIDARG,
5309          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5310     else
5311     {
5312         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5313         if (buf)
5314         {
5315             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
5316              size);
5317             if (size == sizeof(PKCSSignerWithHash))
5318                 ok(!memcmp(buf, PKCSSignerWithHash, size),
5319                  "Unexpected value\n");
5320             else
5321                 ok(0, "Unexpected value\n");
5322             LocalFree(buf);
5323         }
5324     }
5325     info.AuthAttrs.cAttr = 1;
5326     info.AuthAttrs.rgAttr = &attr;
5327     SetLastError(0xdeadbeef);
5328     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5329      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5330     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5331         ok(!ret && GetLastError() == E_INVALIDARG,
5332          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5333     else
5334     {
5335         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5336         if (buf)
5337         {
5338             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
5339              size);
5340             if (size == sizeof(PKCSSignerWithAuthAttr))
5341                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
5342                  "Unexpected value\n");
5343             else
5344                 ok(0, "Unexpected value\n");
5345             LocalFree(buf);
5346         }
5347     }
5348 }
5349
5350 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
5351 {
5352     BOOL ret;
5353     LPBYTE buf = NULL;
5354     DWORD size = 0;
5355     CMSG_SIGNER_INFO *info;
5356
5357     /* A PKCS signer can't be decoded without a serial number. */
5358     SetLastError(0xdeadbeef);
5359     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5360      minimalPKCSSigner, sizeof(minimalPKCSSigner),
5361      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5362     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
5363      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
5364     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5365      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
5366      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5367     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5368     if (buf)
5369     {
5370         info = (CMSG_SIGNER_INFO *)buf;
5371         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5372          info->dwVersion);
5373         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5374          "Unexpected size %d\n", info->Issuer.cbData);
5375         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5376          info->Issuer.cbData), "Unexpected value\n");
5377         ok(info->SerialNumber.cbData == sizeof(serialNum),
5378          "Unexpected size %d\n", info->SerialNumber.cbData);
5379         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5380          "Unexpected value\n");
5381         LocalFree(buf);
5382     }
5383     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5384      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
5385      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5386     if (buf)
5387     {
5388         info = (CMSG_SIGNER_INFO *)buf;
5389         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5390          info->dwVersion);
5391         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5392          "Unexpected size %d\n", info->Issuer.cbData);
5393         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5394          info->Issuer.cbData), "Unexpected value\n");
5395         ok(info->SerialNumber.cbData == sizeof(serialNum),
5396          "Unexpected size %d\n", info->SerialNumber.cbData);
5397         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5398          "Unexpected value\n");
5399         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5400          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5401         LocalFree(buf);
5402     }
5403     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5404      PKCSSignerWithHashAndEncryptionAlgo,
5405      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
5406      NULL, (BYTE *)&buf, &size);
5407     if (buf)
5408     {
5409         info = (CMSG_SIGNER_INFO *)buf;
5410         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5411          info->dwVersion);
5412         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5413          "Unexpected size %d\n", info->Issuer.cbData);
5414         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5415          info->Issuer.cbData), "Unexpected value\n");
5416         ok(info->SerialNumber.cbData == sizeof(serialNum),
5417          "Unexpected size %d\n", info->SerialNumber.cbData);
5418         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5419          "Unexpected value\n");
5420         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5421          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5422         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5423          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5424         LocalFree(buf);
5425     }
5426     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5427      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
5428      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5429     if (buf)
5430     {
5431         info = (CMSG_SIGNER_INFO *)buf;
5432         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5433          info->dwVersion);
5434         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5435          "Unexpected size %d\n", info->Issuer.cbData);
5436         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5437          info->Issuer.cbData), "Unexpected value\n");
5438         ok(info->SerialNumber.cbData == sizeof(serialNum),
5439          "Unexpected size %d\n", info->SerialNumber.cbData);
5440         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5441          "Unexpected value\n");
5442         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5443          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5444         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5445          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5446         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
5447          info->EncryptedHash.cbData);
5448         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
5449          "Unexpected value\n");
5450         LocalFree(buf);
5451     }
5452     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5453      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
5454      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5455     if (buf)
5456     {
5457         info = (CMSG_SIGNER_INFO *)buf;
5458         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
5459          info->AuthAttrs.cAttr);
5460         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
5461          "Expected %s, got %s\n", szOID_COMMON_NAME,
5462          info->AuthAttrs.rgAttr[0].pszObjId);
5463         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
5464          info->AuthAttrs.rgAttr[0].cValue);
5465         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
5466          sizeof(encodedCommonName), "Unexpected size %d\n",
5467          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
5468         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
5469          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
5470         LocalFree(buf);
5471     }
5472 }
5473
5474 static BYTE emptyDNSPermittedConstraints[] = {
5475 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
5476 static BYTE emptyDNSExcludedConstraints[] = {
5477 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
5478 static BYTE DNSExcludedConstraints[] = {
5479 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
5480 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5481 static BYTE permittedAndExcludedConstraints[] = {
5482 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
5483 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
5484 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5485 static BYTE permittedAndExcludedWithMinConstraints[] = {
5486 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
5487 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
5488 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5489 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
5490 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
5491 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
5492 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5493
5494 static void test_encodeNameConstraints(DWORD dwEncoding)
5495 {
5496     BOOL ret;
5497     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
5498     CERT_GENERAL_SUBTREE permitted = { { 0 } };
5499     CERT_GENERAL_SUBTREE excluded = { { 0 } };
5500     LPBYTE buf;
5501     DWORD size;
5502
5503     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5504      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5505     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5506     if (ret)
5507     {
5508         ok(size == sizeof(emptySequence), "Unexpected size\n");
5509         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
5510         LocalFree(buf);
5511     }
5512     constraints.cPermittedSubtree = 1;
5513     constraints.rgPermittedSubtree = &permitted;
5514     SetLastError(0xdeadbeef);
5515     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5516      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5517     ok(!ret && GetLastError() == E_INVALIDARG,
5518      "Expected E_INVALIDARG, got %08x\n", GetLastError());
5519     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
5520     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5521      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5522     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5523     if (ret)
5524     {
5525         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
5526         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
5527          "Unexpected value\n");
5528         LocalFree(buf);
5529     }
5530     constraints.cPermittedSubtree = 0;
5531     constraints.cExcludedSubtree = 1;
5532     constraints.rgExcludedSubtree = &excluded;
5533     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
5534     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5535      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5536     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5537     if (ret)
5538     {
5539         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
5540         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
5541          "Unexpected value\n");
5542         LocalFree(buf);
5543     }
5544     excluded.Base.pwszURL = (LPWSTR)url;
5545     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5546      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5547     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5548     if (ret)
5549     {
5550         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
5551         ok(!memcmp(buf, DNSExcludedConstraints, size),
5552          "Unexpected value\n");
5553         LocalFree(buf);
5554     }
5555     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
5556     permitted.Base.IPAddress.cbData = sizeof(encodedIPAddr);
5557     permitted.Base.IPAddress.pbData = (LPBYTE)encodedIPAddr;
5558     constraints.cPermittedSubtree = 1;
5559     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5560      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5561     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5562     if (ret)
5563     {
5564         ok(size == sizeof(permittedAndExcludedConstraints),
5565          "Unexpected size\n");
5566         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
5567          "Unexpected value\n");
5568         LocalFree(buf);
5569     }
5570     permitted.dwMinimum = 5;
5571     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5572      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5573     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5574     if (ret)
5575     {
5576         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
5577          "Unexpected size\n");
5578         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
5579          "Unexpected value\n");
5580         LocalFree(buf);
5581     }
5582     permitted.fMaximum = TRUE;
5583     permitted.dwMaximum = 3;
5584     SetLastError(0xdeadbeef);
5585     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5586      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5587     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5588     if (ret)
5589     {
5590         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
5591          "Unexpected size\n");
5592         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
5593          "Unexpected value\n");
5594         LocalFree(buf);
5595     }
5596 }
5597
5598 struct EncodedNameConstraints
5599 {
5600     CRYPT_DATA_BLOB            encoded;
5601     CERT_NAME_CONSTRAINTS_INFO constraints;
5602 };
5603
5604 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
5605  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
5606 static CERT_GENERAL_SUBTREE DNSSubtree = {
5607  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
5608 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
5609  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
5610 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
5611  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
5612 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
5613  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
5614
5615 struct EncodedNameConstraints encodedNameConstraints[] = {
5616  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
5617  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
5618    { 1, &emptyDNSSubtree, 0, NULL } },
5619  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
5620    { 0, NULL, 1, &emptyDNSSubtree } },
5621  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
5622    { 0, NULL, 1, &DNSSubtree } },
5623  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
5624    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
5625  { { sizeof(permittedAndExcludedWithMinConstraints),
5626      permittedAndExcludedWithMinConstraints },
5627    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
5628  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
5629      permittedAndExcludedWithMinMaxConstraints },
5630    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
5631 };
5632
5633 static void test_decodeNameConstraints(DWORD dwEncoding)
5634 {
5635     BOOL ret;
5636     DWORD i;
5637     CERT_NAME_CONSTRAINTS_INFO *constraints;
5638
5639     DNSSubtree.Base.pwszURL = (LPWSTR)url;
5640     IPAddressSubtree.Base.IPAddress.cbData = sizeof(encodedIPAddr);
5641     IPAddressSubtree.Base.IPAddress.pbData = (LPBYTE)encodedIPAddr;
5642     IPAddressWithMinSubtree.Base.IPAddress.cbData = sizeof(encodedIPAddr);
5643     IPAddressWithMinSubtree.Base.IPAddress.pbData = (LPBYTE)encodedIPAddr;
5644     IPAddressWithMinMaxSubtree.Base.IPAddress.cbData = sizeof(encodedIPAddr);
5645     IPAddressWithMinMaxSubtree.Base.IPAddress.pbData = (LPBYTE)encodedIPAddr;
5646     for (i = 0;
5647      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
5648      i++)
5649     {
5650         DWORD size;
5651
5652         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
5653          encodedNameConstraints[i].encoded.pbData,
5654          encodedNameConstraints[i].encoded.cbData,
5655          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
5656         todo_wine
5657         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
5658         if (ret)
5659         {
5660             DWORD j;
5661
5662             if (constraints->cPermittedSubtree !=
5663              encodedNameConstraints[i].constraints.cPermittedSubtree)
5664                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
5665                  encodedNameConstraints[i].constraints.cPermittedSubtree,
5666                  constraints->cPermittedSubtree);
5667             if (constraints->cPermittedSubtree ==
5668              encodedNameConstraints[i].constraints.cPermittedSubtree)
5669             {
5670                 for (j = 0; j < constraints->cPermittedSubtree; j++)
5671                 {
5672                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
5673                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
5674                 }
5675             }
5676             if (constraints->cExcludedSubtree !=
5677              encodedNameConstraints[i].constraints.cExcludedSubtree)
5678                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
5679                  encodedNameConstraints[i].constraints.cExcludedSubtree,
5680                  constraints->cExcludedSubtree);
5681             if (constraints->cExcludedSubtree ==
5682              encodedNameConstraints[i].constraints.cExcludedSubtree)
5683             {
5684                 for (j = 0; j < constraints->cExcludedSubtree; j++)
5685                 {
5686                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
5687                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
5688                 }
5689             }
5690             LocalFree(constraints);
5691         }
5692     }
5693 }
5694
5695 /* Free *pInfo with HeapFree */
5696 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
5697 {
5698     BOOL ret;
5699     DWORD size = 0;
5700     HCRYPTKEY key;
5701
5702     /* This crashes
5703     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
5704      */
5705     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
5706     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5707      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5708     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
5709      &size);
5710     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5711      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5712     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
5713      NULL, &size);
5714     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5715      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5716     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5717      0, NULL, NULL, &size);
5718     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5719      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5720     /* Test with no key */
5721     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5722      0, NULL, NULL, &size);
5723     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
5724      GetLastError());
5725     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
5726     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
5727     if (ret)
5728     {
5729         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
5730          NULL, 0, NULL, NULL, &size);
5731         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
5732         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
5733         if (*pInfo)
5734         {
5735             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
5736              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
5737             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
5738              GetLastError());
5739             if (ret)
5740             {
5741                 /* By default (we passed NULL as the OID) the OID is
5742                  * szOID_RSA_RSA.
5743                  */
5744                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
5745                  "Expected %s, got %s\n", szOID_RSA_RSA,
5746                  (*pInfo)->Algorithm.pszObjId);
5747             }
5748         }
5749     }
5750 }
5751
5752 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
5753  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
5754  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
5755  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5756  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5757  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5758  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
5759  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
5760  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5761  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5762  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5763  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5764  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
5765  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
5766  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
5767  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
5768  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
5769  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
5770  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
5771  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
5772  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
5773  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
5774  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
5775  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
5776  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
5777
5778 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
5779 {
5780     BOOL ret;
5781     HCRYPTKEY key;
5782     PCCERT_CONTEXT context;
5783
5784     /* These crash
5785     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
5786     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
5787     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
5788     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5789      NULL);
5790      */
5791     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
5792     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5793      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5794     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
5795     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5796      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5797     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
5798      &key);
5799     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5800      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5801     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5802      &key);
5803     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5804     CryptDestroyKey(key);
5805
5806     /* Test importing a public key from a certificate context */
5807     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
5808      sizeof(expiredCert));
5809     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
5810      GetLastError());
5811     if (context)
5812     {
5813         ok(!strcmp(szOID_RSA_RSA,
5814          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
5815          "Expected %s, got %s\n", szOID_RSA_RSA,
5816          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
5817         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
5818          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
5819         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5820         CryptDestroyKey(key);
5821         CertFreeCertificateContext(context);
5822     }
5823 }
5824
5825 static const char cspName[] = "WineCryptTemp";
5826
5827 static void testPortPublicKeyInfo(void)
5828 {
5829     HCRYPTPROV csp;
5830     BOOL ret;
5831     PCERT_PUBLIC_KEY_INFO info = NULL;
5832
5833     /* Just in case a previous run failed, delete this thing */
5834     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5835      CRYPT_DELETEKEYSET);
5836     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5837      CRYPT_NEWKEYSET);
5838
5839     testExportPublicKey(csp, &info);
5840     testImportPublicKey(csp, info);
5841
5842     HeapFree(GetProcessHeap(), 0, info);
5843     CryptReleaseContext(csp, 0);
5844     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5845      CRYPT_DELETEKEYSET);
5846 }
5847
5848 START_TEST(encode)
5849 {
5850     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
5851      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
5852     DWORD i;
5853
5854     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
5855     {
5856         test_encodeInt(encodings[i]);
5857         test_decodeInt(encodings[i]);
5858         test_encodeEnumerated(encodings[i]);
5859         test_decodeEnumerated(encodings[i]);
5860         test_encodeFiletime(encodings[i]);
5861         test_decodeFiletime(encodings[i]);
5862         test_encodeName(encodings[i]);
5863         test_decodeName(encodings[i]);
5864         test_encodeUnicodeName(encodings[i]);
5865         test_decodeUnicodeName(encodings[i]);
5866         test_encodeNameValue(encodings[i]);
5867         test_decodeNameValue(encodings[i]);
5868         test_encodeUnicodeNameValue(encodings[i]);
5869         test_decodeUnicodeNameValue(encodings[i]);
5870         test_encodeAltName(encodings[i]);
5871         test_decodeAltName(encodings[i]);
5872         test_encodeOctets(encodings[i]);
5873         test_decodeOctets(encodings[i]);
5874         test_encodeBits(encodings[i]);
5875         test_decodeBits(encodings[i]);
5876         test_encodeBasicConstraints(encodings[i]);
5877         test_decodeBasicConstraints(encodings[i]);
5878         test_encodeRsaPublicKey(encodings[i]);
5879         test_decodeRsaPublicKey(encodings[i]);
5880         test_encodeSequenceOfAny(encodings[i]);
5881         test_decodeSequenceOfAny(encodings[i]);
5882         test_encodeExtensions(encodings[i]);
5883         test_decodeExtensions(encodings[i]);
5884         test_encodePublicKeyInfo(encodings[i]);
5885         test_decodePublicKeyInfo(encodings[i]);
5886         test_encodeCertToBeSigned(encodings[i]);
5887         test_decodeCertToBeSigned(encodings[i]);
5888         test_encodeCert(encodings[i]);
5889         test_decodeCert(encodings[i]);
5890         test_encodeCRLDistPoints(encodings[i]);
5891         test_decodeCRLDistPoints(encodings[i]);
5892         test_encodeCRLIssuingDistPoint(encodings[i]);
5893         test_decodeCRLIssuingDistPoint(encodings[i]);
5894         test_encodeCRLToBeSigned(encodings[i]);
5895         test_decodeCRLToBeSigned(encodings[i]);
5896         test_encodeEnhancedKeyUsage(encodings[i]);
5897         test_decodeEnhancedKeyUsage(encodings[i]);
5898         test_encodeAuthorityKeyId(encodings[i]);
5899         test_decodeAuthorityKeyId(encodings[i]);
5900         test_encodeAuthorityKeyId2(encodings[i]);
5901         test_decodeAuthorityKeyId2(encodings[i]);
5902         test_encodePKCSContentInfo(encodings[i]);
5903         test_decodePKCSContentInfo(encodings[i]);
5904         test_encodePKCSAttribute(encodings[i]);
5905         test_decodePKCSAttribute(encodings[i]);
5906         test_encodePKCSAttributes(encodings[i]);
5907         test_decodePKCSAttributes(encodings[i]);
5908         test_encodePKCSSignerInfo(encodings[i]);
5909         test_decodePKCSSignerInfo(encodings[i]);
5910         test_encodeNameConstraints(encodings[i]);
5911         test_decodeNameConstraints(encodings[i]);
5912     }
5913     testPortPublicKeyInfo();
5914 }