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