mshtml: Fixed handling channels without container and necko channel.
[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 = { { 0 } };
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     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         LocalFree(buf);
4300     }
4301     /* a real CRL from verisign that has extensions */
4302     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4303      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4304      NULL, (BYTE *)&buf, &size);
4305     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4306     if (buf)
4307     {
4308         CRL_INFO *info = (CRL_INFO *)buf;
4309         CRL_ENTRY *entry;
4310
4311         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4312         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4313          info->cCRLEntry);
4314         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4315         entry = info->rgCRLEntry;
4316         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4317          info->cExtension);
4318         LocalFree(buf);
4319     }
4320     /* another real CRL from verisign that has lots of entries */
4321     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4322      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4323      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4324     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4325     if (buf)
4326     {
4327         CRL_INFO *info = (CRL_INFO *)buf;
4328
4329         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4330         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4331          info->cCRLEntry);
4332         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4333          info->cExtension);
4334         LocalFree(buf);
4335     }
4336     /* and finally, with an extension */
4337     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4338      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4339      NULL, (BYTE *)&buf, &size);
4340     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4341     if (buf)
4342     {
4343         CRL_INFO *info = (CRL_INFO *)buf;
4344         CRL_ENTRY *entry;
4345
4346         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4347         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4348          info->cCRLEntry);
4349         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4350         entry = info->rgCRLEntry;
4351         ok(entry->SerialNumber.cbData == 1,
4352          "Expected serial number size 1, got %d\n",
4353          entry->SerialNumber.cbData);
4354         ok(*entry->SerialNumber.pbData == *serialNum,
4355          "Expected serial number %d, got %d\n", *serialNum,
4356          *entry->SerialNumber.pbData);
4357         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4358          "Wrong issuer size %d\n", info->Issuer.cbData);
4359         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4360          "Unexpected issuer\n");
4361         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4362          info->cExtension);
4363         LocalFree(buf);
4364     }
4365     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4366      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4367      NULL, (BYTE *)&buf, &size);
4368     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4369     if (buf)
4370     {
4371         CRL_INFO *info = (CRL_INFO *)buf;
4372
4373         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4374          info->cExtension);
4375         LocalFree(buf);
4376     }
4377     /* And again, with an issuing dist point */
4378     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4379      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4380      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4381     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4382     if (buf)
4383     {
4384         CRL_INFO *info = (CRL_INFO *)buf;
4385
4386         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4387          info->cExtension);
4388         LocalFree(buf);
4389     }
4390 }
4391
4392 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4393  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4394 static const BYTE encodedUsage[] = {
4395  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4396  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4397  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4398
4399 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4400 {
4401     BOOL ret;
4402     BYTE *buf = NULL;
4403     DWORD size = 0;
4404     CERT_ENHKEY_USAGE usage;
4405
4406     /* Test with empty usage */
4407     usage.cUsageIdentifier = 0;
4408     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4409      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4410     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4411     if (buf)
4412     {
4413         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4414         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4415         LocalFree(buf);
4416     }
4417     /* Test with a few usages */
4418     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4419     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4420     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4421      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4422     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4423     if (buf)
4424     {
4425         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4426         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4427         LocalFree(buf);
4428     }
4429 }
4430
4431 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4432 {
4433     BOOL ret;
4434     LPBYTE buf = NULL;
4435     DWORD size = 0;
4436
4437     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4438      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4439      (BYTE *)&buf, &size);
4440     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4441     if (buf)
4442     {
4443         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4444
4445         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4446          "Wrong size %d\n", size);
4447         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4448          usage->cUsageIdentifier);
4449         LocalFree(buf);
4450     }
4451     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4452      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4453      (BYTE *)&buf, &size);
4454     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4455     if (buf)
4456     {
4457         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4458         DWORD i;
4459
4460         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4461          "Wrong size %d\n", size);
4462         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4463          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4464         for (i = 0; i < usage->cUsageIdentifier; i++)
4465             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4466              "Expected OID %s, got %s\n", keyUsages[i],
4467              usage->rgpszUsageIdentifier[i]);
4468         LocalFree(buf);
4469     }
4470 }
4471
4472 static BYTE keyId[] = { 1,2,3,4 };
4473 static const BYTE authorityKeyIdWithId[] = {
4474  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4475 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4476  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4477  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4478 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4479
4480 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4481 {
4482     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4483     BOOL ret;
4484     BYTE *buf = NULL;
4485     DWORD size = 0;
4486
4487     /* Test with empty id */
4488     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4489      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4490     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4491     if (buf)
4492     {
4493         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4494         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4495         LocalFree(buf);
4496     }
4497     /* With just a key id */
4498     info.KeyId.cbData = sizeof(keyId);
4499     info.KeyId.pbData = keyId;
4500     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4501      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4502     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4503     if (buf)
4504     {
4505         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4506         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4507         LocalFree(buf);
4508     }
4509     /* With just an issuer */
4510     info.KeyId.cbData = 0;
4511     info.CertIssuer.cbData = sizeof(encodedCommonName);
4512     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4513     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4514      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4515     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4516     if (buf)
4517     {
4518         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4519          size);
4520         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4521         LocalFree(buf);
4522     }
4523     /* With just a serial number */
4524     info.CertIssuer.cbData = 0;
4525     info.CertSerialNumber.cbData = sizeof(serialNum);
4526     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4527     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4528      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4529     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4530     if (buf)
4531     {
4532         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4533          size);
4534         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4535         LocalFree(buf);
4536     }
4537 }
4538
4539 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4540 {
4541     BOOL ret;
4542     LPBYTE buf = NULL;
4543     DWORD size = 0;
4544
4545     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4546      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4547      (BYTE *)&buf, &size);
4548     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4549     if (buf)
4550     {
4551         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4552
4553         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4554          size);
4555         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4556         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4557         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4558         LocalFree(buf);
4559     }
4560     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4561      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4562      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4563     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4564     if (buf)
4565     {
4566         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4567
4568         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4569          size);
4570         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4571         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4572          "Unexpected key id\n");
4573         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4574         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4575         LocalFree(buf);
4576     }
4577     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4578      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4579      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4580     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4581     if (buf)
4582     {
4583         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4584
4585         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4586          size);
4587         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4588         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4589          "Unexpected issuer len\n");
4590         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4591          sizeof(encodedCommonName)), "Unexpected issuer\n");
4592         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4593         LocalFree(buf);
4594     }
4595     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4596      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4597      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4598     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4599     if (buf)
4600     {
4601         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4602
4603         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4604          size);
4605         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4606         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4607         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4608          "Unexpected serial number len\n");
4609         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4610          "Unexpected serial number\n");
4611         LocalFree(buf);
4612     }
4613 }
4614
4615 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4616  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4617  0x6f,0x72,0x67 };
4618
4619 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4620 {
4621     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4622     CERT_ALT_NAME_ENTRY entry = { 0 };
4623     BOOL ret;
4624     BYTE *buf = NULL;
4625     DWORD size = 0;
4626
4627     /* Test with empty id */
4628     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4629      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4630     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4631     if (buf)
4632     {
4633         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4634         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4635         LocalFree(buf);
4636     }
4637     /* With just a key id */
4638     info.KeyId.cbData = sizeof(keyId);
4639     info.KeyId.pbData = keyId;
4640     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4641      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4642     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4643     if (buf)
4644     {
4645         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4646          size);
4647         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4648         LocalFree(buf);
4649     }
4650     /* With a bogus issuer name */
4651     info.KeyId.cbData = 0;
4652     info.AuthorityCertIssuer.cAltEntry = 1;
4653     info.AuthorityCertIssuer.rgAltEntry = &entry;
4654     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4655      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4656     ok(!ret && GetLastError() == E_INVALIDARG,
4657      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4658     /* With an issuer name */
4659     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4660     U(entry).pwszURL = (LPWSTR)url;
4661     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4662      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4663     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4664     if (buf)
4665     {
4666         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4667          size);
4668         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4669          "Unexpected value\n");
4670         LocalFree(buf);
4671     }
4672     /* With just a serial number */
4673     info.AuthorityCertIssuer.cAltEntry = 0;
4674     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4675     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4676     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4677      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4678     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4679     if (buf)
4680     {
4681         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4682          size);
4683         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4684         LocalFree(buf);
4685     }
4686 }
4687
4688 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4689 {
4690     BOOL ret;
4691     LPBYTE buf = NULL;
4692     DWORD size = 0;
4693
4694     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4695      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4696      (BYTE *)&buf, &size);
4697     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4698     if (buf)
4699     {
4700         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4701
4702         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4703          size);
4704         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4705         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4706          "Expected no issuer name entries\n");
4707         ok(info->AuthorityCertSerialNumber.cbData == 0,
4708          "Expected no serial number\n");
4709         LocalFree(buf);
4710     }
4711     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4712      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4713      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4714     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4715     if (buf)
4716     {
4717         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4718
4719         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4720          size);
4721         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4722         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4723          "Unexpected key id\n");
4724         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4725          "Expected no issuer name entries\n");
4726         ok(info->AuthorityCertSerialNumber.cbData == 0,
4727          "Expected no serial number\n");
4728         LocalFree(buf);
4729     }
4730     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4731      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4732      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4733     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4734     if (buf)
4735     {
4736         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4737
4738         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4739          size);
4740         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4741         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4742          "Expected 1 issuer entry, got %d\n",
4743          info->AuthorityCertIssuer.cAltEntry);
4744         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4745          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4746          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4747         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4748          url), "Unexpected URL\n");
4749         ok(info->AuthorityCertSerialNumber.cbData == 0,
4750          "Expected no serial number\n");
4751         LocalFree(buf);
4752     }
4753     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4754      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4755      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4756     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4757     if (buf)
4758     {
4759         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4760
4761         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4762          size);
4763         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4764         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4765          "Expected no issuer name entries\n");
4766         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4767          "Unexpected serial number len\n");
4768         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4769          sizeof(serialNum)), "Unexpected serial number\n");
4770         LocalFree(buf);
4771     }
4772 }
4773
4774 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
4775 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
4776  0x03,0,0,0,0,0,0 };
4777 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
4778  0xa0,0x01,0x01 };
4779 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
4780  0x03,0x02,0x01,0x01 };
4781 static BYTE bogusDER[] = { 1 };
4782
4783 static void test_encodePKCSContentInfo(DWORD dwEncoding)
4784 {
4785     BOOL ret;
4786     BYTE *buf = NULL;
4787     DWORD size = 0;
4788     CRYPT_CONTENT_INFO info = { 0 };
4789     char oid1[] = "1.2.3";
4790
4791     SetLastError(0xdeadbeef);
4792     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
4793      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4794     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4795      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4796     SetLastError(0xdeadbeef);
4797     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4798      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4799     ok(!ret && GetLastError() == E_INVALIDARG,
4800      "Expected E_INVALIDARG, got %x\n", GetLastError());
4801     info.pszObjId = oid1;
4802     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4803      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4804     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4805     if (buf)
4806     {
4807         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
4808         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
4809         LocalFree(buf);
4810     }
4811     info.Content.pbData = bogusDER;
4812     info.Content.cbData = sizeof(bogusDER);
4813     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4814      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4815     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
4816     if (buf)
4817     {
4818         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
4819         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
4820         LocalFree(buf);
4821     }
4822     info.Content.pbData = (BYTE *)ints[0].encoded;
4823     info.Content.cbData = ints[0].encoded[1] + 2;
4824     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4825      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4826     if (buf)
4827     {
4828         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
4829         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
4830         LocalFree(buf);
4831     }
4832 }
4833
4834 static const BYTE indefiniteSignedPKCSContent[] = {
4835 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
4836 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
4837 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
4838 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
4839 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
4840 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
4841 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
4842 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4843 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
4844 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
4845 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
4846 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
4847 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
4848 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
4849 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
4850 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
4851 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
4852 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
4853 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
4854 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
4855 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
4856 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
4857 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
4858 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
4859 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
4860 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
4861 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
4862 0x00,0x00,0x00,0x00,0x00,0x00 };
4863
4864 static void test_decodePKCSContentInfo(DWORD dwEncoding)
4865 {
4866     BOOL ret;
4867     LPBYTE buf = NULL;
4868     DWORD size = 0;
4869     CRYPT_CONTENT_INFO *info;
4870
4871     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4872      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
4873      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4874     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4875     if (buf)
4876     {
4877         info = (CRYPT_CONTENT_INFO *)buf;
4878
4879         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4880          info->pszObjId);
4881         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
4882          info->Content.cbData);
4883         LocalFree(buf);
4884     }
4885     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4886      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
4887      0, NULL, NULL, &size);
4888     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4889     SetLastError(0xdeadbeef);
4890     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4891      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
4892      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4893     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4894      * I doubt an app depends on that.
4895      */
4896     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4897      GetLastError() == CRYPT_E_ASN1_CORRUPT),
4898      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4899      GetLastError());
4900     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4901      intPKCSContentInfo, sizeof(intPKCSContentInfo),
4902      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4903     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4904     if (buf)
4905     {
4906         info = (CRYPT_CONTENT_INFO *)buf;
4907
4908         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4909          info->pszObjId);
4910         ok(info->Content.cbData == ints[0].encoded[1] + 2,
4911          "Unexpected size %d\n", info->Content.cbData);
4912         ok(!memcmp(info->Content.pbData, ints[0].encoded,
4913          info->Content.cbData), "Unexpected value\n");
4914         LocalFree(buf);
4915     }
4916     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4917      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
4918      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4919     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4920     if (buf)
4921     {
4922         info = (CRYPT_CONTENT_INFO *)buf;
4923
4924         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
4925          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
4926         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
4927          info->Content.cbData);
4928         LocalFree(buf);
4929     }
4930 }
4931
4932 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
4933  0x00 };
4934 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
4935  0x01 };
4936 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
4937  0x02,0x01,0x01 };
4938
4939 static void test_encodePKCSAttribute(DWORD dwEncoding)
4940 {
4941     CRYPT_ATTRIBUTE attr = { 0 };
4942     BOOL ret;
4943     LPBYTE buf = NULL;
4944     DWORD size = 0;
4945     CRYPT_ATTR_BLOB blob;
4946     char oid[] = "1.2.3";
4947
4948     SetLastError(0xdeadbeef);
4949     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
4950      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4951     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4952      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4953     SetLastError(0xdeadbeef);
4954     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4955      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4956     ok(!ret && GetLastError() == E_INVALIDARG,
4957      "Expected E_INVALIDARG, got %x\n", GetLastError());
4958     attr.pszObjId = oid;
4959     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4960      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4961     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4962     if (buf)
4963     {
4964         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
4965         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
4966         LocalFree(buf);
4967     }
4968     blob.cbData = sizeof(bogusDER);
4969     blob.pbData = bogusDER;
4970     attr.cValue = 1;
4971     attr.rgValue = &blob;
4972     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4973      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4974     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4975     if (buf)
4976     {
4977         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
4978         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
4979         LocalFree(buf);
4980     }
4981     blob.pbData = (BYTE *)ints[0].encoded;
4982     blob.cbData = ints[0].encoded[1] + 2;
4983     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4984      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4985     if (buf)
4986     {
4987         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
4988         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
4989         LocalFree(buf);
4990     }
4991 }
4992
4993 static void test_decodePKCSAttribute(DWORD dwEncoding)
4994 {
4995     BOOL ret;
4996     LPBYTE buf = NULL;
4997     DWORD size = 0;
4998     CRYPT_ATTRIBUTE *attr;
4999
5000     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5001      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5002      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5003     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5004     if (buf)
5005     {
5006         attr = (CRYPT_ATTRIBUTE *)buf;
5007
5008         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5009          attr->pszObjId);
5010         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5011         LocalFree(buf);
5012     }
5013     SetLastError(0xdeadbeef);
5014     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5015      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5016      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5017     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5018      * I doubt an app depends on that.
5019      */
5020     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5021      GetLastError() == CRYPT_E_ASN1_CORRUPT),
5022      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5023      GetLastError());
5024     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5025      intPKCSAttr, sizeof(intPKCSAttr),
5026      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5027     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5028     if (buf)
5029     {
5030         attr = (CRYPT_ATTRIBUTE *)buf;
5031
5032         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5033          attr->pszObjId);
5034         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5035         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5036          "Unexpected size %d\n", attr->rgValue[0].cbData);
5037         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5038          attr->rgValue[0].cbData), "Unexpected value\n");
5039         LocalFree(buf);
5040     }
5041 }
5042
5043 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5044 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5045  0x2a,0x03,0x31,0x00 };
5046 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5047  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5048
5049 static void test_encodePKCSAttributes(DWORD dwEncoding)
5050 {
5051     CRYPT_ATTRIBUTES attributes = { 0 };
5052     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5053     CRYPT_ATTR_BLOB blob;
5054     BOOL ret;
5055     LPBYTE buf = NULL;
5056     DWORD size = 0;
5057     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5058
5059     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5060      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5061     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5062     if (buf)
5063     {
5064         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5065         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5066         LocalFree(buf);
5067     }
5068     attributes.cAttr = 1;
5069     attributes.rgAttr = attr;
5070     SetLastError(0xdeadbeef);
5071     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5072      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5073     ok(!ret && GetLastError() == E_INVALIDARG,
5074      "Expected E_INVALIDARG, got %x\n", GetLastError());
5075     attr[0].pszObjId = oid1;
5076     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5077      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5078     if (buf)
5079     {
5080         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5081         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5082         LocalFree(buf);
5083     }
5084     attr[1].pszObjId = oid2;
5085     attr[1].cValue = 1;
5086     attr[1].rgValue = &blob;
5087     blob.pbData = (BYTE *)ints[0].encoded;
5088     blob.cbData = ints[0].encoded[1] + 2;
5089     attributes.cAttr = 2;
5090     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5091      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5092     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5093     if (buf)
5094     {
5095         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5096         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5097         LocalFree(buf);
5098     }
5099 }
5100
5101 static void test_decodePKCSAttributes(DWORD dwEncoding)
5102 {
5103     BOOL ret;
5104     LPBYTE buf = NULL;
5105     DWORD size = 0;
5106     CRYPT_ATTRIBUTES *attributes;
5107
5108     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5109      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5110      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5111     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5112     if (buf)
5113     {
5114         attributes = (CRYPT_ATTRIBUTES *)buf;
5115         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5116          attributes->cAttr);
5117         LocalFree(buf);
5118     }
5119     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5120      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5121      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5122     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5123     if (buf)
5124     {
5125         attributes = (CRYPT_ATTRIBUTES *)buf;
5126         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5127          attributes->cAttr);
5128         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5129          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5130         ok(attributes->rgAttr[0].cValue == 0,
5131          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5132         LocalFree(buf);
5133     }
5134     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5135      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5136      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5137     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5138     if (buf)
5139     {
5140         attributes = (CRYPT_ATTRIBUTES *)buf;
5141         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5142          attributes->cAttr);
5143         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5144          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5145         ok(attributes->rgAttr[0].cValue == 0,
5146          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5147         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5148          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5149         ok(attributes->rgAttr[1].cValue == 1,
5150          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5151         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5152          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5153         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5154          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5155         LocalFree(buf);
5156     }
5157 }
5158
5159 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
5160  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5161  0x67 };
5162 static const BYTE minimalPKCSSigner[] = {
5163  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5164  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5165  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
5166 static const BYTE PKCSSignerWithSerial[] = {
5167  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5168  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5169  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5170  0x00 };
5171 static const BYTE PKCSSignerWithHashAlgo[] = {
5172  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5173  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5174  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5175  0x00,0x04,0x00 };
5176 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
5177  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5178  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5179  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
5180  0x06,0x05,0x00,0x04,0x00 };
5181 static const BYTE PKCSSignerWithHash[] = {
5182  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5183  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5184  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
5185  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
5186  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
5187 static const BYTE PKCSSignerWithAuthAttr[] = {
5188 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5189 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5190 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
5191 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
5192 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
5193 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
5194 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
5195
5196 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
5197 {
5198     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
5199     BOOL ret;
5200     LPBYTE buf = NULL;
5201     DWORD size = 0;
5202     CMSG_SIGNER_INFO info = { 0 };
5203     char oid_common_name[] = szOID_COMMON_NAME;
5204     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
5205      (LPBYTE)encodedCommonName };
5206     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
5207
5208     SetLastError(0xdeadbeef);
5209     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5210      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5211     ok(!ret && GetLastError() == E_INVALIDARG,
5212      "Expected E_INVALIDARG, got %08x\n", GetLastError());
5213     /* To be encoded, a signer must have an issuer at least, and the encoding
5214      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
5215      * see decoding tests.)
5216      */
5217     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
5218     info.Issuer.pbData = encodedCommonNameNoNull;
5219     SetLastError(0xdeadbeef);
5220     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5221      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5222     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5223         ok(!ret && GetLastError() == E_INVALIDARG,
5224          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5225     else
5226     {
5227         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5228         if (buf)
5229         {
5230             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
5231             if (size == sizeof(minimalPKCSSigner))
5232                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
5233             else
5234                 ok(0, "Unexpected value\n");
5235             LocalFree(buf);
5236         }
5237     }
5238     info.SerialNumber.cbData = sizeof(serialNum);
5239     info.SerialNumber.pbData = (BYTE *)serialNum;
5240     SetLastError(0xdeadbeef);
5241     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5242      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5243     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5244         ok(!ret && GetLastError() == E_INVALIDARG,
5245          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5246     else
5247     {
5248         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5249         if (buf)
5250         {
5251             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
5252              size);
5253             if (size == sizeof(PKCSSignerWithSerial))
5254                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
5255                  "Unexpected value\n");
5256             else
5257                 ok(0, "Unexpected value\n");
5258             LocalFree(buf);
5259         }
5260     }
5261     info.HashAlgorithm.pszObjId = oid1;
5262     SetLastError(0xdeadbeef);
5263     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5264      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5265     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5266         ok(!ret && GetLastError() == E_INVALIDARG,
5267          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5268     else
5269     {
5270         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5271         if (buf)
5272         {
5273             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
5274              size);
5275             if (size == sizeof(PKCSSignerWithHashAlgo))
5276                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
5277                  "Unexpected value\n");
5278             else
5279                 ok(0, "Unexpected value\n");
5280             LocalFree(buf);
5281         }
5282     }
5283     info.HashEncryptionAlgorithm.pszObjId = oid2;
5284     SetLastError(0xdeadbeef);
5285     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5286      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5287     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5288         ok(!ret && GetLastError() == E_INVALIDARG,
5289          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5290     else
5291     {
5292         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5293         if (buf)
5294         {
5295             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
5296              "Unexpected size %d\n", size);
5297             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
5298                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
5299                  "Unexpected value\n");
5300             else
5301                 ok(0, "Unexpected value\n");
5302             LocalFree(buf);
5303         }
5304     }
5305     info.EncryptedHash.cbData = sizeof(hash);
5306     info.EncryptedHash.pbData = (BYTE *)hash;
5307     SetLastError(0xdeadbeef);
5308     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5309      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5310     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5311         ok(!ret && GetLastError() == E_INVALIDARG,
5312          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5313     else
5314     {
5315         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5316         if (buf)
5317         {
5318             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
5319              size);
5320             if (size == sizeof(PKCSSignerWithHash))
5321                 ok(!memcmp(buf, PKCSSignerWithHash, size),
5322                  "Unexpected value\n");
5323             else
5324                 ok(0, "Unexpected value\n");
5325             LocalFree(buf);
5326         }
5327     }
5328     info.AuthAttrs.cAttr = 1;
5329     info.AuthAttrs.rgAttr = &attr;
5330     SetLastError(0xdeadbeef);
5331     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5332      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5333     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5334         ok(!ret && GetLastError() == E_INVALIDARG,
5335          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5336     else
5337     {
5338         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5339         if (buf)
5340         {
5341             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
5342              size);
5343             if (size == sizeof(PKCSSignerWithAuthAttr))
5344                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
5345                  "Unexpected value\n");
5346             else
5347                 ok(0, "Unexpected value\n");
5348             LocalFree(buf);
5349         }
5350     }
5351 }
5352
5353 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
5354 {
5355     BOOL ret;
5356     LPBYTE buf = NULL;
5357     DWORD size = 0;
5358     CMSG_SIGNER_INFO *info;
5359
5360     /* A PKCS signer can't be decoded without a serial number. */
5361     SetLastError(0xdeadbeef);
5362     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5363      minimalPKCSSigner, sizeof(minimalPKCSSigner),
5364      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5365     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
5366      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
5367     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5368      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
5369      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5370     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5371     if (buf)
5372     {
5373         info = (CMSG_SIGNER_INFO *)buf;
5374         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5375          info->dwVersion);
5376         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5377          "Unexpected size %d\n", info->Issuer.cbData);
5378         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5379          info->Issuer.cbData), "Unexpected value\n");
5380         ok(info->SerialNumber.cbData == sizeof(serialNum),
5381          "Unexpected size %d\n", info->SerialNumber.cbData);
5382         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5383          "Unexpected value\n");
5384         LocalFree(buf);
5385     }
5386     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5387      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
5388      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5389     if (buf)
5390     {
5391         info = (CMSG_SIGNER_INFO *)buf;
5392         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5393          info->dwVersion);
5394         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5395          "Unexpected size %d\n", info->Issuer.cbData);
5396         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5397          info->Issuer.cbData), "Unexpected value\n");
5398         ok(info->SerialNumber.cbData == sizeof(serialNum),
5399          "Unexpected size %d\n", info->SerialNumber.cbData);
5400         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5401          "Unexpected value\n");
5402         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5403          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5404         LocalFree(buf);
5405     }
5406     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5407      PKCSSignerWithHashAndEncryptionAlgo,
5408      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
5409      NULL, (BYTE *)&buf, &size);
5410     if (buf)
5411     {
5412         info = (CMSG_SIGNER_INFO *)buf;
5413         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5414          info->dwVersion);
5415         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5416          "Unexpected size %d\n", info->Issuer.cbData);
5417         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5418          info->Issuer.cbData), "Unexpected value\n");
5419         ok(info->SerialNumber.cbData == sizeof(serialNum),
5420          "Unexpected size %d\n", info->SerialNumber.cbData);
5421         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5422          "Unexpected value\n");
5423         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5424          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5425         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5426          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5427         LocalFree(buf);
5428     }
5429     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5430      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
5431      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5432     if (buf)
5433     {
5434         info = (CMSG_SIGNER_INFO *)buf;
5435         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5436          info->dwVersion);
5437         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5438          "Unexpected size %d\n", info->Issuer.cbData);
5439         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5440          info->Issuer.cbData), "Unexpected value\n");
5441         ok(info->SerialNumber.cbData == sizeof(serialNum),
5442          "Unexpected size %d\n", info->SerialNumber.cbData);
5443         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5444          "Unexpected value\n");
5445         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5446          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5447         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5448          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5449         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
5450          info->EncryptedHash.cbData);
5451         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
5452          "Unexpected value\n");
5453         LocalFree(buf);
5454     }
5455     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5456      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
5457      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5458     if (buf)
5459     {
5460         info = (CMSG_SIGNER_INFO *)buf;
5461         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
5462          info->AuthAttrs.cAttr);
5463         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
5464          "Expected %s, got %s\n", szOID_COMMON_NAME,
5465          info->AuthAttrs.rgAttr[0].pszObjId);
5466         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
5467          info->AuthAttrs.rgAttr[0].cValue);
5468         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
5469          sizeof(encodedCommonName), "Unexpected size %d\n",
5470          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
5471         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
5472          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
5473         LocalFree(buf);
5474     }
5475 }
5476
5477 static BYTE emptyDNSPermittedConstraints[] = {
5478 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
5479 static BYTE emptyDNSExcludedConstraints[] = {
5480 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
5481 static BYTE DNSExcludedConstraints[] = {
5482 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
5483 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5484 static BYTE permittedAndExcludedConstraints[] = {
5485 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
5486 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
5487 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5488 static BYTE permittedAndExcludedWithMinConstraints[] = {
5489 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
5490 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
5491 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5492 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
5493 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
5494 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
5495 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5496
5497 static void test_encodeNameConstraints(DWORD dwEncoding)
5498 {
5499     BOOL ret;
5500     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
5501     CERT_GENERAL_SUBTREE permitted = { { 0 } };
5502     CERT_GENERAL_SUBTREE excluded = { { 0 } };
5503     LPBYTE buf;
5504     DWORD size;
5505
5506     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5507      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5508     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5509     if (ret)
5510     {
5511         ok(size == sizeof(emptySequence), "Unexpected size\n");
5512         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
5513         LocalFree(buf);
5514     }
5515     constraints.cPermittedSubtree = 1;
5516     constraints.rgPermittedSubtree = &permitted;
5517     SetLastError(0xdeadbeef);
5518     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5519      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5520     ok(!ret && GetLastError() == E_INVALIDARG,
5521      "Expected E_INVALIDARG, got %08x\n", GetLastError());
5522     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
5523     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5524      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5525     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5526     if (ret)
5527     {
5528         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
5529         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
5530          "Unexpected value\n");
5531         LocalFree(buf);
5532     }
5533     constraints.cPermittedSubtree = 0;
5534     constraints.cExcludedSubtree = 1;
5535     constraints.rgExcludedSubtree = &excluded;
5536     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
5537     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5538      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5539     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5540     if (ret)
5541     {
5542         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
5543         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
5544          "Unexpected value\n");
5545         LocalFree(buf);
5546     }
5547     U(excluded.Base).pwszURL = (LPWSTR)url;
5548     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5549      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5550     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5551     if (ret)
5552     {
5553         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
5554         ok(!memcmp(buf, DNSExcludedConstraints, size),
5555          "Unexpected value\n");
5556         LocalFree(buf);
5557     }
5558     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
5559     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
5560     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
5561     constraints.cPermittedSubtree = 1;
5562     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5563      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5564     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5565     if (ret)
5566     {
5567         ok(size == sizeof(permittedAndExcludedConstraints),
5568          "Unexpected size\n");
5569         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
5570          "Unexpected value\n");
5571         LocalFree(buf);
5572     }
5573     permitted.dwMinimum = 5;
5574     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5575      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5576     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5577     if (ret)
5578     {
5579         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
5580          "Unexpected size\n");
5581         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
5582          "Unexpected value\n");
5583         LocalFree(buf);
5584     }
5585     permitted.fMaximum = TRUE;
5586     permitted.dwMaximum = 3;
5587     SetLastError(0xdeadbeef);
5588     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5589      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5590     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5591     if (ret)
5592     {
5593         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
5594          "Unexpected size\n");
5595         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
5596          "Unexpected value\n");
5597         LocalFree(buf);
5598     }
5599 }
5600
5601 struct EncodedNameConstraints
5602 {
5603     CRYPT_DATA_BLOB            encoded;
5604     CERT_NAME_CONSTRAINTS_INFO constraints;
5605 };
5606
5607 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
5608  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
5609 static CERT_GENERAL_SUBTREE DNSSubtree = {
5610  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
5611 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
5612  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
5613 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
5614  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
5615 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
5616  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
5617
5618 struct EncodedNameConstraints encodedNameConstraints[] = {
5619  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
5620  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
5621    { 1, &emptyDNSSubtree, 0, NULL } },
5622  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
5623    { 0, NULL, 1, &emptyDNSSubtree } },
5624  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
5625    { 0, NULL, 1, &DNSSubtree } },
5626  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
5627    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
5628  { { sizeof(permittedAndExcludedWithMinConstraints),
5629      permittedAndExcludedWithMinConstraints },
5630    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
5631  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
5632      permittedAndExcludedWithMinMaxConstraints },
5633    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
5634 };
5635
5636 static void test_decodeNameConstraints(DWORD dwEncoding)
5637 {
5638     BOOL ret;
5639     DWORD i;
5640     CERT_NAME_CONSTRAINTS_INFO *constraints;
5641
5642     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
5643     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
5644     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
5645     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
5646     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
5647     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
5648     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
5649     for (i = 0;
5650      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
5651      i++)
5652     {
5653         DWORD size;
5654
5655         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
5656          encodedNameConstraints[i].encoded.pbData,
5657          encodedNameConstraints[i].encoded.cbData,
5658          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
5659         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
5660         if (ret)
5661         {
5662             DWORD j;
5663
5664             if (constraints->cPermittedSubtree !=
5665              encodedNameConstraints[i].constraints.cPermittedSubtree)
5666                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
5667                  encodedNameConstraints[i].constraints.cPermittedSubtree,
5668                  constraints->cPermittedSubtree);
5669             if (constraints->cPermittedSubtree ==
5670              encodedNameConstraints[i].constraints.cPermittedSubtree)
5671             {
5672                 for (j = 0; j < constraints->cPermittedSubtree; j++)
5673                 {
5674                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
5675                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
5676                 }
5677             }
5678             if (constraints->cExcludedSubtree !=
5679              encodedNameConstraints[i].constraints.cExcludedSubtree)
5680                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
5681                  encodedNameConstraints[i].constraints.cExcludedSubtree,
5682                  constraints->cExcludedSubtree);
5683             if (constraints->cExcludedSubtree ==
5684              encodedNameConstraints[i].constraints.cExcludedSubtree)
5685             {
5686                 for (j = 0; j < constraints->cExcludedSubtree; j++)
5687                 {
5688                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
5689                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
5690                 }
5691             }
5692             LocalFree(constraints);
5693         }
5694     }
5695 }
5696
5697 /* Free *pInfo with HeapFree */
5698 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
5699 {
5700     BOOL ret;
5701     DWORD size = 0;
5702     HCRYPTKEY key;
5703
5704     /* This crashes
5705     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
5706      */
5707     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
5708     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5709      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5710     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
5711      &size);
5712     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5713      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5714     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
5715      NULL, &size);
5716     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5717      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5718     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5719      0, NULL, NULL, &size);
5720     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5721      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5722     /* Test with no key */
5723     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5724      0, NULL, NULL, &size);
5725     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
5726      GetLastError());
5727     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
5728     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
5729     if (ret)
5730     {
5731         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
5732          NULL, 0, NULL, NULL, &size);
5733         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
5734         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
5735         if (*pInfo)
5736         {
5737             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
5738              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
5739             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
5740              GetLastError());
5741             if (ret)
5742             {
5743                 /* By default (we passed NULL as the OID) the OID is
5744                  * szOID_RSA_RSA.
5745                  */
5746                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
5747                  "Expected %s, got %s\n", szOID_RSA_RSA,
5748                  (*pInfo)->Algorithm.pszObjId);
5749             }
5750         }
5751     }
5752     CryptDestroyKey(key);
5753 }
5754
5755 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
5756  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
5757  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
5758  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5759  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5760  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5761  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
5762  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
5763  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5764  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5765  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5766  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5767  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
5768  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
5769  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
5770  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
5771  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
5772  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
5773  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
5774  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
5775  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
5776  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
5777  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
5778  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
5779  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
5780
5781 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
5782 {
5783     BOOL ret;
5784     HCRYPTKEY key;
5785     PCCERT_CONTEXT context;
5786
5787     /* These crash
5788     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
5789     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
5790     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
5791     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5792      NULL);
5793      */
5794     ret = CryptImportPublicKeyInfoEx(0, 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(csp, 0, info, 0, 0, NULL, &key);
5798     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5799      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5800     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
5801      &key);
5802     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5803      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5804     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5805      &key);
5806     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5807     CryptDestroyKey(key);
5808
5809     /* Test importing a public key from a certificate context */
5810     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
5811      sizeof(expiredCert));
5812     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
5813      GetLastError());
5814     if (context)
5815     {
5816         ok(!strcmp(szOID_RSA_RSA,
5817          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
5818          "Expected %s, got %s\n", szOID_RSA_RSA,
5819          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
5820         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
5821          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
5822         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5823         CryptDestroyKey(key);
5824         CertFreeCertificateContext(context);
5825     }
5826 }
5827
5828 static const char cspName[] = "WineCryptTemp";
5829
5830 static void testPortPublicKeyInfo(void)
5831 {
5832     HCRYPTPROV csp;
5833     BOOL ret;
5834     PCERT_PUBLIC_KEY_INFO info = NULL;
5835
5836     /* Just in case a previous run failed, delete this thing */
5837     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5838      CRYPT_DELETEKEYSET);
5839     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5840      CRYPT_NEWKEYSET);
5841
5842     testExportPublicKey(csp, &info);
5843     testImportPublicKey(csp, info);
5844
5845     HeapFree(GetProcessHeap(), 0, info);
5846     CryptReleaseContext(csp, 0);
5847     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5848      CRYPT_DELETEKEYSET);
5849 }
5850
5851 START_TEST(encode)
5852 {
5853     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
5854      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
5855     DWORD i;
5856
5857     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
5858     {
5859         test_encodeInt(encodings[i]);
5860         test_decodeInt(encodings[i]);
5861         test_encodeEnumerated(encodings[i]);
5862         test_decodeEnumerated(encodings[i]);
5863         test_encodeFiletime(encodings[i]);
5864         test_decodeFiletime(encodings[i]);
5865         test_encodeName(encodings[i]);
5866         test_decodeName(encodings[i]);
5867         test_encodeUnicodeName(encodings[i]);
5868         test_decodeUnicodeName(encodings[i]);
5869         test_encodeNameValue(encodings[i]);
5870         test_decodeNameValue(encodings[i]);
5871         test_encodeUnicodeNameValue(encodings[i]);
5872         test_decodeUnicodeNameValue(encodings[i]);
5873         test_encodeAltName(encodings[i]);
5874         test_decodeAltName(encodings[i]);
5875         test_encodeOctets(encodings[i]);
5876         test_decodeOctets(encodings[i]);
5877         test_encodeBits(encodings[i]);
5878         test_decodeBits(encodings[i]);
5879         test_encodeBasicConstraints(encodings[i]);
5880         test_decodeBasicConstraints(encodings[i]);
5881         test_encodeRsaPublicKey(encodings[i]);
5882         test_decodeRsaPublicKey(encodings[i]);
5883         test_encodeSequenceOfAny(encodings[i]);
5884         test_decodeSequenceOfAny(encodings[i]);
5885         test_encodeExtensions(encodings[i]);
5886         test_decodeExtensions(encodings[i]);
5887         test_encodePublicKeyInfo(encodings[i]);
5888         test_decodePublicKeyInfo(encodings[i]);
5889         test_encodeCertToBeSigned(encodings[i]);
5890         test_decodeCertToBeSigned(encodings[i]);
5891         test_encodeCert(encodings[i]);
5892         test_decodeCert(encodings[i]);
5893         test_encodeCRLDistPoints(encodings[i]);
5894         test_decodeCRLDistPoints(encodings[i]);
5895         test_encodeCRLIssuingDistPoint(encodings[i]);
5896         test_decodeCRLIssuingDistPoint(encodings[i]);
5897         test_encodeCRLToBeSigned(encodings[i]);
5898         test_decodeCRLToBeSigned(encodings[i]);
5899         test_encodeEnhancedKeyUsage(encodings[i]);
5900         test_decodeEnhancedKeyUsage(encodings[i]);
5901         test_encodeAuthorityKeyId(encodings[i]);
5902         test_decodeAuthorityKeyId(encodings[i]);
5903         test_encodeAuthorityKeyId2(encodings[i]);
5904         test_decodeAuthorityKeyId2(encodings[i]);
5905         test_encodePKCSContentInfo(encodings[i]);
5906         test_decodePKCSContentInfo(encodings[i]);
5907         test_encodePKCSAttribute(encodings[i]);
5908         test_decodePKCSAttribute(encodings[i]);
5909         test_encodePKCSAttributes(encodings[i]);
5910         test_decodePKCSAttributes(encodings[i]);
5911         test_encodePKCSSignerInfo(encodings[i]);
5912         test_decodePKCSSignerInfo(encodings[i]);
5913         test_encodeNameConstraints(encodings[i]);
5914         test_decodeNameConstraints(encodings[i]);
5915     }
5916     testPortPublicKeyInfo();
5917 }