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 #include <snmp.h>
27 
28 #include "wine/test.h"
29 
30 
31 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
32 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
33 
34 struct encodedInt
35 {
36     int val;
37     const BYTE *encoded;
38 };
39 
40 static const BYTE bin1[] = {0x02,0x01,0x01};
41 static const BYTE bin2[] = {0x02,0x01,0x7f};
42 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
43 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
44 static const BYTE bin5[] = {0x02,0x01,0x80};
45 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
46 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
47 
48 static const struct encodedInt ints[] = {
49  { 1,          bin1 },
50  { 127,        bin2 },
51  { 128,        bin3 },
52  { 256,        bin4 },
53  { -128,       bin5 },
54  { -129,       bin6 },
55  { 0xbaddf00d, bin7 },
56 };
57 
58 struct encodedBigInt
59 {
60     const BYTE *val;
61     const BYTE *encoded;
62     const BYTE *decoded;
63 };
64 
65 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
66 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
67 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
68 
69 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
70 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
71 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
72 
73 static const struct encodedBigInt bigInts[] = {
74  { bin8, bin9, bin10 },
75  { bin11, bin12, bin13 },
76 };
77 
78 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
79 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
80 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
81 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
82 
83 /* Decoded is the same as original, so don't bother storing a separate copy */
84 static const struct encodedBigInt bigUInts[] = {
85  { bin14, bin15, NULL },
86  { bin16, bin17, NULL },
87 };
88 
89 static void test_encodeInt(DWORD dwEncoding)
90 {
91     DWORD bufSize = 0;
92     int i;
93     BOOL ret;
94     CRYPT_INTEGER_BLOB blob;
95     BYTE *buf = NULL;
96 
97     /* CryptEncodeObjectEx with NULL bufSize crashes..
98     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
99      NULL);
100      */
101     /* check bogus encoding */
102     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
103      &bufSize);
104     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
105      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
106     if (0)
107     {
108         /* check with NULL integer buffer.  Windows XP incorrectly returns an
109          * NTSTATUS (crashes on win9x).
110          */
111         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
112          &bufSize);
113         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
114          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
115     }
116     for (i = 0; i < ARRAY_SIZE(ints); i++)
117     {
118         /* encode as normal integer */
119         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
120          NULL, NULL, &bufSize);
121         ok(ret, "Expected success, got %d\n", GetLastError());
122         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
123          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
124         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
125         if (ret)
126         {
127             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
128              buf[0]);
129             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
130              buf[1], ints[i].encoded[1]);
131             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
132              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
133             LocalFree(buf);
134         }
135         /* encode as multibyte integer */
136         blob.cbData = sizeof(ints[i].val);
137         blob.pbData = (BYTE *)&ints[i].val;
138         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
139          0, NULL, NULL, &bufSize);
140         ok(ret, "Expected success, got %d\n", GetLastError());
141         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
142          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
143         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
144         if (ret)
145         {
146             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
147              buf[0]);
148             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
149              buf[1], ints[i].encoded[1]);
150             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
151              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
152             LocalFree(buf);
153         }
154     }
155     /* encode a couple bigger ints, just to show it's little-endian and leading
156      * sign bytes are dropped
157      */
158     for (i = 0; i < ARRAY_SIZE(bigInts); i++)
159     {
160         blob.cbData = strlen((const char*)bigInts[i].val);
161         blob.pbData = (BYTE *)bigInts[i].val;
162         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
163          0, NULL, NULL, &bufSize);
164         ok(ret, "Expected success, got %d\n", GetLastError());
165         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
166          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
167         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
168         if (ret)
169         {
170             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
171              buf[0]);
172             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
173              buf[1], bigInts[i].encoded[1]);
174             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
175              bigInts[i].encoded[1] + 1),
176              "Encoded value didn't match expected\n");
177             LocalFree(buf);
178         }
179     }
180     /* and, encode some uints */
181     for (i = 0; i < ARRAY_SIZE(bigUInts); i++)
182     {
183         blob.cbData = strlen((const char*)bigUInts[i].val);
184         blob.pbData = (BYTE*)bigUInts[i].val;
185         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
186          0, NULL, NULL, &bufSize);
187         ok(ret, "Expected success, got %d\n", GetLastError());
188         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
189          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
190         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
191         if (ret)
192         {
193             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
194              buf[0]);
195             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
196              buf[1], bigUInts[i].encoded[1]);
197             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
198              bigUInts[i].encoded[1] + 1),
199              "Encoded value didn't match expected\n");
200             LocalFree(buf);
201         }
202     }
203 }
204 
205 static void test_decodeInt(DWORD dwEncoding)
206 {
207     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
208     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
209     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
210     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
211     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
212     BYTE *buf = NULL;
213     DWORD bufSize = 0;
214     int i;
215     BOOL ret;
216 
217     /* CryptDecodeObjectEx with NULL bufSize crashes..
218     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
219      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
220      */
221     /* check bogus encoding */
222     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
223      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
224     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
225      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
226     /* check with NULL integer buffer */
227     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
228      &bufSize);
229     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
230      GetLastError() == OSS_BAD_ARG /* Win9x */),
231      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
232     /* check with a valid, but too large, integer */
233     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
234      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
235     ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
236      broken(ret) /* Win9x */,
237      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
238     /* check with a DER-encoded string */
239     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
240      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
241     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
242      GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
243      "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
244      GetLastError());
245     for (i = 0; i < ARRAY_SIZE(ints); i++)
246     {
247         /* When the output buffer is NULL, this always succeeds */
248         SetLastError(0xdeadbeef);
249         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
250          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
251          &bufSize);
252         ok(ret && GetLastError() == NOERROR,
253          "Expected success and NOERROR, got %d\n", GetLastError());
254         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
255          ints[i].encoded, ints[i].encoded[1] + 2,
256          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
257         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
258         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
259         ok(buf != NULL, "Expected allocated buffer\n");
260         if (ret)
261         {
262             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
263              ints[i].val, *(int *)buf);
264             LocalFree(buf);
265         }
266     }
267     for (i = 0; i < ARRAY_SIZE(bigInts); i++)
268     {
269         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
270          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
271          &bufSize);
272         ok(ret && GetLastError() == NOERROR,
273          "Expected success and NOERROR, got %d\n", GetLastError());
274         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
275          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
276          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
277         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
278         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
279         ok(buf != NULL, "Expected allocated buffer\n");
280         if (ret)
281         {
282             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
283 
284             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
285              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
286              blob->cbData);
287             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
288              "Unexpected value\n");
289             LocalFree(buf);
290         }
291     }
292     for (i = 0; i < ARRAY_SIZE(bigUInts); i++)
293     {
294         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
295          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
296          &bufSize);
297         ok(ret && GetLastError() == NOERROR,
298          "Expected success and NOERROR, got %d\n", GetLastError());
299         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
300          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
301          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
302         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
303         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
304         ok(buf != NULL, "Expected allocated buffer\n");
305         if (ret)
306         {
307             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
308 
309             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
310              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
311              blob->cbData);
312             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
313              "Unexpected value\n");
314             LocalFree(buf);
315         }
316     }
317     /* Decode the value 1 with long-form length */
318     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
319      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
320     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
321     if (ret)
322     {
323         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
324         LocalFree(buf);
325     }
326     /* check with extra bytes at the end */
327     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
328      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
329     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
330     if (ret)
331     {
332         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
333         LocalFree(buf);
334     }
335     /* Try to decode some bogus large items */
336     /* The buffer size is smaller than the encoded length, so this should fail
337      * with CRYPT_E_ASN1_EOD if it's being decoded.
338      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
339      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
340      * So this test unfortunately isn't useful.
341     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
342      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
343     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
344      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
345      */
346     /* This will try to decode the buffer and overflow it, check that it's
347      * caught.
348      */
349     if (0)
350     {
351     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
352     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
353      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
354     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
355      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
356     }
357 }
358 
359 static const BYTE bin18[] = {0x0a,0x01,0x01};
360 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
361 
362 /* These are always encoded unsigned, and aren't constrained to be any
363  * particular value
364  */
365 static const struct encodedInt enums[] = {
366  { 1,    bin18 },
367  { -128, bin19 },
368 };
369 
370 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
371  * X509_ENUMERATED.
372  */
373 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
374  szOID_CRL_REASON_CODE };
375 
376 static void test_encodeEnumerated(DWORD dwEncoding)
377 {
378     DWORD i, j;
379 
380     for (i = 0; i < ARRAY_SIZE(enumeratedTypes); i++)
381     {
382         for (j = 0; j < ARRAY_SIZE(enums); j++)
383         {
384             BOOL ret;
385             BYTE *buf = NULL;
386             DWORD bufSize = 0;
387 
388             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
389              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
390              &bufSize);
391             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
392             if (ret)
393             {
394                 ok(buf[0] == 0xa,
395                  "Got unexpected type %d for enumerated (expected 0xa)\n",
396                  buf[0]);
397                 ok(buf[1] == enums[j].encoded[1],
398                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
399                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
400                  enums[j].encoded[1] + 1),
401                  "Encoded value of 0x%08x didn't match expected\n",
402                  enums[j].val);
403                 LocalFree(buf);
404             }
405         }
406     }
407 }
408 
409 static void test_decodeEnumerated(DWORD dwEncoding)
410 {
411     DWORD i, j;
412 
413     for (i = 0; i < ARRAY_SIZE(enumeratedTypes); i++)
414     {
415         for (j = 0; j < ARRAY_SIZE(enums); j++)
416         {
417             BOOL ret;
418             DWORD bufSize = sizeof(int);
419             int val;
420 
421             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
422              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
423              &val, &bufSize);
424             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
425             ok(bufSize == sizeof(int),
426              "Got unexpected size %d for enumerated\n", bufSize);
427             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
428              val, enums[j].val);
429         }
430     }
431 }
432 
433 struct encodedFiletime
434 {
435     SYSTEMTIME sysTime;
436     const BYTE *encodedTime;
437 };
438 
439 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
440  const struct encodedFiletime *time)
441 {
442     FILETIME ft = { 0 };
443     BYTE *buf = NULL;
444     DWORD bufSize = 0;
445     BOOL ret;
446 
447     ret = SystemTimeToFileTime(&time->sysTime, &ft);
448     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
449     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
450      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
451     /* years other than 1950-2050 are not allowed for encodings other than
452      * X509_CHOICE_OF_TIME.
453      */
454     if (structType == X509_CHOICE_OF_TIME ||
455      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
456     {
457         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
458          GetLastError());
459         ok(buf != NULL, "Expected an allocated buffer\n");
460         if (ret)
461         {
462             ok(buf[0] == time->encodedTime[0],
463              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
464              buf[0]);
465             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
466              time->encodedTime[1], bufSize);
467             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
468              "Got unexpected value for time encoding\n");
469             LocalFree(buf);
470         }
471     }
472     else
473         ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
474          broken(GetLastError() == ERROR_SUCCESS),
475          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
476 }
477 
478 static const char *printSystemTime(const SYSTEMTIME *st)
479 {
480     static char buf[64];
481 
482     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
483      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
484     return buf;
485 }
486 
487 static const char *printFileTime(const FILETIME *ft)
488 {
489     static char buf[64];
490     SYSTEMTIME st;
491 
492     FileTimeToSystemTime(ft, &st);
493     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
494      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
495     return buf;
496 }
497 
498 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
499 {
500     SYSTEMTIME st;
501 
502     FileTimeToSystemTime(got, &st);
503     ok((expected->wYear == st.wYear &&
504      expected->wMonth == st.wMonth &&
505      expected->wDay == st.wDay &&
506      expected->wHour == st.wHour &&
507      expected->wMinute == st.wMinute &&
508      expected->wSecond == st.wSecond &&
509      abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
510      /* Some Windows systems only seem to be accurate in their time decoding to
511       * within about an hour.
512       */
513      broken(expected->wYear == st.wYear &&
514      expected->wMonth == st.wMonth &&
515      expected->wDay == st.wDay &&
516      abs(expected->wHour - st.wHour) <= 1),
517      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
518      printSystemTime(expected), printFileTime(got));
519 }
520 
521 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
522  const struct encodedFiletime *time)
523 {
524     FILETIME ft = { 0 };
525     DWORD size = sizeof(ft);
526     BOOL ret;
527 
528     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
529      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
530     /* years other than 1950-2050 are not allowed for encodings other than
531      * X509_CHOICE_OF_TIME.
532      */
533     if (structType == X509_CHOICE_OF_TIME ||
534      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
535     {
536         ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
537          "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
538          GetLastError());
539         if (ret)
540             compareTime(&time->sysTime, &ft);
541     }
542     else
543         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
544          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
545          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
546          GetLastError());
547 }
548 
549 static const BYTE bin20[] = {
550     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
551 static const BYTE bin21[] = {
552     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
553 static const BYTE bin22[] = {
554     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
555 
556 static const struct encodedFiletime times[] = {
557  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
558  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
559  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
560 };
561 
562 static void test_encodeFiletime(DWORD dwEncoding)
563 {
564     DWORD i;
565 
566     for (i = 0; i < ARRAY_SIZE(times); i++)
567     {
568         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
569         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
570         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
571     }
572 }
573 
574 static const BYTE bin23[] = {
575     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
576 static const BYTE bin24[] = {
577     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
578 static const BYTE bin25[] = {
579     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
580 static const BYTE bin26[] = {
581     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
582 static const BYTE bin27[] = {
583     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
584 static const BYTE bin28[] = {
585     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
586 static const BYTE bin29[] = {
587     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
588 static const BYTE bin30[] = {
589     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
590 static const BYTE bin31[] = {
591     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
592 static const BYTE bin32[] = {
593     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
594 static const BYTE bin33[] = {
595     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
596 static const BYTE bin34[] = {
597     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
598 static const BYTE bin35[] = {
599     0x17,0x08, '4','5','0','6','0','6','1','6'};
600 static const BYTE bin36[] = {
601     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
602 static const BYTE bin37[] = {
603     0x18,0x04, '2','1','4','5'};
604 static const BYTE bin38[] = {
605     0x18,0x08, '2','1','4','5','0','6','0','6'};
606 
607 static void test_decodeFiletime(DWORD dwEncoding)
608 {
609     static const struct encodedFiletime otherTimes[] = {
610      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
611      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
612      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
613      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
614      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
615      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
616      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
617      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
618      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
619      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
620      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
621      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
622     };
623     /* An oddball case that succeeds in Windows, but doesn't seem correct
624      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
625      */
626     static const unsigned char *bogusTimes[] = {
627      /* oddly, this succeeds on Windows, with year 2765
628      "\x18" "\x0f" "21r50606161000Z",
629       */
630      bin35,
631      bin36,
632      bin37,
633      bin38,
634     };
635     DWORD i, size;
636     FILETIME ft1 = { 0 }, ft2 = { 0 };
637     BOOL ret;
638 
639     /* Check bogus length with non-NULL buffer */
640     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
641     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
642     size = 1;
643     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
644      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
645     ok(!ret && GetLastError() == ERROR_MORE_DATA,
646      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
647     /* Normal tests */
648     for (i = 0; i < ARRAY_SIZE(times); i++)
649     {
650         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
651         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
652         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
653     }
654     for (i = 0; i < ARRAY_SIZE(otherTimes); i++)
655     {
656         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
657         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
658         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
659     }
660     for (i = 0; i < ARRAY_SIZE(bogusTimes); i++)
661     {
662         size = sizeof(ft1);
663         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
664          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
665         ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
666                      GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
667            broken(ret), /* Win9x and NT4 for bin38 */
668          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
669          GetLastError());
670     }
671 }
672 
673 static const char commonName[] = "Juan Lang";
674 static const char surName[] = "Lang";
675 
676 static const BYTE emptySequence[] = { 0x30, 0 };
677 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
678 static const BYTE twoRDNs[] = {
679     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
680     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
681     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
682 static const BYTE encodedTwoRDNs[] = {
683 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
684 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
685 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
686 0x6e,0x67,0x00,
687 };
688 
689 static const BYTE us[] = { 0x55, 0x53 };
690 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
691  0x74, 0x61 };
692 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
693  0x6f, 0x6c, 0x69, 0x73 };
694 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
695  0x76, 0x65, 0x72, 0x73 };
696 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
697  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
698 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
699  0x73, 0x74 };
700 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
701  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
702 
703 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
704 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
705 
706 static CHAR oid_us[]            = "2.5.4.6",
707             oid_minnesota[]     = "2.5.4.8",
708             oid_minneapolis[]   = "2.5.4.7",
709             oid_codeweavers[]   = "2.5.4.10",
710             oid_wine[]          = "2.5.4.11",
711             oid_localhostAttr[] = "2.5.4.3",
712             oid_aric[]          = "1.2.840.113549.1.9.1";
713 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
714                                     { RDNA(minnesota) },
715                                     { RDNA(minneapolis) },
716                                     { RDNA(codeweavers) },
717                                     { RDNA(wine) },
718                                     { RDNA(localhostAttr) },
719                                     { RDNIA5(aric) } };
720 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
721                                            { RDNA(localhostAttr) },
722                                            { RDNA(minnesota) },
723                                            { RDNA(minneapolis) },
724                                            { RDNA(codeweavers) },
725                                            { RDNA(wine) },
726                                            { RDNIA5(aric) } };
727 
728 #undef RDNIA5
729 #undef RDNA
730 
731 static const BYTE encodedRDNAttrs[] = {
732 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
733 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
734 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
735 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
736 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
737 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
738 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
739 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
740 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
741 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
742 };
743 
744 static void test_encodeName(DWORD dwEncoding)
745 {
746     CERT_RDN_ATTR attrs[2];
747     CERT_RDN rdn;
748     CERT_NAME_INFO info;
749     static CHAR oid_common_name[] = szOID_COMMON_NAME,
750                 oid_sur_name[]    = szOID_SUR_NAME;
751     BYTE *buf = NULL;
752     DWORD size = 0;
753     BOOL ret;
754 
755     if (0)
756     {
757         /* Test with NULL pvStructInfo (crashes on win9x) */
758         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
759          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
760         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
761          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
762     }
763     /* Test with empty CERT_NAME_INFO */
764     info.cRDN = 0;
765     info.rgRDN = NULL;
766     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
767      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
768     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
769     if (ret)
770     {
771         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
772          "Got unexpected encoding for empty name\n");
773         LocalFree(buf);
774     }
775     if (0)
776     {
777         /* Test with bogus CERT_RDN (crashes on win9x) */
778         info.cRDN = 1;
779         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
780          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
781         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
782          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
783     }
784     /* Test with empty CERT_RDN */
785     rdn.cRDNAttr = 0;
786     rdn.rgRDNAttr = NULL;
787     info.cRDN = 1;
788     info.rgRDN = &rdn;
789     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
790      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
791     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
792     if (ret)
793     {
794         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
795          "Got unexpected encoding for empty RDN array\n");
796         LocalFree(buf);
797     }
798     if (0)
799     {
800         /* Test with bogus attr array (crashes on win9x) */
801         rdn.cRDNAttr = 1;
802         rdn.rgRDNAttr = NULL;
803         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
804          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
805         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
806          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
807     }
808     /* oddly, a bogus OID is accepted by Windows XP; not testing.
809     attrs[0].pszObjId = "bogus";
810     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
811     attrs[0].Value.cbData = sizeof(commonName);
812     attrs[0].Value.pbData = commonName;
813     rdn.cRDNAttr = 1;
814     rdn.rgRDNAttr = attrs;
815     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
816      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
817     ok(!ret, "Expected failure, got success\n");
818      */
819     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
820      * the encoded attributes to be swapped.
821      */
822     attrs[0].pszObjId = oid_common_name;
823     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
824     attrs[0].Value.cbData = sizeof(commonName);
825     attrs[0].Value.pbData = (BYTE *)commonName;
826     attrs[1].pszObjId = oid_sur_name;
827     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
828     attrs[1].Value.cbData = sizeof(surName);
829     attrs[1].Value.pbData = (BYTE *)surName;
830     rdn.cRDNAttr = 2;
831     rdn.rgRDNAttr = attrs;
832     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
833      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
834     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
835     if (ret)
836     {
837         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
838          "Got unexpected encoding for two RDN array\n");
839         LocalFree(buf);
840     }
841     /* A name can be "encoded" with previously encoded RDN attrs. */
842     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
843     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
844     attrs[0].Value.cbData = sizeof(twoRDNs);
845     rdn.cRDNAttr = 1;
846     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
847      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
848     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
849     if (ret)
850     {
851         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
852         ok(!memcmp(buf, encodedTwoRDNs, size),
853          "Unexpected value for re-encoded two RDN array\n");
854         LocalFree(buf);
855     }
856     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
857     rdn.cRDNAttr = 1;
858     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
859     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
860      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
861     ok(!ret && GetLastError() == E_INVALIDARG,
862      "Expected E_INVALIDARG, got %08x\n", GetLastError());
863     /* Test a more complex name */
864     rdn.cRDNAttr = ARRAY_SIZE(rdnAttrs);
865     rdn.rgRDNAttr = rdnAttrs;
866     info.cRDN = 1;
867     info.rgRDN = &rdn;
868     buf = NULL;
869     size = 0;
870     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
871      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
872     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
873     if (ret)
874     {
875         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
876         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
877         LocalFree(buf);
878     }
879 }
880 
881 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
882 static WCHAR surNameW[] = { 'L','a','n','g',0 };
883 
884 static const BYTE twoRDNsNoNull[] = {
885  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
886  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
887  0x20,0x4c,0x61,0x6e,0x67 };
888 static const BYTE anyType[] = {
889  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
890  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
891  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
892  0x61,0x4c,0x67,0x6e };
893 
894 static void test_encodeUnicodeName(DWORD dwEncoding)
895 {
896     CERT_RDN_ATTR attrs[2];
897     CERT_RDN rdn;
898     CERT_NAME_INFO info;
899     static CHAR oid_common_name[] = szOID_COMMON_NAME,
900                 oid_sur_name[]    = szOID_SUR_NAME;
901     BYTE *buf = NULL;
902     DWORD size = 0;
903     BOOL ret;
904 
905     if (0)
906     {
907         /* Test with NULL pvStructInfo (crashes on win9x) */
908         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
909          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
910         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
911          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
912     }
913     /* Test with empty CERT_NAME_INFO */
914     info.cRDN = 0;
915     info.rgRDN = NULL;
916     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
917      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
918     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
919     if (ret)
920     {
921         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
922          "Got unexpected encoding for empty name\n");
923         LocalFree(buf);
924     }
925     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
926      * encoding (the NULL).
927      */
928     attrs[0].pszObjId = oid_common_name;
929     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
930     attrs[0].Value.cbData = sizeof(commonNameW);
931     attrs[0].Value.pbData = (BYTE *)commonNameW;
932     rdn.cRDNAttr = 1;
933     rdn.rgRDNAttr = attrs;
934     info.cRDN = 1;
935     info.rgRDN = &rdn;
936     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
937      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
938     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
939      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
940     ok(size == 9, "Unexpected error index %08x\n", size);
941     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
942      * forces the order of the encoded attributes to be swapped.
943      */
944     attrs[0].pszObjId = oid_common_name;
945     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
946     attrs[0].Value.cbData = 0;
947     attrs[0].Value.pbData = (BYTE *)commonNameW;
948     attrs[1].pszObjId = oid_sur_name;
949     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
950     attrs[1].Value.cbData = 0;
951     attrs[1].Value.pbData = (BYTE *)surNameW;
952     rdn.cRDNAttr = 2;
953     rdn.rgRDNAttr = attrs;
954     info.cRDN = 1;
955     info.rgRDN = &rdn;
956     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
957      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
958     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
959     if (ret)
960     {
961         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
962          "Got unexpected encoding for two RDN array\n");
963         LocalFree(buf);
964     }
965     /* A name can be "encoded" with previously encoded RDN attrs. */
966     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
967     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
968     attrs[0].Value.cbData = sizeof(twoRDNs);
969     rdn.cRDNAttr = 1;
970     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
971      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
972     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
973     if (ret)
974     {
975         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
976         ok(!memcmp(buf, encodedTwoRDNs, size),
977          "Unexpected value for re-encoded two RDN array\n");
978         LocalFree(buf);
979     }
980     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
981     rdn.cRDNAttr = 1;
982     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
983     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
984      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
985     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
986     if (ret)
987     {
988         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
989         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
990         LocalFree(buf);
991     }
992 }
993 
994 static void compareNameValues(const CERT_NAME_VALUE *expected,
995  const CERT_NAME_VALUE *got)
996 {
997     if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
998         got->dwValueType == CERT_RDN_ENCODED_BLOB)
999     {
1000         win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1001         return;
1002     }
1003 
1004     ok(got->dwValueType == expected->dwValueType,
1005      "Expected string type %d, got %d\n", expected->dwValueType,
1006      got->dwValueType);
1007     ok(got->Value.cbData == expected->Value.cbData ||
1008      got->Value.cbData == expected->Value.cbData - sizeof(WCHAR) /* Win8 */,
1009      "String type %d: unexpected data size, got %d, expected %d\n",
1010      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1011     if (got->Value.cbData && got->Value.pbData)
1012         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1013          min(got->Value.cbData, expected->Value.cbData)),
1014          "String type %d: unexpected value\n", expected->dwValueType);
1015 }
1016 
1017 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1018  const CERT_RDN_ATTR *got)
1019 {
1020     if (expected->pszObjId && *expected->pszObjId)
1021     {
1022         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1023          expected->pszObjId);
1024         if (got->pszObjId)
1025         {
1026             ok(!strcmp(got->pszObjId, expected->pszObjId),
1027              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1028              expected->pszObjId);
1029         }
1030     }
1031     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1032      (const CERT_NAME_VALUE *)&got->dwValueType);
1033 }
1034 
1035 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1036 {
1037     ok(got->cRDNAttr == expected->cRDNAttr,
1038      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1039     if (got->cRDNAttr)
1040     {
1041         DWORD i;
1042 
1043         for (i = 0; i < got->cRDNAttr; i++)
1044             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1045     }
1046 }
1047 
1048 static void compareNames(const CERT_NAME_INFO *expected,
1049  const CERT_NAME_INFO *got)
1050 {
1051     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1052      expected->cRDN, got->cRDN);
1053     if (got->cRDN)
1054     {
1055         DWORD i;
1056 
1057         for (i = 0; i < got->cRDN; i++)
1058             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1059     }
1060 }
1061 
1062 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1063 static const BYTE twoRDNsExtraBytes[] = {
1064     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1065     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1066     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1067 
1068 static void test_decodeName(DWORD dwEncoding)
1069 {
1070     BYTE *buf = NULL;
1071     DWORD bufSize = 0;
1072     BOOL ret;
1073     CERT_RDN rdn;
1074     CERT_NAME_INFO info = { 1, &rdn };
1075 
1076     /* test empty name */
1077     bufSize = 0;
1078     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1079      emptySequence[1] + 2,
1080      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1081      &buf, &bufSize);
1082     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1083     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1084      * decoder works the same way, so only test the count.
1085      */
1086     if (ret)
1087     {
1088         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1089         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1090          "Expected 0 RDNs in empty info, got %d\n",
1091          ((CERT_NAME_INFO *)buf)->cRDN);
1092         LocalFree(buf);
1093     }
1094     /* test empty name with indefinite-length encoding */
1095     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1096      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1097      &buf, &bufSize);
1098     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1099     if (ret)
1100     {
1101         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1102         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1103          "Expected 0 RDNs in empty info, got %d\n",
1104          ((CERT_NAME_INFO *)buf)->cRDN);
1105         LocalFree(buf);
1106     }
1107     /* test empty RDN */
1108     bufSize = 0;
1109     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1110      emptyRDNs[1] + 2,
1111      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1112      &buf, &bufSize);
1113     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1114     if (ret)
1115     {
1116         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1117 
1118         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1119          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1120          "Got unexpected value for empty RDN\n");
1121         LocalFree(buf);
1122     }
1123     /* test two RDN attrs */
1124     bufSize = 0;
1125     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1126      twoRDNs[1] + 2,
1127      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1128      &buf, &bufSize);
1129     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1130     if (ret)
1131     {
1132         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1133                     oid_common_name[] = szOID_COMMON_NAME;
1134 
1135         CERT_RDN_ATTR attrs[] = {
1136          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1137           (BYTE *)surName } },
1138          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1139           (BYTE *)commonName } },
1140         };
1141 
1142         rdn.cRDNAttr = ARRAY_SIZE(attrs);
1143         rdn.rgRDNAttr = attrs;
1144         compareNames(&info, (CERT_NAME_INFO *)buf);
1145         LocalFree(buf);
1146     }
1147     /* test that two RDN attrs with extra bytes succeeds */
1148     bufSize = 0;
1149     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1150      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1151     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1152     /* And, a slightly more complicated name */
1153     buf = NULL;
1154     bufSize = 0;
1155     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1156      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1157     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1158     if (ret)
1159     {
1160         rdn.cRDNAttr = ARRAY_SIZE(decodedRdnAttrs);
1161         rdn.rgRDNAttr = decodedRdnAttrs;
1162         compareNames(&info, (CERT_NAME_INFO *)buf);
1163         LocalFree(buf);
1164     }
1165 }
1166 
1167 static void test_decodeUnicodeName(DWORD dwEncoding)
1168 {
1169     BYTE *buf = NULL;
1170     DWORD bufSize = 0;
1171     BOOL ret;
1172     CERT_RDN rdn;
1173     CERT_NAME_INFO info = { 1, &rdn };
1174 
1175     /* test empty name */
1176     bufSize = 0;
1177     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1178      emptySequence[1] + 2,
1179      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1180      &buf, &bufSize);
1181     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1182     if (ret)
1183     {
1184         ok(bufSize == sizeof(CERT_NAME_INFO),
1185          "Got wrong bufSize %d\n", bufSize);
1186         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1187          "Expected 0 RDNs in empty info, got %d\n",
1188          ((CERT_NAME_INFO *)buf)->cRDN);
1189         LocalFree(buf);
1190     }
1191     /* test empty RDN */
1192     bufSize = 0;
1193     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1194      emptyRDNs[1] + 2,
1195      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1196      &buf, &bufSize);
1197     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1198     if (ret)
1199     {
1200         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1201 
1202         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1203          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1204          "Got unexpected value for empty RDN\n");
1205         LocalFree(buf);
1206     }
1207     /* test two RDN attrs */
1208     bufSize = 0;
1209     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1210      sizeof(twoRDNsNoNull),
1211      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1212      &buf, &bufSize);
1213     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1214     if (ret)
1215     {
1216         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1217                     oid_common_name[] = szOID_COMMON_NAME;
1218 
1219         CERT_RDN_ATTR attrs[] = {
1220          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1221          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1222          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1223          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1224         };
1225 
1226         rdn.cRDNAttr = ARRAY_SIZE(attrs);
1227         rdn.rgRDNAttr = attrs;
1228         compareNames(&info, (CERT_NAME_INFO *)buf);
1229         LocalFree(buf);
1230     }
1231 }
1232 
1233 struct EncodedNameValue
1234 {
1235     CERT_NAME_VALUE value;
1236     const BYTE *encoded;
1237     DWORD encodedSize;
1238 };
1239 
1240 static const char bogusIA5[] = "\x80";
1241 static const char bogusPrintable[] = "~";
1242 static const char bogusNumeric[] = "A";
1243 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1244 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1245 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1246 static BYTE octetCommonNameValue[] = {
1247  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE numericCommonNameValue[] = {
1249  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE printableCommonNameValue[] = {
1251  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE t61CommonNameValue[] = {
1253  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE videotexCommonNameValue[] = {
1255  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1256 static BYTE ia5CommonNameValue[] = {
1257  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1258 static BYTE graphicCommonNameValue[] = {
1259  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1260 static BYTE visibleCommonNameValue[] = {
1261  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1262 static BYTE generalCommonNameValue[] = {
1263  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1264 static BYTE bmpCommonNameValue[] = {
1265  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1266  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1267 static BYTE utf8CommonNameValue[] = {
1268  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1269 static char embedded_null[] = "foo\0com";
1270 static BYTE ia5EmbeddedNull[] = {
1271  0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1272 
1273 static struct EncodedNameValue nameValues[] = {
1274  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1275      octetCommonNameValue, sizeof(octetCommonNameValue) },
1276  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1277      numericCommonNameValue, sizeof(numericCommonNameValue) },
1278  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1279      printableCommonNameValue, sizeof(printableCommonNameValue) },
1280  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1281      t61CommonNameValue, sizeof(t61CommonNameValue) },
1282  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1283      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1284  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1285      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1286  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1287      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1288  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1289      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1290  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1291      generalCommonNameValue, sizeof(generalCommonNameValue) },
1292  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1293      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1294  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1295      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1296  /* The following tests succeed under Windows, but really should fail,
1297   * they contain characters that are illegal for the encoding.  I'm
1298   * including them to justify my lazy encoding.
1299   */
1300  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1301      sizeof(bin42) },
1302  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1303      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1304  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1305      bin44, sizeof(bin44) },
1306 };
1307 /* This is kept separate, because the decoding doesn't return to the original
1308  * value.
1309  */
1310 static struct EncodedNameValue embeddedNullNameValue = {
1311  { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1312    ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1313 
1314 static void test_encodeNameValue(DWORD dwEncoding)
1315 {
1316     BYTE *buf = NULL;
1317     DWORD size = 0, i;
1318     BOOL ret;
1319     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1320 
1321     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1322     value.Value.pbData = printableCommonNameValue;
1323     value.Value.cbData = sizeof(printableCommonNameValue);
1324     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1325      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1326     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1327     if (ret)
1328     {
1329         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1330          size);
1331         ok(!memcmp(buf, printableCommonNameValue, size),
1332          "Unexpected encoding\n");
1333         LocalFree(buf);
1334     }
1335     for (i = 0; i < ARRAY_SIZE(nameValues); i++)
1336     {
1337         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1338          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1339         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1340          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1341          nameValues[i].value.dwValueType, GetLastError());
1342         if (ret)
1343         {
1344             ok(size == nameValues[i].encodedSize,
1345              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1346             ok(!memcmp(buf, nameValues[i].encoded, size),
1347              "Got unexpected encoding\n");
1348             LocalFree(buf);
1349         }
1350     }
1351     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1352      &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1353     ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1354      "Type %d: CryptEncodeObjectEx failed: %08x\n",
1355      embeddedNullNameValue.value.dwValueType, GetLastError());
1356     if (ret)
1357     {
1358         ok(size == embeddedNullNameValue.encodedSize,
1359          "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1360         ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1361          "Got unexpected encoding\n");
1362         LocalFree(buf);
1363     }
1364 }
1365 
1366 static void test_decodeNameValue(DWORD dwEncoding)
1367 {
1368     int i;
1369     BYTE *buf = NULL;
1370     DWORD bufSize = 0;
1371     BOOL ret;
1372 
1373     for (i = 0; i < ARRAY_SIZE(nameValues); i++)
1374     {
1375         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1376          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1377          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1378          &buf, &bufSize);
1379         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1380          nameValues[i].value.dwValueType, GetLastError());
1381         if (ret)
1382         {
1383             compareNameValues(&nameValues[i].value,
1384              (const CERT_NAME_VALUE *)buf);
1385             LocalFree(buf);
1386         }
1387     }
1388     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1389      embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1390      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1391      &buf, &bufSize);
1392     /* Some Windows versions disallow name values with embedded NULLs, so
1393      * either success or failure is acceptable.
1394      */
1395     if (ret)
1396     {
1397         CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1398          { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1399         CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1400          { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1401         const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1402          *expected = NULL;
1403 
1404         /* Some Windows versions decode name values with embedded NULLs,
1405          * others leave them encoded, even with the same version of crypt32.
1406          * Accept either.
1407          */
1408         ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1409          got->dwValueType == CERT_RDN_IA5_STRING,
1410          "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1411          got->dwValueType);
1412         if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1413             expected = &rdnEncodedValue;
1414         else if (got->dwValueType == CERT_RDN_IA5_STRING)
1415             expected = &embeddedNullValue;
1416         if (expected)
1417         {
1418             ok(got->Value.cbData == expected->Value.cbData,
1419              "String type %d: unexpected data size, got %d, expected %d\n",
1420              got->dwValueType, got->Value.cbData, expected->Value.cbData);
1421             if (got->Value.cbData && got->Value.pbData)
1422                 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1423                  min(got->Value.cbData, expected->Value.cbData)),
1424                  "String type %d: unexpected value\n", expected->dwValueType);
1425         }
1426         LocalFree(buf);
1427     }
1428 }
1429 
1430 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1431 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1432 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1433  'h','q','.','o','r','g',0 };
1434 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1435  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1436  0x6f, 0x72, 0x67 };
1437 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1438  0x575b, 0 };
1439 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1440 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1441  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1442 static const BYTE localhost[] = { 127, 0, 0, 1 };
1443 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1444  0x01 };
1445 static const unsigned char encodedCommonName[] = {
1446     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1447 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1448 static const BYTE encodedDirectoryName[] = {
1449 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1450 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1451 
1452 static void test_encodeAltName(DWORD dwEncoding)
1453 {
1454     CERT_ALT_NAME_INFO info = { 0 };
1455     CERT_ALT_NAME_ENTRY entry = { 0 };
1456     BYTE *buf = NULL;
1457     DWORD size = 0;
1458     BOOL ret;
1459     char oid[] = "1.2.3";
1460 
1461     /* Test with empty info */
1462     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1463      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1464     if (ret)
1465     {
1466         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1467         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1468         LocalFree(buf);
1469     }
1470     /* Test with an empty entry */
1471     info.cAltEntry = 1;
1472     info.rgAltEntry = &entry;
1473     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1474      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1475     ok(!ret && GetLastError() == E_INVALIDARG,
1476      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1477     /* Test with an empty pointer */
1478     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1479     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1480      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1481     if (ret)
1482     {
1483         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1484         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1485         LocalFree(buf);
1486     }
1487     /* Test with a real URL */
1488     U(entry).pwszURL = (LPWSTR)url;
1489     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1490      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1491     if (ret)
1492     {
1493         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1494         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1495         LocalFree(buf);
1496     }
1497     /* Now with the URL containing an invalid IA5 char */
1498     U(entry).pwszURL = (LPWSTR)nihongoURL;
1499     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1500      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1501     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1502      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1503     /* The first invalid character is at index 7 */
1504     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1505      "Expected invalid char at index 7, got %d\n",
1506      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1507     /* Now with the URL missing a scheme */
1508     U(entry).pwszURL = (LPWSTR)dnsName;
1509     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1510      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1511     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1512     if (ret)
1513     {
1514         /* This succeeds, but it shouldn't, so don't worry about conforming */
1515         LocalFree(buf);
1516     }
1517     /* Now with a DNS name */
1518     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1519     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1520      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1521     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1522     if (ret)
1523     {
1524         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1525         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1526         LocalFree(buf);
1527     }
1528     /* Test with an IP address */
1529     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1530     U(entry).IPAddress.cbData = sizeof(localhost);
1531     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1532     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1533      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1534     if (ret)
1535     {
1536         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1537         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1538         LocalFree(buf);
1539     }
1540     /* Test with OID */
1541     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1542     U(entry).pszRegisteredID = oid;
1543     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1544      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1545     if (ret)
1546     {
1547         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1548         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1549         LocalFree(buf);
1550     }
1551     /* Test with directory name */
1552     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1553     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1554     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1555     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1556      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1557     if (ret)
1558     {
1559         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1560         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1561         LocalFree(buf);
1562     }
1563 }
1564 
1565 static void test_decodeAltName(DWORD dwEncoding)
1566 {
1567     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1568      0x00, 0x00, 0x01 };
1569     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1570      0x01 };
1571     static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1572      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1573     static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1574      0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1575     static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1576      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1577     BOOL ret;
1578     BYTE *buf = NULL;
1579     DWORD bufSize = 0;
1580     CERT_ALT_NAME_INFO *info;
1581 
1582     /* Test some bogus ones first */
1583     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1584      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1585      NULL, &buf, &bufSize);
1586     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1587      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1588      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1589      GetLastError());
1590     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1591      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1592      &bufSize);
1593     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1594      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1595      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1596      GetLastError());
1597     /* Now expected cases */
1598     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1599      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1600     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1601     if (ret)
1602     {
1603         info = (CERT_ALT_NAME_INFO *)buf;
1604 
1605         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1606          info->cAltEntry);
1607         LocalFree(buf);
1608     }
1609     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1610      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1611     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1612     if (ret)
1613     {
1614         info = (CERT_ALT_NAME_INFO *)buf;
1615 
1616         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1617          info->cAltEntry);
1618         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1619          "Expected CERT_ALT_NAME_URL, got %d\n",
1620          info->rgAltEntry[0].dwAltNameChoice);
1621         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1622          "Expected empty URL\n");
1623         LocalFree(buf);
1624     }
1625     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1626      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1627     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1628     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1629      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1630     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1631     if (ret)
1632     {
1633         info = (CERT_ALT_NAME_INFO *)buf;
1634 
1635         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1636          info->cAltEntry);
1637         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1638          "Expected CERT_ALT_NAME_URL, got %d\n",
1639          info->rgAltEntry[0].dwAltNameChoice);
1640         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1641         LocalFree(buf);
1642     }
1643     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1644      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1645     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1646     if (ret)
1647     {
1648         info = (CERT_ALT_NAME_INFO *)buf;
1649 
1650         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1651          info->cAltEntry);
1652         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1653          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1654          info->rgAltEntry[0].dwAltNameChoice);
1655         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1656          "Unexpected DNS name\n");
1657         LocalFree(buf);
1658     }
1659     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1660      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1661     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1662     if (ret)
1663     {
1664         info = (CERT_ALT_NAME_INFO *)buf;
1665 
1666         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1667          info->cAltEntry);
1668         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1669          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1670          info->rgAltEntry[0].dwAltNameChoice);
1671         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1672          "Unexpected IP address length %d\n",
1673           U(info->rgAltEntry[0]).IPAddress.cbData);
1674         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1675          sizeof(localhost)), "Unexpected IP address value\n");
1676         LocalFree(buf);
1677     }
1678     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1679      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1680     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1681     if (ret)
1682     {
1683         info = (CERT_ALT_NAME_INFO *)buf;
1684 
1685         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1686          info->cAltEntry);
1687         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1688          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1689          info->rgAltEntry[0].dwAltNameChoice);
1690         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1691            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1692         LocalFree(buf);
1693     }
1694     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1695      encodedDirectoryName, sizeof(encodedDirectoryName),
1696      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1697     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1698     if (ret)
1699     {
1700         info = (CERT_ALT_NAME_INFO *)buf;
1701 
1702         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1703          info->cAltEntry);
1704         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1705          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1706          info->rgAltEntry[0].dwAltNameChoice);
1707         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1708          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1709           U(info->rgAltEntry[0]).DirectoryName.cbData);
1710         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1711          encodedCommonName, sizeof(encodedCommonName)),
1712          "Unexpected directory name value\n");
1713         LocalFree(buf);
1714     }
1715     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1716      dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1717      NULL, &buf, &bufSize);
1718     /* Fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned about the
1719      * particular failure, just that it doesn't decode.
1720      * It succeeds on (broken) Windows versions that haven't addressed
1721      * embedded NULLs in alternate names.
1722      */
1723     ok(!ret || broken(ret), "expected failure\n");
1724     /* An embedded bell character is allowed, however. */
1725     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1726      dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1727      NULL, &buf, &bufSize);
1728     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1729     if (ret)
1730     {
1731         info = (CERT_ALT_NAME_INFO *)buf;
1732 
1733         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1734          info->cAltEntry);
1735         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1736          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1737          info->rgAltEntry[0].dwAltNameChoice);
1738         LocalFree(buf);
1739     }
1740     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1741      url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1742      NULL, &buf, &bufSize);
1743     /* Again, fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned
1744      * about the particular failure, just that it doesn't decode.
1745      * It succeeds on (broken) Windows versions that haven't addressed
1746      * embedded NULLs in alternate names.
1747      */
1748     ok(!ret || broken(ret), "expected failure\n");
1749 }
1750 
1751 struct UnicodeExpectedError
1752 {
1753     DWORD   valueType;
1754     LPCWSTR str;
1755     DWORD   errorIndex;
1756     DWORD   error;
1757 };
1758 
1759 static const WCHAR oneW[] = { '1',0 };
1760 static const WCHAR aW[] = { 'a',0 };
1761 static const WCHAR quoteW[] = { '"', 0 };
1762 
1763 static struct UnicodeExpectedError unicodeErrors[] = {
1764  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1765  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1766  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1767  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1768  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1769  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1770 };
1771 
1772 struct UnicodeExpectedResult
1773 {
1774     DWORD           valueType;
1775     LPCWSTR         str;
1776     CRYPT_DATA_BLOB encoded;
1777 };
1778 
1779 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1780 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1781 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1782 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1783 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1784 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1785 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1786 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1787 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1788 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1789 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1790 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1791  0x5b };
1792 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1793  0x6f,0x5b };
1794 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1795  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1796 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1797  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1798 
1799 static struct UnicodeExpectedResult unicodeResults[] = {
1800  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1801  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1802  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1803  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1804  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1805  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1806  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1807  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1808  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1809  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1810  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1811  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1812  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1813 };
1814 
1815 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1816  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1817  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1818 };
1819 
1820 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1821 {
1822     BYTE *buf = NULL;
1823     DWORD size = 0, i;
1824     BOOL ret;
1825     CERT_NAME_VALUE value;
1826 
1827     if (0)
1828     {
1829         /* Crashes on win9x */
1830         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1831          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1832         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1833          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1834     }
1835     /* Have to have a string of some sort */
1836     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1837     value.Value.pbData = NULL;
1838     value.Value.cbData = 0;
1839     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1840      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1841     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1842      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1843     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1844     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1845      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1846     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1847      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1848     value.dwValueType = CERT_RDN_ANY_TYPE;
1849     value.Value.pbData = (LPBYTE)oneW;
1850     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1851      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1852     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1853      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1854     value.Value.cbData = sizeof(oneW);
1855     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1856      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1857     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1858      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1859     /* An encoded string with specified length isn't good enough either */
1860     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1861     value.Value.pbData = oneUniversal;
1862     value.Value.cbData = sizeof(oneUniversal);
1863     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1864      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1865     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1866      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1867     /* More failure checking */
1868     value.Value.cbData = 0;
1869     for (i = 0; i < ARRAY_SIZE(unicodeErrors); i++)
1870     {
1871         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1872         value.dwValueType = unicodeErrors[i].valueType;
1873         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1874          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1875         ok(!ret && GetLastError() == unicodeErrors[i].error,
1876          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1877          unicodeErrors[i].error, GetLastError());
1878         ok(size == unicodeErrors[i].errorIndex,
1879          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1880          size);
1881     }
1882     /* cbData can be zero if the string is NULL-terminated */
1883     value.Value.cbData = 0;
1884     for (i = 0; i < ARRAY_SIZE(unicodeResults); i++)
1885     {
1886         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1887         value.dwValueType = unicodeResults[i].valueType;
1888         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1889          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1890         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1891          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1892         if (ret)
1893         {
1894             ok(size == unicodeResults[i].encoded.cbData,
1895              "Value type %d: expected size %d, got %d\n",
1896              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1897             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1898              "Value type %d: unexpected value\n", value.dwValueType);
1899             LocalFree(buf);
1900         }
1901     }
1902     /* These "encode," but they do so by truncating each unicode character
1903      * rather than properly encoding it.  Kept separate from the proper results,
1904      * because the encoded forms won't decode to their original strings.
1905      */
1906     for (i = 0; i < ARRAY_SIZE(unicodeWeirdness); i++)
1907     {
1908         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1909         value.dwValueType = unicodeWeirdness[i].valueType;
1910         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1911          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1912         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1913         if (ret)
1914         {
1915             ok(size == unicodeWeirdness[i].encoded.cbData,
1916              "Value type %d: expected size %d, got %d\n",
1917              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1918             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1919              "Value type %d: unexpected value\n", value.dwValueType);
1920             LocalFree(buf);
1921         }
1922     }
1923 }
1924 
1925 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1926 {
1927     if (n <= 0) return 0;
1928     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1929     return *str1 - *str2;
1930 }
1931 
1932 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1933 {
1934     DWORD i;
1935 
1936     for (i = 0; i < ARRAY_SIZE(unicodeResults); i++)
1937     {
1938         BYTE *buf = NULL;
1939         BOOL ret;
1940         DWORD size = 0;
1941 
1942         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1943          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1944          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1945         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1946          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1947         if (ret && buf)
1948         {
1949             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1950 
1951             ok(value->dwValueType == unicodeResults[i].valueType,
1952              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1953              value->dwValueType);
1954             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1955              value->Value.cbData / sizeof(WCHAR)),
1956              "Unexpected decoded value for index %d (value type %d)\n", i,
1957              unicodeResults[i].valueType);
1958             LocalFree(buf);
1959         }
1960     }
1961 }
1962 
1963 static const unsigned char decoded_hi_octet[] = { 'h','i' };
1964 static const unsigned char encoded_hi_octet[] = { ASN_OCTETSTRING,2,'h','i' };
1965 static const unsigned char decoded_something_long_octet[] = {
1966      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g' };
1967 static const unsigned char encoded_something_long_octet[] = {
1968      ASN_OCTETSTRING,15,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g' };
1969 static const unsigned char encoded_empty_octet[] = { ASN_OCTETSTRING,0 };
1970 
1971 static void test_encodeOctets(DWORD dwEncoding)
1972 {
1973     CRYPT_DATA_BLOB blob;
1974     DWORD i;
1975 
1976     static const struct {
1977         const BYTE *decoded;
1978         UINT decoded_size;
1979         const BYTE *encoded;
1980         UINT encoded_size;
1981     } tests[] = {
1982         {
1983             decoded_hi_octet, sizeof(decoded_hi_octet),
1984             encoded_hi_octet, sizeof(encoded_hi_octet)
1985         },{
1986             decoded_something_long_octet, sizeof(decoded_something_long_octet),
1987             encoded_something_long_octet, sizeof(encoded_something_long_octet)
1988         },{
1989             encoded_empty_octet, 0,
1990             encoded_empty_octet, sizeof(encoded_empty_octet)
1991         }
1992     };
1993 
1994     for (i = 0; i < ARRAY_SIZE(tests); i++)
1995     {
1996         BYTE *buf = NULL;
1997         BOOL ret;
1998         DWORD bufSize = 0;
1999 
2000         blob.cbData = tests[i].decoded_size;
2001         blob.pbData = (BYTE*)tests[i].decoded;
2002         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
2003          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2004         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
2005         if (ret)
2006         {
2007             ok(bufSize == tests[i].encoded_size, "[%u] buf size %u expected %u\n",
2008                i, bufSize, tests[i].encoded_size);
2009             ok(buf[0] == 4, "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
2010             ok(buf[1] == tests[i].decoded_size, "[%u] Got length %d, expected %d\n",
2011                i, buf[1], tests[i].decoded_size);
2012             ok(!memcmp(buf, tests[i].encoded, tests[i].encoded_size), "[%u] Got unexpected value\n", i);
2013             LocalFree(buf);
2014         }
2015     }
2016 }
2017 
2018 static const unsigned char encoded_constructed_hi_octet[] =
2019     { ASN_CONSTRUCTOR|ASN_OCTETSTRING,0x80, ASN_OCTETSTRING,2,'h','i', 0,0 };
2020 static const unsigned char encoded_constructed_hi_octet2[] =
2021     { ASN_CONSTRUCTOR|ASN_OCTETSTRING,4, ASN_OCTETSTRING,2,'h','i', 1,2,3 };
2022 static const unsigned char encoded_constructed_hi_octet3[] =
2023     { ASN_CONSTRUCTOR|ASN_OCTETSTRING,8, ASN_CONSTRUCTOR|ASN_OCTETSTRING,0x80, ASN_OCTETSTRING,2,'h','i', 0,0, 0,0 };
2024 static const unsigned char encoded_constructed_hi_octet_invalid_end[] =
2025     { ASN_CONSTRUCTOR|ASN_OCTETSTRING,0x80, ASN_OCTETSTRING,2,'h','i', 0,1 };
2026 
2027 static void test_decodeOctets(DWORD dwEncoding)
2028 {
2029     DWORD i;
2030 
2031     static const struct {
2032         const BYTE *encoded;
2033         UINT encoded_size;
2034         const BYTE *decoded;
2035         UINT decoded_size;
2036         DWORD error;
2037     } tests[] = {
2038         {
2039             encoded_hi_octet, sizeof(encoded_hi_octet),
2040             decoded_hi_octet, sizeof(decoded_hi_octet)
2041         },{
2042             encoded_something_long_octet, sizeof(encoded_something_long_octet),
2043             decoded_something_long_octet, sizeof(decoded_something_long_octet)
2044         },{
2045             encoded_constructed_hi_octet, sizeof(encoded_constructed_hi_octet),
2046             decoded_hi_octet, sizeof(decoded_hi_octet)
2047         },{
2048             encoded_constructed_hi_octet2, sizeof(encoded_constructed_hi_octet2),
2049             decoded_hi_octet, sizeof(decoded_hi_octet)
2050         },{
2051             encoded_constructed_hi_octet3, sizeof(encoded_constructed_hi_octet3),
2052             decoded_hi_octet, sizeof(decoded_hi_octet)
2053         },{
2054             encoded_empty_octet, sizeof(encoded_empty_octet),
2055             encoded_empty_octet, 0
2056         },{
2057             encoded_hi_octet, sizeof(encoded_hi_octet) - 1,
2058             NULL, 0, CRYPT_E_ASN1_EOD
2059         },{
2060             encoded_constructed_hi_octet, sizeof(encoded_constructed_hi_octet) - 1,
2061             NULL, 0, CRYPT_E_ASN1_EOD
2062         },{
2063             encoded_constructed_hi_octet_invalid_end, sizeof(encoded_constructed_hi_octet_invalid_end),
2064             NULL, 0, CRYPT_E_ASN1_CORRUPT
2065         }
2066     };
2067 
2068     for (i = 0; i < ARRAY_SIZE(tests); i++)
2069     {
2070         BYTE *buf = NULL;
2071         BOOL ret;
2072         DWORD bufSize = 0;
2073 
2074         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2075          tests[i].encoded, tests[i].encoded_size,
2076          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2077         if (tests[i].error)
2078         {
2079             ok(!ret && GetLastError() == tests[i].error,
2080                "[%u] CryptDecodeObjectEx returned %x(%x)\n", i, ret, GetLastError());
2081             continue;
2082         }
2083         ok(ret, "[%u] CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
2084         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + tests[i].decoded_size,
2085            "[%u] Expected size >= %d, got %d\n", i,
2086            (int)sizeof(CRYPT_DATA_BLOB) + tests[i].decoded_size, bufSize);
2087         ok(buf != NULL, "Expected allocated buffer\n");
2088         if (ret)
2089         {
2090             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2091 
2092             ok (blob->cbData == tests[i].decoded_size, "[%u] cbData = %u\n", i, blob->cbData);
2093             if (blob->cbData)
2094                 ok(!memcmp(blob->pbData, tests[i].decoded, blob->cbData),
2095                  "Unexpected value\n");
2096             LocalFree(buf);
2097         }
2098     }
2099 }
2100 
2101 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2102 
2103 struct encodedBits
2104 {
2105     DWORD cUnusedBits;
2106     const BYTE *encoded;
2107     DWORD cbDecoded;
2108     const BYTE *decoded;
2109 };
2110 
2111 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2112 static const unsigned char bin53[] = { 0xff,0xff };
2113 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2114 static const unsigned char bin55[] = { 0xff,0xfe };
2115 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2116 static const unsigned char bin57[] = { 0xfe };
2117 
2118 static const struct encodedBits bits[] = {
2119     /* normal test cases */
2120     { 0, bin52, 2, bin53 },
2121     { 1, bin54, 2, bin55 },
2122     /* strange test case, showing cUnusedBits >= 8 is allowed */
2123     { 9, bin56, 1, bin57 },
2124 };
2125 
2126 static void test_encodeBits(DWORD dwEncoding)
2127 {
2128     DWORD i;
2129 
2130     for (i = 0; i < ARRAY_SIZE(bits); i++)
2131     {
2132         CRYPT_BIT_BLOB blob;
2133         BOOL ret;
2134         BYTE *buf = NULL;
2135         DWORD bufSize = 0;
2136 
2137         blob.cbData = sizeof(bytesToEncode);
2138         blob.pbData = (BYTE *)bytesToEncode;
2139         blob.cUnusedBits = bits[i].cUnusedBits;
2140         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2141          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2142         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2143         if (ret)
2144         {
2145             ok(bufSize == bits[i].encoded[1] + 2,
2146              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2147              bits[i].encoded[1] + 2);
2148             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2149              "%d: Unexpected value\n", i);
2150             LocalFree(buf);
2151         }
2152     }
2153 }
2154 
2155 static void test_decodeBits(DWORD dwEncoding)
2156 {
2157     static const BYTE ber[] = "\x03\x02\x01\xff";
2158     static const BYTE berDecoded = 0xfe;
2159     DWORD i;
2160     BOOL ret;
2161     BYTE *buf = NULL;
2162     DWORD bufSize = 0;
2163 
2164     /* normal cases */
2165     for (i = 0; i < ARRAY_SIZE(bits); i++)
2166     {
2167         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2168          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2169          &bufSize);
2170         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2171         if (ret)
2172         {
2173             CRYPT_BIT_BLOB *blob;
2174 
2175             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2176                "Got unexpected size %d\n", bufSize);
2177             blob = (CRYPT_BIT_BLOB *)buf;
2178             ok(blob->cbData == bits[i].cbDecoded,
2179              "Got unexpected length %d, expected %d\n", blob->cbData,
2180              bits[i].cbDecoded);
2181             if (blob->cbData && bits[i].cbDecoded)
2182                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2183                  "Unexpected value\n");
2184             LocalFree(buf);
2185         }
2186     }
2187     /* special case: check that something that's valid in BER but not in DER
2188      * decodes successfully
2189      */
2190     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2191      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2192     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2193     if (ret)
2194     {
2195         CRYPT_BIT_BLOB *blob;
2196 
2197         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2198            "Got unexpected size %d\n", bufSize);
2199         blob = (CRYPT_BIT_BLOB *)buf;
2200         ok(blob->cbData == sizeof(berDecoded),
2201            "Got unexpected length %d\n", blob->cbData);
2202         if (blob->cbData)
2203             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2204         LocalFree(buf);
2205     }
2206 }
2207 
2208 struct Constraints2
2209 {
2210     CERT_BASIC_CONSTRAINTS2_INFO info;
2211     const BYTE *encoded;
2212 };
2213 
2214 static const unsigned char bin59[] = { 0x30,0x00 };
2215 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2216 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2217 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2218 static const struct Constraints2 constraints2[] = {
2219  /* empty constraints */
2220  { { FALSE, FALSE, 0}, bin59 },
2221  /* can be a CA */
2222  { { TRUE,  FALSE, 0}, bin60 },
2223  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2224   * but that's not the case
2225   */
2226  { { FALSE, TRUE,  0}, bin61 },
2227  /* can be a CA and has path length constraints set */
2228  { { TRUE,  TRUE,  1}, bin62 },
2229 };
2230 
2231 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2232 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2233  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2234  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2235  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2236 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2237  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2238  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2239  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2240  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2241 
2242 static void test_encodeBasicConstraints(DWORD dwEncoding)
2243 {
2244     DWORD i, bufSize = 0;
2245     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2246     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2247      (LPBYTE)encodedDomainName };
2248     BOOL ret;
2249     BYTE *buf = NULL;
2250 
2251     /* First test with the simpler info2 */
2252     for (i = 0; i < ARRAY_SIZE(constraints2); i++)
2253     {
2254         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2255          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2256          &bufSize);
2257         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2258         if (ret)
2259         {
2260             ok(bufSize == constraints2[i].encoded[1] + 2,
2261              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2262              bufSize);
2263             ok(!memcmp(buf, constraints2[i].encoded,
2264              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2265             LocalFree(buf);
2266         }
2267     }
2268     /* Now test with more complex basic constraints */
2269     info.SubjectType.cbData = 0;
2270     info.fPathLenConstraint = FALSE;
2271     info.cSubtreesConstraint = 0;
2272     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2273      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2274     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2275      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2276     if (ret)
2277     {
2278         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2279         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2280          "Unexpected value\n");
2281         LocalFree(buf);
2282     }
2283     /* None of the certs I examined had any subtree constraint, but I test one
2284      * anyway just in case.
2285      */
2286     info.cSubtreesConstraint = 1;
2287     info.rgSubtreesConstraint = &nameBlob;
2288     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2289      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2290     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2291      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2292     if (ret)
2293     {
2294         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2295         ok(!memcmp(buf, constraintWithDomainName,
2296          sizeof(constraintWithDomainName)), "Unexpected value\n");
2297         LocalFree(buf);
2298     }
2299     /* FIXME: test encoding with subject type. */
2300 }
2301 
2302 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2303 
2304 static void test_decodeBasicConstraints(DWORD dwEncoding)
2305 {
2306     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2307      0xff };
2308     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2309     DWORD i;
2310     BOOL ret;
2311     BYTE *buf = NULL;
2312     DWORD bufSize = 0;
2313 
2314     /* First test with simpler info2 */
2315     for (i = 0; i < ARRAY_SIZE(constraints2); i++)
2316     {
2317         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2318          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2319          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2320         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2321          GetLastError());
2322         if (ret)
2323         {
2324             CERT_BASIC_CONSTRAINTS2_INFO *info =
2325              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2326 
2327             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2328              "Unexpected value for item %d\n", i);
2329             LocalFree(buf);
2330         }
2331     }
2332     /* Check with the order of encoded elements inverted */
2333     buf = (PBYTE)1;
2334     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2335      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2336      &bufSize);
2337     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2338      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2339      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2340      GetLastError());
2341     ok(!buf, "Expected buf to be set to NULL\n");
2342     /* Check with a non-DER bool */
2343     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2344      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2345      &buf, &bufSize);
2346     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2347     if (ret)
2348     {
2349         CERT_BASIC_CONSTRAINTS2_INFO *info =
2350          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2351 
2352         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2353         LocalFree(buf);
2354     }
2355     /* Check with a non-basic constraints value */
2356     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2357      encodedCommonName, encodedCommonName[1] + 2,
2358      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2359     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2360      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2361      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2362      GetLastError());
2363     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2364     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2365      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2366      &buf, &bufSize);
2367     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2368     if (ret)
2369     {
2370         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2371 
2372         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2373         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2374         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2375         LocalFree(buf);
2376     }
2377     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2378      constraintWithDomainName, sizeof(constraintWithDomainName),
2379      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2380     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2381     if (ret)
2382     {
2383         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2384 
2385         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2386         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2387         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2388         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2389         {
2390             ok(info->rgSubtreesConstraint[0].cbData ==
2391              sizeof(encodedDomainName), "Wrong size %d\n",
2392              info->rgSubtreesConstraint[0].cbData);
2393             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2394              sizeof(encodedDomainName)), "Unexpected value\n");
2395         }
2396         LocalFree(buf);
2397     }
2398 }
2399 
2400 /* These are terrible public keys of course, I'm just testing encoding */
2401 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2402 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2403 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2404 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2405 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2406 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2407 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2408 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2409 
2410 struct EncodedRSAPubKey
2411 {
2412     const BYTE *modulus;
2413     size_t modulusLen;
2414     const BYTE *encoded;
2415     size_t decodedModulusLen;
2416 };
2417 
2418 static const struct EncodedRSAPubKey rsaPubKeys[] = {
2419     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2420     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2421     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2422     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2423 };
2424 
2425 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2426 {
2427     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2428     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2429     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2430     BOOL ret;
2431     BYTE *buf = NULL;
2432     DWORD bufSize = 0, i;
2433 
2434     /* Try with a bogus blob type */
2435     hdr->bType = 2;
2436     hdr->bVersion = CUR_BLOB_VERSION;
2437     hdr->reserved = 0;
2438     hdr->aiKeyAlg = CALG_RSA_KEYX;
2439     rsaPubKey->magic = 0x31415352;
2440     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2441     rsaPubKey->pubexp = 65537;
2442     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2443      sizeof(modulus1));
2444 
2445     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2446      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2447     ok(!ret && GetLastError() == E_INVALIDARG,
2448      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2449     /* Now with a bogus reserved field */
2450     hdr->bType = PUBLICKEYBLOB;
2451     hdr->reserved = 1;
2452     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2453      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2454     if (ret)
2455     {
2456         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2457          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2458         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2459         LocalFree(buf);
2460     }
2461     /* Now with a bogus blob version */
2462     hdr->reserved = 0;
2463     hdr->bVersion = 0;
2464     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2465      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2466     if (ret)
2467     {
2468         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2469          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2470         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2471         LocalFree(buf);
2472     }
2473     /* And with a bogus alg ID */
2474     hdr->bVersion = CUR_BLOB_VERSION;
2475     hdr->aiKeyAlg = CALG_DES;
2476     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2477      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2478     if (ret)
2479     {
2480         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2481          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2482         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2483         LocalFree(buf);
2484     }
2485     /* Check a couple of RSA-related OIDs */
2486     hdr->aiKeyAlg = CALG_RSA_KEYX;
2487     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2488      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2489     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2490      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2491     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2492      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2493     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2494      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2495     /* Finally, all valid */
2496     hdr->aiKeyAlg = CALG_RSA_KEYX;
2497     for (i = 0; i < ARRAY_SIZE(rsaPubKeys); i++)
2498     {
2499         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2500          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2501         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2502          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2503         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2504         if (ret)
2505         {
2506             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2507              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2508              bufSize);
2509             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2510              "Unexpected value\n");
2511             LocalFree(buf);
2512         }
2513     }
2514 }
2515 
2516 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2517 {
2518     DWORD i;
2519     LPBYTE buf = NULL;
2520     DWORD bufSize = 0;
2521     BOOL ret;
2522 
2523     /* Try with a bad length */
2524     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2525      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2526      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2527     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2528      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2529      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2530      GetLastError());
2531     /* Try with a couple of RSA-related OIDs */
2532     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2533      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2534      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2535     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2536      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2537     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2538      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2539      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2540     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2541      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2542     /* Now try success cases */
2543     for (i = 0; i < ARRAY_SIZE(rsaPubKeys); i++)
2544     {
2545         bufSize = 0;
2546         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2547          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2548          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2549         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2550         if (ret)
2551         {
2552             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2553             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2554 
2555             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2556              rsaPubKeys[i].decodedModulusLen,
2557              "Wrong size %d\n", bufSize);
2558             ok(hdr->bType == PUBLICKEYBLOB,
2559              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2560              hdr->bType);
2561             ok(hdr->bVersion == CUR_BLOB_VERSION,
2562              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2563              CUR_BLOB_VERSION, hdr->bVersion);
2564             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2565              hdr->reserved);
2566             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2567              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2568             ok(rsaPubKey->magic == 0x31415352,
2569              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2570             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2571              "Wrong bit len %d\n", rsaPubKey->bitlen);
2572             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2573              rsaPubKey->pubexp);
2574             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2575              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2576              "Unexpected modulus\n");
2577             LocalFree(buf);
2578         }
2579     }
2580 }
2581 
2582 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2583  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2584  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2585 
2586 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2587  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2588  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2589  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2590 
2591 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2592 {
2593     CRYPT_DER_BLOB blobs[ARRAY_SIZE(ints)];
2594     CRYPT_SEQUENCE_OF_ANY seq;
2595     DWORD i;
2596     BOOL ret;
2597     BYTE *buf = NULL;
2598     DWORD bufSize = 0;
2599 
2600     /* Encode a homogeneous sequence */
2601     for (i = 0; i < ARRAY_SIZE(ints); i++)
2602     {
2603         blobs[i].cbData = ints[i].encoded[1] + 2;
2604         blobs[i].pbData = (BYTE *)ints[i].encoded;
2605     }
2606     seq.cValue = ARRAY_SIZE(ints);
2607     seq.rgValue = blobs;
2608 
2609     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2610      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2611     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2612     if (ret)
2613     {
2614         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2615         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2616         LocalFree(buf);
2617     }
2618     /* Change the type of the first element in the sequence, and give it
2619      * another go
2620      */
2621     blobs[0].cbData = times[0].encodedTime[1] + 2;
2622     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2623     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2624      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2625     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2626     if (ret)
2627     {
2628         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2629         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2630          "Unexpected value\n");
2631         LocalFree(buf);
2632     }
2633 }
2634 
2635 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2636 {
2637     BOOL ret;
2638     BYTE *buf = NULL;
2639     DWORD bufSize = 0;
2640 
2641     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2642      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2643     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2644     if (ret)
2645     {
2646         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2647         DWORD i;
2648 
2649         ok(seq->cValue == ARRAY_SIZE(ints), "Wrong elements %d\n", seq->cValue);
2650         for (i = 0; i < min(seq->cValue, ARRAY_SIZE(ints)); i++)
2651         {
2652             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2653              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2654              seq->rgValue[i].cbData);
2655             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2656              ints[i].encoded[1] + 2), "Unexpected value\n");
2657         }
2658         LocalFree(buf);
2659     }
2660     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2661      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2662      &bufSize);
2663     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2664     if (ret)
2665     {
2666         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2667 
2668         ok(seq->cValue == ARRAY_SIZE(ints), "Wrong elements %d\n", seq->cValue);
2669         /* Just check the first element since it's all that changed */
2670         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2671          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2672          seq->rgValue[0].cbData);
2673         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2674          times[0].encodedTime[1] + 2), "Unexpected value\n");
2675         LocalFree(buf);
2676     }
2677 }
2678 
2679 struct encodedExtensions
2680 {
2681     CERT_EXTENSIONS exts;
2682     const BYTE *encoded;
2683 };
2684 
2685 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2686 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2687 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2688 static CERT_EXTENSION criticalExt =
2689  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2690 static CERT_EXTENSION nonCriticalExt =
2691  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2692 static CHAR oid_short[] = "1.1";
2693 static CERT_EXTENSION extWithShortOid =
2694  { oid_short, FALSE, { 0, NULL } };
2695 
2696 static const BYTE ext0[] = { 0x30,0x00 };
2697 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2698                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2699 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2700                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2701 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2702 
2703 static const struct encodedExtensions exts[] = {
2704  { { 0, NULL }, ext0 },
2705  { { 1, &criticalExt }, ext1 },
2706  { { 1, &nonCriticalExt }, ext2 },
2707  { { 1, &extWithShortOid }, ext3 }
2708 };
2709 
2710 static void test_encodeExtensions(DWORD dwEncoding)
2711 {
2712     DWORD i;
2713 
2714     for (i = 0; i < ARRAY_SIZE(exts); i++)
2715     {
2716         BOOL ret;
2717         BYTE *buf = NULL;
2718         DWORD bufSize = 0;
2719 
2720         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2721          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2722         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2723         if (ret)
2724         {
2725             ok(bufSize == exts[i].encoded[1] + 2,
2726              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2727             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2728              "Unexpected value\n");
2729             LocalFree(buf);
2730         }
2731     }
2732 }
2733 
2734 static void test_decodeExtensions(DWORD dwEncoding)
2735 {
2736     DWORD i;
2737 
2738     for (i = 0; i < ARRAY_SIZE(exts); i++)
2739     {
2740         BOOL ret;
2741         BYTE *buf = NULL;
2742         DWORD bufSize = 0;
2743 
2744         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2745          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2746          NULL, &buf, &bufSize);
2747         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2748         if (ret)
2749         {
2750             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2751             DWORD j;
2752 
2753             ok(ext->cExtension == exts[i].exts.cExtension,
2754              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2755              ext->cExtension);
2756             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2757             {
2758                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2759                  exts[i].exts.rgExtension[j].pszObjId),
2760                  "Expected OID %s, got %s\n",
2761                  exts[i].exts.rgExtension[j].pszObjId,
2762                  ext->rgExtension[j].pszObjId);
2763                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2764                  exts[i].exts.rgExtension[j].Value.pbData,
2765                  exts[i].exts.rgExtension[j].Value.cbData),
2766                  "Unexpected value\n");
2767             }
2768             LocalFree(buf);
2769         }
2770         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2771          exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
2772         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2773         buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);
2774         if (buf)
2775         {
2776             ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2777              exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, buf, &bufSize);
2778             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2779             HeapFree(GetProcessHeap(), 0, buf);
2780         }
2781     }
2782 }
2783 
2784 /* MS encodes public key info with a NULL if the algorithm identifier's
2785  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2786  * it encodes them by omitting the algorithm parameters.  It accepts either
2787  * form for decoding.
2788  */
2789 struct encodedPublicKey
2790 {
2791     CERT_PUBLIC_KEY_INFO info;
2792     const BYTE *encoded;
2793     const BYTE *encodedNoNull;
2794     CERT_PUBLIC_KEY_INFO decoded;
2795 };
2796 
2797 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2798  0xe, 0xf };
2799 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2800 
2801 static const unsigned char bin64[] = {
2802     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2803 static const unsigned char bin65[] = {
2804     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2805 static const unsigned char bin66[] = {
2806     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2807 static const unsigned char bin67[] = {
2808     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2809 static const unsigned char bin68[] = {
2810     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2811     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2812 static const unsigned char bin69[] = {
2813     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2814     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2815 static const unsigned char bin70[] = {
2816     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2817     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2818     0x0f};
2819 static const unsigned char bin71[] = {
2820     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2821     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2822     0x0f};
2823 static unsigned char bin72[] = { 0x05,0x00};
2824 
2825 static CHAR oid_bogus[] = "1.2.3",
2826             oid_rsa[]   = szOID_RSA;
2827 
2828 static const struct encodedPublicKey pubKeys[] = {
2829  /* with a bogus OID */
2830  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2831   bin64, bin65,
2832   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2833  /* some normal keys */
2834  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2835   bin66, bin67,
2836   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2837  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2838   bin68, bin69,
2839   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2840  /* with add'l parameters--note they must be DER-encoded */
2841  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2842   (BYTE *)aKey, 0 } },
2843   bin70, bin71,
2844   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2845   (BYTE *)aKey, 0 } } },
2846 };
2847 
2848 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2849 {
2850     DWORD i;
2851 
2852     for (i = 0; i < ARRAY_SIZE(pubKeys); i++)
2853     {
2854         BOOL ret;
2855         BYTE *buf = NULL;
2856         DWORD bufSize = 0;
2857 
2858         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2859          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2860          &bufSize);
2861         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2862          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2863         if (ret)
2864         {
2865             ok(bufSize == pubKeys[i].encoded[1] + 2,
2866              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2867             if (bufSize == pubKeys[i].encoded[1] + 2)
2868                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2869                  "Unexpected value\n");
2870             LocalFree(buf);
2871         }
2872     }
2873 }
2874 
2875 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2876  const CERT_PUBLIC_KEY_INFO *got)
2877 {
2878     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2879      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2880      got->Algorithm.pszObjId);
2881     ok(expected->Algorithm.Parameters.cbData ==
2882      got->Algorithm.Parameters.cbData,
2883      "Expected parameters of %d bytes, got %d\n",
2884      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2885     if (expected->Algorithm.Parameters.cbData)
2886         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2887          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2888          "Unexpected algorithm parameters\n");
2889     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2890      "Expected public key of %d bytes, got %d\n",
2891      expected->PublicKey.cbData, got->PublicKey.cbData);
2892     if (expected->PublicKey.cbData)
2893         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2894          got->PublicKey.cbData), "Unexpected public key value\n");
2895 }
2896 
2897 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2898 {
2899     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2900      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2901      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2902      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2903     DWORD i;
2904     BOOL ret;
2905     BYTE *buf = NULL;
2906     DWORD bufSize = 0;
2907 
2908     for (i = 0; i < ARRAY_SIZE(pubKeys); i++)
2909     {
2910         /* The NULL form decodes to the decoded member */
2911         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2912          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2913          NULL, &buf, &bufSize);
2914         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2915         if (ret)
2916         {
2917             comparePublicKeyInfo(&pubKeys[i].decoded,
2918              (CERT_PUBLIC_KEY_INFO *)buf);
2919             LocalFree(buf);
2920         }
2921         /* The non-NULL form decodes to the original */
2922         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2923          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2924          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2925         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2926         if (ret)
2927         {
2928             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2929             LocalFree(buf);
2930         }
2931     }
2932     /* Test with bogus (not valid DER) parameters */
2933     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2934      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2935      NULL, &buf, &bufSize);
2936     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2937      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2938      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2939      GetLastError());
2940 }
2941 
2942 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2943  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2944  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2945  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2946  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2947 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2948  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2949  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2950  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2951  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2952 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2953  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2954  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2955  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2956  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2957 static const BYTE v4Cert[] = {
2958 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2959 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2960 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2961 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2962 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2963  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2964  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2965  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2966  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2967  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2968  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2969 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2970  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2971  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2972  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2973  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2974  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2975  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2976 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2977  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2978  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2979  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2980  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2981  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2982  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2983  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2984  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2985  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2986 static const BYTE v1CertWithPubKey[] = {
2987 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2988 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2989 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2990 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2991 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2992 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2993 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2994 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2995 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2996 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2997 0x01,0x01 };
2998 static const BYTE v1CertWithPubKeyNoNull[] = {
2999 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
3000 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
3001 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
3002 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3003 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
3004 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
3005 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
3006 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
3007 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
3008 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3009 static const BYTE v1CertWithSubjectKeyId[] = {
3010 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
3011 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
3012 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
3013 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3014 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
3015 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
3016 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
3017 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
3018 0x4c,0x61,0x6e,0x67,0x00 };
3019 static const BYTE v1CertWithIssuerUniqueId[] = {
3020 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
3021 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
3022 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3023 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
3024 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
3025 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
3026 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
3027 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
3028 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3029 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
3030 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
3031 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
3032 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
3033 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
3034 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
3035 0x01,0x01,0xff,0x02,0x01,0x01 };
3036 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
3037 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
3038 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
3039 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
3040 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3041 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
3042 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
3043 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
3044 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
3045 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
3046 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
3047 0xff,0x02,0x01,0x01 };
3048 
3049 static const BYTE serialNum[] = { 0x01 };
3050 
3051 static void test_encodeCertToBeSigned(DWORD dwEncoding)
3052 {
3053     BOOL ret;
3054     BYTE *buf = NULL;
3055     DWORD size = 0;
3056     CERT_INFO info = { 0 };
3057     static char oid_rsa_rsa[] = szOID_RSA_RSA;
3058     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
3059     CERT_EXTENSION ext;
3060 
3061     if (0)
3062     {
3063         /* Test with NULL pvStructInfo (crashes on win9x) */
3064         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
3065          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3066         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3067          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3068     }
3069     /* Test with a V1 cert */
3070     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3071      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3072     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3073      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3074     if (ret)
3075     {
3076         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3077          v1Cert[1] + 2, size);
3078         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3079         LocalFree(buf);
3080     }
3081     /* Test v2 cert */
3082     info.dwVersion = CERT_V2;
3083     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3084      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3085     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3086      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3087     if (ret)
3088     {
3089         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3090         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3091         LocalFree(buf);
3092     }
3093     /* Test v3 cert */
3094     info.dwVersion = CERT_V3;
3095     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3096      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3097     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3098      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3099     if (ret)
3100     {
3101         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3102         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3103         LocalFree(buf);
3104     }
3105     /* A v4 cert? */
3106     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3107     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3108      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3109     if (ret)
3110     {
3111         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3112         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3113         LocalFree(buf);
3114     }
3115     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3116      * API doesn't prevent it)
3117      */
3118     info.dwVersion = CERT_V1;
3119     info.cExtension = 1;
3120     info.rgExtension = &criticalExt;
3121     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3122      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3123     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3124      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3125     if (ret)
3126     {
3127         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3128         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3129         LocalFree(buf);
3130     }
3131     /* test v1 cert with a serial number */
3132     info.SerialNumber.cbData = sizeof(serialNum);
3133     info.SerialNumber.pbData = (BYTE *)serialNum;
3134     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3135      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3136     if (ret)
3137     {
3138         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3139         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3140         LocalFree(buf);
3141     }
3142     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3143     info.dwVersion = CERT_V1;
3144     info.cExtension = 0;
3145     info.IssuerUniqueId.cbData = sizeof(serialNum);
3146     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3147     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3148      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3149     ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3150      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3151     if (ret)
3152     {
3153         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3154         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3155          "Got unexpected value\n");
3156         LocalFree(buf);
3157     }
3158     /* Test v1 cert with an issuer name, a subject name, and a serial number */
3159     info.IssuerUniqueId.cbData = 0;
3160     info.IssuerUniqueId.pbData = NULL;
3161     info.cExtension = 1;
3162     info.rgExtension = &criticalExt;
3163     info.Issuer.cbData = sizeof(encodedCommonName);
3164     info.Issuer.pbData = (BYTE *)encodedCommonName;
3165     info.Subject.cbData = sizeof(encodedCommonName);
3166     info.Subject.pbData = (BYTE *)encodedCommonName;
3167     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3168      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3169     if (ret)
3170     {
3171         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3172         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3173         LocalFree(buf);
3174     }
3175     /* Add a public key */
3176     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3177     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3178     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3179     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3180      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3181     if (ret)
3182     {
3183         ok(size == sizeof(v1CertWithPubKey) ||
3184          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3185         if (size == sizeof(v1CertWithPubKey))
3186             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3187         else if (size == sizeof(v1CertWithPubKeyNoNull))
3188             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3189              "Got unexpected value\n");
3190         LocalFree(buf);
3191     }
3192     /* Again add an issuer unique id */
3193     info.IssuerUniqueId.cbData = sizeof(serialNum);
3194     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3195     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3196      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3197     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3198     if (ret)
3199     {
3200         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3201          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3202          "Wrong size %d\n", size);
3203         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3204             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3205              size), "unexpected value\n");
3206         else if (size ==
3207          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3208             ok(!memcmp(buf,
3209              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3210              "unexpected value\n");
3211         LocalFree(buf);
3212     }
3213     /* Remove the public key, and add a subject key identifier extension */
3214     info.IssuerUniqueId.cbData = 0;
3215     info.IssuerUniqueId.pbData = NULL;
3216     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3217     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3218     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3219     ext.pszObjId = oid_subject_key_identifier;
3220     ext.fCritical = FALSE;
3221     ext.Value.cbData = sizeof(octetCommonNameValue);
3222     ext.Value.pbData = octetCommonNameValue;
3223     info.cExtension = 1;
3224     info.rgExtension = &ext;
3225     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3226      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3227     if (ret)
3228     {
3229         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3230         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3231         LocalFree(buf);
3232     }
3233 }
3234 
3235 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3236 {
3237     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3238      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3239     BOOL ret;
3240     BYTE *buf = NULL;
3241     DWORD size = 0, i;
3242 
3243     /* Test with NULL pbEncoded */
3244     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3245      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3246     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3247      GetLastError() == OSS_BAD_ARG /* Win9x */),
3248      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3249     if (0)
3250     {
3251         /* Crashes on win9x */
3252         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3253          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3254         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3255          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3256     }
3257     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3258      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3259      * serial number, an issuer, a subject, and a public key.
3260      */
3261     for (i = 0; i < ARRAY_SIZE(corruptCerts); i++)
3262     {
3263         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3264          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3265          &buf, &size);
3266         ok(!ret, "Expected failure\n");
3267     }
3268     /* The following succeeds, even though v1 certs are not allowed to have
3269      * extensions.
3270      */
3271     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3272      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3273      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3274     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3275     if (ret)
3276     {
3277         CERT_INFO *info = (CERT_INFO *)buf;
3278 
3279         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3280         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3281          info->dwVersion);
3282         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3283          info->cExtension);
3284         LocalFree(buf);
3285     }
3286     /* The following also succeeds, even though V1 certs are not allowed to
3287      * have issuer unique ids.
3288      */
3289     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3290      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3291      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3292      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3293     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3294     if (ret)
3295     {
3296         CERT_INFO *info = (CERT_INFO *)buf;
3297 
3298         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3299         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3300          info->dwVersion);
3301         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3302          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3303         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3304          "unexpected issuer unique id value\n");
3305         LocalFree(buf);
3306     }
3307     /* Now check with serial number, subject and issuer specified */
3308     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3309      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3310     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3311     if (ret)
3312     {
3313         CERT_INFO *info = (CERT_INFO *)buf;
3314 
3315         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3316         ok(info->SerialNumber.cbData == 1,
3317          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3318         ok(*info->SerialNumber.pbData == *serialNum,
3319          "Expected serial number %d, got %d\n", *serialNum,
3320          *info->SerialNumber.pbData);
3321         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3322          "Wrong size %d\n", info->Issuer.cbData);
3323         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3324          "Unexpected issuer\n");
3325         ok(info->Subject.cbData == sizeof(encodedCommonName),
3326          "Wrong size %d\n", info->Subject.cbData);
3327         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3328          info->Subject.cbData), "Unexpected subject\n");
3329         LocalFree(buf);
3330     }
3331     /* Check again with pub key specified */
3332     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3333      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3334      &buf, &size);
3335     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3336     if (ret)
3337     {
3338         CERT_INFO *info = (CERT_INFO *)buf;
3339 
3340         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3341         ok(info->SerialNumber.cbData == 1,
3342          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3343         ok(*info->SerialNumber.pbData == *serialNum,
3344          "Expected serial number %d, got %d\n", *serialNum,
3345          *info->SerialNumber.pbData);
3346         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3347          "Wrong size %d\n", info->Issuer.cbData);
3348         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3349          "Unexpected issuer\n");
3350         ok(info->Subject.cbData == sizeof(encodedCommonName),
3351          "Wrong size %d\n", info->Subject.cbData);
3352         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3353          info->Subject.cbData), "Unexpected subject\n");
3354         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3355          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3356          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3357         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3358          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3359         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3360          sizeof(aKey)), "Unexpected public key\n");
3361         LocalFree(buf);
3362     }
3363 }
3364 
3365 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3366  0xe, 0xf };
3367 
3368 static const BYTE signedBigCert[] = {
3369  ASN_SEQUENCE,0x81,147,
3370    ASN_SEQUENCE,122,
3371      ASN_INTEGER,1, 0x01,
3372      ASN_SEQUENCE,2,
3373        ASN_OBJECTIDENTIFIER,0,
3374      ASN_SEQUENCE,21,
3375        0x31,19,
3376          ASN_SEQUENCE,17,
3377            ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03,
3378            0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
3379      ASN_SEQUENCE,34,
3380        0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3381        0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3382      ASN_SEQUENCE,21,
3383        0x31,19,
3384          ASN_SEQUENCE,17,
3385            ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03,
3386            0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
3387      ASN_SEQUENCE,7,
3388        ASN_SEQUENCE,2,
3389          ASN_OBJECTIDENTIFIER,0,
3390        ASN_BITS,1, 0x00,
3391    0xa3,22,
3392      ASN_SEQUENCE,20,
3393        ASN_SEQUENCE,18,
3394          ASN_OBJECTIDENTIFIER,3, 0x55,0x1d,0x13,
3395          0x01,1, 0xff,
3396          ASN_OCTETSTRING,8, 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,
3397      ASN_SEQUENCE,2,
3398        ASN_OBJECTIDENTIFIER,0,
3399  ASN_BITS,17, 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,
3400               0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00
3401 };
3402 
3403 static const BYTE signedBigCertWithIndefiniteSeq[] = {
3404  ASN_SEQUENCE,0x81,151,
3405    ASN_SEQUENCE,126,
3406      ASN_INTEGER,1, 0x01,
3407      ASN_SEQUENCE,2,
3408        ASN_OBJECTIDENTIFIER,0,
3409      ASN_SEQUENCE,21,
3410        0x31,19,
3411          ASN_SEQUENCE,17,
3412            ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03,
3413            0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
3414      ASN_SEQUENCE,0x80,
3415        0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3416        0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3417      0,0,
3418      ASN_SEQUENCE,21,
3419        0x31,19,
3420          ASN_SEQUENCE,17,
3421            ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03,
3422            0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
3423      ASN_SEQUENCE,0x80,
3424        ASN_SEQUENCE,2,
3425          ASN_OBJECTIDENTIFIER,0,
3426        ASN_BITS,1, 0x00,
3427      0,0,
3428    0xa3,22,
3429      ASN_SEQUENCE,20,
3430        ASN_SEQUENCE,18,
3431          ASN_OBJECTIDENTIFIER,3, 0x55,0x1d,0x13,
3432          0x01,1, 0xff,
3433          ASN_OCTETSTRING,8, 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,
3434      ASN_SEQUENCE,2,
3435        ASN_OBJECTIDENTIFIER,0,
3436  ASN_BITS,17, 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,
3437               0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00
3438 };
3439 
3440 static void test_encodeCert(DWORD dwEncoding)
3441 {
3442     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3443      * also that bigCert is a NULL-terminated string, so don't count its
3444      * last byte (otherwise the signed cert won't decode.)
3445      */
3446     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3447      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3448     BOOL ret;
3449     BYTE *buf = NULL;
3450     DWORD bufSize = 0;
3451 
3452     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3453      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3454     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3455     if (ret)
3456     {
3457         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3458         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3459         LocalFree(buf);
3460     }
3461 }
3462 
3463 static void test_decodeCert(DWORD dwEncoding)
3464 {
3465     BOOL ret;
3466     BYTE *buf = NULL;
3467     DWORD size = 0;
3468 
3469     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3470      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3471     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3472     if (ret)
3473     {
3474         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3475 
3476         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3477          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3478         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3479          "Unexpected cert\n");
3480         ok(info->Signature.cbData == sizeof(hash),
3481          "Wrong signature size %d\n", info->Signature.cbData);
3482         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3483          "Unexpected signature\n");
3484         LocalFree(buf);
3485     }
3486     /* A signed cert decodes as a CERT_INFO too */
3487     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3488      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3489     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3490     if (ret)
3491     {
3492         CERT_INFO *info = (CERT_INFO *)buf;
3493 
3494         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3495         ok(info->SerialNumber.cbData == 1,
3496          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3497         ok(*info->SerialNumber.pbData == *serialNum,
3498          "Expected serial number %d, got %d\n", *serialNum,
3499          *info->SerialNumber.pbData);
3500         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3501          "Wrong size %d\n", info->Issuer.cbData);
3502         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3503          "Unexpected issuer\n");
3504         ok(info->Subject.cbData == sizeof(encodedCommonName),
3505          "Wrong size %d\n", info->Subject.cbData);
3506         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3507          info->Subject.cbData), "Unexpected subject\n");
3508         LocalFree(buf);
3509     }
3510     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCertWithIndefiniteSeq,
3511      sizeof(signedBigCertWithIndefiniteSeq), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3512     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3513     if (ret)
3514     {
3515         CERT_INFO *info = (CERT_INFO *)buf;
3516 
3517         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3518         ok(info->SerialNumber.cbData == 1,
3519          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3520         ok(*info->SerialNumber.pbData == *serialNum,
3521          "Expected serial number %d, got %d\n", *serialNum,
3522          *info->SerialNumber.pbData);
3523         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3524          "Wrong size %d\n", info->Issuer.cbData);
3525         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3526          "Unexpected issuer\n");
3527         ok(info->Subject.cbData == sizeof(encodedCommonName),
3528          "Wrong size %d\n", info->Subject.cbData);
3529         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3530          info->Subject.cbData), "Unexpected subject\n");
3531         LocalFree(buf);
3532     }
3533 }
3534 
3535 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3536 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3537  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3538  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3539 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3540  0x00, 0x03 };
3541 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3542  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3543  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3544 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3545  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3546  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3547  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3548  0x2e, 0x6f, 0x72, 0x67 };
3549 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3550  CRL_REASON_AFFILIATION_CHANGED;
3551 
3552 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3553 {
3554     CRL_DIST_POINTS_INFO info = { 0 };
3555     CRL_DIST_POINT point = { { 0 } };
3556     CERT_ALT_NAME_ENTRY entry = { 0 };
3557     BOOL ret;
3558     BYTE *buf = NULL;
3559     DWORD size = 0;
3560 
3561     /* Test with an empty info */
3562     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3563      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3564     ok(!ret && GetLastError() == E_INVALIDARG,
3565      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3566     /* Test with one empty dist point */
3567     info.cDistPoint = 1;
3568     info.rgDistPoint = &point;
3569     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3570      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3571     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3572     if (ret)
3573     {
3574         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3575         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3576         LocalFree(buf);
3577     }
3578     /* A dist point with an invalid name */
3579     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3580     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3581     U(entry).pwszURL = (LPWSTR)nihongoURL;
3582     U(point.DistPointName).FullName.cAltEntry = 1;
3583     U(point.DistPointName).FullName.rgAltEntry = &entry;
3584     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3585      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3586     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3587      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3588     /* The first invalid character is at index 7 */
3589     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3590      "Expected invalid char at index 7, got %d\n",
3591      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3592     /* A dist point with (just) a valid name */
3593     U(entry).pwszURL = (LPWSTR)url;
3594     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3595      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3596     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3597     if (ret)
3598     {
3599         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3600         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3601         LocalFree(buf);
3602     }
3603     /* A dist point with (just) reason flags */
3604     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3605     point.ReasonFlags.cbData = sizeof(crlReason);
3606     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3607     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3608      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3609     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3610     if (ret)
3611     {
3612         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3613         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3614         LocalFree(buf);
3615     }
3616     /* A dist point with just an issuer */
3617     point.ReasonFlags.cbData = 0;
3618     point.CRLIssuer.cAltEntry = 1;
3619     point.CRLIssuer.rgAltEntry = &entry;
3620     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3621      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3622     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3623     if (ret)
3624     {
3625         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3626         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3627         LocalFree(buf);
3628     }
3629     /* A dist point with both a name and an issuer */
3630     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3631     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3632      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3633     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3634     if (ret)
3635     {
3636         ok(size == sizeof(distPointWithUrlAndIssuer),
3637          "Wrong size %d\n", size);
3638         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3639         LocalFree(buf);
3640     }
3641 }
3642 
3643 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3644 {
3645     BOOL ret;
3646     BYTE *buf = NULL;
3647     DWORD size = 0;
3648     PCRL_DIST_POINTS_INFO info;
3649     PCRL_DIST_POINT point;
3650     PCERT_ALT_NAME_ENTRY entry;
3651 
3652     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3653      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3654      &buf, &size);
3655     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3656     if (ret)
3657     {
3658         info = (PCRL_DIST_POINTS_INFO)buf;
3659         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3660          "Wrong size %d\n", size);
3661         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3662          info->cDistPoint);
3663         point = info->rgDistPoint;
3664         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3665          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3666          point->DistPointName.dwDistPointNameChoice);
3667         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3668         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3669         LocalFree(buf);
3670     }
3671     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3672      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3673      &buf, &size);
3674     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3675     if (ret)
3676     {
3677         info = (PCRL_DIST_POINTS_INFO)buf;
3678         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3679          "Wrong size %d\n", size);
3680         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3681          info->cDistPoint);
3682         point = info->rgDistPoint;
3683         ok(point->DistPointName.dwDistPointNameChoice ==
3684          CRL_DIST_POINT_FULL_NAME,
3685          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3686          point->DistPointName.dwDistPointNameChoice);
3687         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3688          "Expected 1 name entry, got %d\n",
3689          U(point->DistPointName).FullName.cAltEntry);
3690         entry = U(point->DistPointName).FullName.rgAltEntry;
3691         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3692          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3693         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3694         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3695         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3696         LocalFree(buf);
3697     }
3698     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3699      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3700      NULL, &buf, &size);
3701     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3702     if (ret)
3703     {
3704         info = (PCRL_DIST_POINTS_INFO)buf;
3705         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3706          "Wrong size %d\n", size);
3707         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3708          info->cDistPoint);
3709         point = info->rgDistPoint;
3710         ok(point->DistPointName.dwDistPointNameChoice ==
3711          CRL_DIST_POINT_NO_NAME,
3712          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3713          point->DistPointName.dwDistPointNameChoice);
3714         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3715          "Expected reason length\n");
3716         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3717          "Unexpected reason\n");
3718         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3719         LocalFree(buf);
3720     }
3721     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3722      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3723      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3724     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3725     if (ret)
3726     {
3727         info = (PCRL_DIST_POINTS_INFO)buf;
3728         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3729          "Wrong size %d\n", size);
3730         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3731          info->cDistPoint);
3732         point = info->rgDistPoint;
3733         ok(point->DistPointName.dwDistPointNameChoice ==
3734          CRL_DIST_POINT_FULL_NAME,
3735          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3736          point->DistPointName.dwDistPointNameChoice);
3737         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3738          "Expected 1 name entry, got %d\n",
3739          U(point->DistPointName).FullName.cAltEntry);
3740         entry = U(point->DistPointName).FullName.rgAltEntry;
3741         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3742          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3743         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3744         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3745         ok(point->CRLIssuer.cAltEntry == 1,
3746          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3747         entry = point->CRLIssuer.rgAltEntry;
3748         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3749          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3750         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3751         LocalFree(buf);
3752     }
3753     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3754      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3755      NULL, NULL, &size);
3756     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3757     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3758     if (buf)
3759     {
3760         ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3761          distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3762          NULL, buf, &size);
3763         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3764         HeapFree(GetProcessHeap(), 0, buf);
3765     }
3766 }
3767 
3768 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3769 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3770 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3771  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3772  0x67 };
3773 
3774 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3775 {
3776     BOOL ret;
3777     BYTE *buf = NULL;
3778     DWORD size = 0;
3779     CRL_ISSUING_DIST_POINT point = { { 0 } };
3780     CERT_ALT_NAME_ENTRY entry;
3781 
3782     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3783      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3784     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3785     {
3786         skip("no X509_ISSUING_DIST_POINT encode support\n");
3787         return;
3788     }
3789     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3790      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3791     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3792      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3793     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3794     if (ret)
3795     {
3796         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3797         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3798         LocalFree(buf);
3799     }
3800     /* nonsensical flags */
3801     point.fOnlyContainsUserCerts = TRUE;
3802     point.fOnlyContainsCACerts = TRUE;
3803     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3804      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3805     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3806     if (ret)
3807     {
3808         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3809         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3810         LocalFree(buf);
3811     }
3812     /* unimplemented name type */
3813     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3814     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3815     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3816      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3817     ok(!ret && GetLastError() == E_INVALIDARG,
3818      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3819     /* empty name */
3820     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3821     U(point.DistPointName).FullName.cAltEntry = 0;
3822     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3823      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3824     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3825     if (ret)
3826     {
3827         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3828         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3829         LocalFree(buf);
3830     }
3831     /* name with URL entry */
3832     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3833     U(entry).pwszURL = (LPWSTR)url;
3834     U(point.DistPointName).FullName.cAltEntry = 1;
3835     U(point.DistPointName).FullName.rgAltEntry = &entry;
3836     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3837      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3838     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3839     if (ret)
3840     {
3841         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3842         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3843         LocalFree(buf);
3844     }
3845 }
3846 
3847 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3848  const CERT_ALT_NAME_ENTRY *got)
3849 {
3850     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3851      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3852      got->dwAltNameChoice);
3853     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3854     {
3855         switch (got->dwAltNameChoice)
3856         {
3857         case CERT_ALT_NAME_RFC822_NAME:
3858         case CERT_ALT_NAME_DNS_NAME:
3859         case CERT_ALT_NAME_EDI_PARTY_NAME:
3860         case CERT_ALT_NAME_URL:
3861         case CERT_ALT_NAME_REGISTERED_ID:
3862             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3863              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3864              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3865              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3866              "Unexpected name\n");
3867             break;
3868         case CERT_ALT_NAME_X400_ADDRESS:
3869         case CERT_ALT_NAME_DIRECTORY_NAME:
3870         case CERT_ALT_NAME_IP_ADDRESS:
3871             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3872                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3873             ok(!memcmp(U(*got).IPAddress.pbData, U(*expected).IPAddress.pbData,
3874                        U(*got).IPAddress.cbData), "Unexpected value\n");
3875             break;
3876         }
3877     }
3878 }
3879 
3880 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3881  const CERT_ALT_NAME_INFO *got)
3882 {
3883     DWORD i;
3884 
3885     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3886      expected->cAltEntry, got->cAltEntry);
3887     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3888         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3889 }
3890 
3891 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3892  const CRL_DIST_POINT_NAME *got)
3893 {
3894     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3895      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3896     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3897         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3898 }
3899 
3900 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3901  const CRL_ISSUING_DIST_POINT *got)
3902 {
3903     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3904     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3905      "Unexpected fOnlyContainsUserCerts\n");
3906     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3907      "Unexpected fOnlyContainsCACerts\n");
3908     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3909      "Unexpected reason flags\n");
3910     ok(got->fIndirectCRL == expected->fIndirectCRL,
3911      "Unexpected fIndirectCRL\n");
3912 }
3913 
3914 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3915 {
3916     BOOL ret;
3917     BYTE *buf = NULL;
3918     DWORD size = 0;
3919     CRL_ISSUING_DIST_POINT point = { { 0 } };
3920 
3921     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3922      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3923      &buf, &size);
3924     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3925     {
3926         skip("no X509_ISSUING_DIST_POINT decode support\n");
3927         return;
3928     }
3929     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3930     if (ret)
3931     {
3932         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3933         LocalFree(buf);
3934     }
3935     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3936      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3937      &buf, &size);
3938     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3939     if (ret)
3940     {
3941         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3942         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3943         LocalFree(buf);
3944     }
3945     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3946      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3947      &buf, &size);
3948     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3949     if (ret)
3950     {
3951         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3952         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3953         U(point.DistPointName).FullName.cAltEntry = 0;
3954         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3955         LocalFree(buf);
3956     }
3957     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3958      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3959     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3960     if (ret)
3961     {
3962         CERT_ALT_NAME_ENTRY entry;
3963 
3964         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3965         U(entry).pwszURL = (LPWSTR)url;
3966         U(point.DistPointName).FullName.cAltEntry = 1;
3967         U(point.DistPointName).FullName.rgAltEntry = &entry;
3968         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3969         LocalFree(buf);
3970     }
3971 }
3972 
3973 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3974  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3975  0x30, 0x5a };
3976 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3977  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3978  0x30, 0x30, 0x30, 0x30, 0x5a };
3979 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3980  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3981  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3982  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3983  0x5a };
3984 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3985  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3986  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3987  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3988  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3989  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3990 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3991  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3992  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3993  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3994  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3995  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3996 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3997  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3998  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3999  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
4000  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
4001  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
4002  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
4003 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
4004  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4005  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
4006  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
4007  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
4008  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
4009  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
4010 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
4011  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
4012  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
4013  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
4014  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
4015  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
4016  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
4017 
4018 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
4019 {
4020     BOOL ret;
4021     BYTE *buf = NULL;
4022     DWORD size = 0;
4023     CRL_INFO info = { 0 };
4024     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
4025 
4026     /* Test with a V1 CRL */
4027     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4028      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4029     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
4030      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4031     if (ret)
4032     {
4033         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
4034         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
4035         LocalFree(buf);
4036     }
4037     /* Test v2 CRL */
4038     info.dwVersion = CRL_V2;
4039     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4040      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4041     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
4042      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4043     if (ret)
4044     {
4045         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
4046          v2CRL[1] + 2, size);
4047         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
4048         LocalFree(buf);
4049     }
4050     /* v1 CRL with a name */
4051     info.dwVersion = CRL_V1;
4052     info.Issuer.cbData = sizeof(encodedCommonName);
4053     info.Issuer.pbData = (BYTE *)encodedCommonName;
4054     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4055      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4056     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4057     if (ret)
4058     {
4059         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
4060         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
4061         LocalFree(buf);
4062     }
4063     if (0)
4064     {
4065         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
4066         info.cCRLEntry = 1;
4067         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4068          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4069         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4070          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
4071     }
4072     /* now set an empty entry */
4073     info.cCRLEntry = 1;
4074     info.rgCRLEntry = &entry;
4075     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4076      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4077     if (ret)
4078     {
4079         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
4080          "Wrong size %d\n", size);
4081         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
4082          "Got unexpected value\n");
4083         LocalFree(buf);
4084     }
4085     /* an entry with a serial number */
4086     entry.SerialNumber.cbData = sizeof(serialNum);
4087     entry.SerialNumber.pbData = (BYTE *)serialNum;
4088     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4089      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4090     if (ret)
4091     {
4092         ok(size == sizeof(v1CRLWithIssuerAndEntry),
4093          "Wrong size %d\n", size);
4094         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
4095          "Got unexpected value\n");
4096         LocalFree(buf);
4097     }
4098     /* an entry with an extension */
4099     entry.cExtension = 1;
4100     entry.rgExtension = &criticalExt;
4101     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4102      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4103     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4104     if (ret)
4105     {
4106         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
4107         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
4108         LocalFree(buf);
4109     }
4110     /* a CRL with an extension */
4111     entry.cExtension = 0;
4112     info.cExtension = 1;
4113     info.rgExtension = &criticalExt;
4114     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4115      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4116     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4117     if (ret)
4118     {
4119         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
4120         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
4121         LocalFree(buf);
4122     }
4123     /* a v2 CRL with an extension, this time non-critical */
4124     info.dwVersion = CRL_V2;
4125     info.rgExtension = &nonCriticalExt;
4126     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4127      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4128     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4129     if (ret)
4130     {
4131         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
4132         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
4133         LocalFree(buf);
4134     }
4135 }
4136 
4137 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
4138  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4139  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
4140  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
4141  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
4142  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
4143  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
4144  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
4145  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
4146  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
4147  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
4148  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
4149  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
4150  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
4151  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
4152  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
4153  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
4154  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
4155  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
4156  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
4157  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
4158  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
4159  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
4160  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
4161  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4162  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4163  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4164  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4165  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4166  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4167  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4168  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4169  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4170  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4171  0xcd };
4172 static const BYTE verisignCRLWithLotsOfEntries[] = {
4173 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4174 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4175 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4176 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4177 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4178 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4179 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4180 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4181 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4182 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4183 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4184 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4185 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4186 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4187 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4188 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4189 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4190 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4191 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4192 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4193 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4194 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4195 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4196 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4197 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4198 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4199 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4200 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4201 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4202 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4203 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4204 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4205 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4206 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4207 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4208 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4209 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4210 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4211 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4212 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4213 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4214 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4215 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4216 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4217 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4218 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4219 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4220 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4221 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4222 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4223 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4224 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4225 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4226 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4227 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4228 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4229 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4230 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4231 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4232 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4233 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4234 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4235 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4236 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4237 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4238 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4239 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4240 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4241 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4242 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4243 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4244 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4245 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4246 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4247 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4248 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4249 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4250 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4251 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4252 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4253 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4254 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4255 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4256 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4257 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4258 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4259 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4260 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4261 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4262 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4263 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4264 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4265 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4266 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4267 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4268 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4269 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4270 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4271 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4272 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4273 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4274 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4275 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4276 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4277 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4278 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4279 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4280 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4281 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4282 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4283 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4284 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4285 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4286 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4287 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4288 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4289 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4290 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4291 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4292 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4293 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4294 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4295 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4296 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4297 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4298 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4299 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4300 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4301 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4302 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4303 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4304 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4305 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4306 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4307 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4308 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4309 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4310 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4311 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4312 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4313 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4314 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4315 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4316 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4317 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4318 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4319 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4320 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4321 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4322 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4323 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4324 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4325 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4326 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4327 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4328 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4329 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4330 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4331 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4332 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4333 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4334 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4335 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4336 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4337 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4338 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4339 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4340 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4341 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4342 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4343 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4344 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4345 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4346 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4347 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4348 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4349 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4350 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4351 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4352 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4353 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4354 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4355 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4356 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4357 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4358 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4359 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4360 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4361 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4362 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4363 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4364 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4365 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4366 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4367 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4368 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4369 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4370 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4371 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4372 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4373 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4374 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4375 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4376 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4377 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4378 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4379 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4380 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4381 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4382 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4383 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4384 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4385 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4386 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4387 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4388 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4389 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4390 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4391 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4392 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4393 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4394 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4395 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4396 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4397 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4398 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4399 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4400 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4401 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4402 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4403 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4404 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4405 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4406 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4407 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4408 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4409 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4410 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4411 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4412 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4413 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4414 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4415 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4416 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4417 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4418 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4419 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4420 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4421 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4422 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4423 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4424 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4425 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4426 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4427 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4428 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4429 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4430 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4431 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4432 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4433 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4434 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4435 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4436 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4437 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4438 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4439 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4440 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4441 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4442 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4443 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4444 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4445 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4446 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4447 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4448 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4449 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4450 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4451 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4452 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4453 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4454 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4455 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4456 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4457 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4458 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4459 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4460 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4461 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4462 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4463 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4464 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4465 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4466 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4467 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4468 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4469 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4470 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4471 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4472 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4473 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4474 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4475 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4476 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4477 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4478 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4479 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4480 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4481 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4482 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4483 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4484 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4485 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4486 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4487 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4488 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4489 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4490 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4491 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4492 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4493 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4494 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4495 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4496 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4497 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4498 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4499 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4500 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4501 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4502 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4503 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4504 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4505 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4506 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4507 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4508 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4509 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4510 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4511 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4512 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4513 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4514 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4515 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4516 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4517 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4518 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4519 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4520 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4521 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4522 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4523 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4524 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4525 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4526 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4527 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4528 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4529 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4530 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4531 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4532 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4533 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4534 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4535 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4536 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4537 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4538 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4539 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4540 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4541 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4542 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4543 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4544 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4545 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4546 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4547 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4548 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4549 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4550 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4551 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4552 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4553 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4554 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4555 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4556 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4557 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4558 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4559 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4560 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4561 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4562 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4563 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4564 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4565 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4566 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4567 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4568 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4569 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4570 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4571 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4572 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4573 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4574 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4575 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4576 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4577 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4578 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4579 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4580 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4581 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4582 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4583 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4584 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4585 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4586 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4587 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4588 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4589 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4590 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4591 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4592 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4593 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4594 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4595 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4596 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4597 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4598 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4599 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4600 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4601 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4602 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4603 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4604 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4605 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4606 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4607 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4608 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4609 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4610 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4611 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4612 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4613 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4614 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4615 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4616 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4617 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4618 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4619 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4620 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4621 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4622 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4623 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4624 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4625 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4626 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4627 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4628 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4629 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4630 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4631 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4632 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4633 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4634 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4635 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4636 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4637 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4638 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4639 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4640 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4641 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4642 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4643 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4644 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4645 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4646 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4647 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4648 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4649 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4650 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4651 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4652 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4653 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4654 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4655 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4656 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4657 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4658 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4659 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4660 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4661 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4662 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4663 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4664 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4665 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4666 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4667 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4668 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4669 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4670 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4671 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4672 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4673 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4674 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4675 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4676 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4677 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4678 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4679 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4680 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4681 
4682 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4683 {
4684     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4685     BOOL ret;
4686     BYTE *buf = NULL;
4687     DWORD size = 0, i;
4688 
4689     for (i = 0; i < ARRAY_SIZE(corruptCRLs); i++)
4690     {
4691         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4692          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4693          &buf, &size);
4694         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4695          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4696          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4697          GetLastError());
4698     }
4699     /* at a minimum, a CRL must contain an issuer: */
4700     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4701      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4702      &buf, &size);
4703     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4704     if (ret)
4705     {
4706         CRL_INFO *info = (CRL_INFO *)buf;
4707 
4708         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4709         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4710          info->cCRLEntry);
4711         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4712          "Wrong issuer size %d\n", info->Issuer.cbData);
4713         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4714          "Unexpected issuer\n");
4715         LocalFree(buf);
4716     }
4717     /* check decoding with an empty CRL entry */
4718     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4719      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4720      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4721     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4722      GetLastError() == OSS_DATA_ERROR /* Win9x */ ||
4723      GetLastError() == CRYPT_E_BAD_ENCODE /* Win8 */),
4724      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4725      GetLastError());
4726     /* with a real CRL entry */
4727     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4728      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4729      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4730     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4731     if (ret)
4732     {
4733         CRL_INFO *info = (CRL_INFO *)buf;
4734         CRL_ENTRY *entry;
4735 
4736         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4737         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4738          info->cCRLEntry);
4739         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4740         entry = info->rgCRLEntry;
4741         ok(entry->SerialNumber.cbData == 1,
4742          "Expected serial number size 1, got %d\n",
4743          entry->SerialNumber.cbData);
4744         ok(*entry->SerialNumber.pbData == *serialNum,
4745          "Expected serial number %d, got %d\n", *serialNum,
4746          *entry->SerialNumber.pbData);
4747         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4748          "Wrong issuer size %d\n", info->Issuer.cbData);
4749         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4750          "Unexpected issuer\n");
4751         LocalFree(buf);
4752     }
4753     /* a real CRL from verisign that has extensions */
4754     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4755      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4756      NULL, &buf, &size);
4757     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4758     if (ret)
4759     {
4760         CRL_INFO *info = (CRL_INFO *)buf;
4761 
4762         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4763         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4764          info->cCRLEntry);
4765         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4766         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4767          info->cExtension);
4768         LocalFree(buf);
4769     }
4770     /* another real CRL from verisign that has lots of entries */
4771     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4772      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4773      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4774     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4775     if (ret)
4776     {
4777         CRL_INFO *info = (CRL_INFO *)buf;
4778 
4779         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4780         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4781          info->cCRLEntry);
4782         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4783          info->cExtension);
4784         LocalFree(buf);
4785     }
4786     /* and finally, with an extension */
4787     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4788      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4789      NULL, &buf, &size);
4790     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4791     if (ret)
4792     {
4793         CRL_INFO *info = (CRL_INFO *)buf;
4794         CRL_ENTRY *entry;
4795 
4796         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4797         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4798          info->cCRLEntry);
4799         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4800         entry = info->rgCRLEntry;
4801         ok(entry->SerialNumber.cbData == 1,
4802          "Expected serial number size 1, got %d\n",
4803          entry->SerialNumber.cbData);
4804         ok(*entry->SerialNumber.pbData == *serialNum,
4805          "Expected serial number %d, got %d\n", *serialNum,
4806          *entry->SerialNumber.pbData);
4807         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4808          "Wrong issuer size %d\n", info->Issuer.cbData);
4809         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4810          "Unexpected issuer\n");
4811         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4812          info->cExtension);
4813         LocalFree(buf);
4814     }
4815     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4816      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4817      NULL, &buf, &size);
4818     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4819     if (ret)
4820     {
4821         CRL_INFO *info = (CRL_INFO *)buf;
4822 
4823         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4824          info->cExtension);
4825         LocalFree(buf);
4826     }
4827 }
4828 
4829 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4830  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4831 static const BYTE encodedUsage[] = {
4832  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4833  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4834  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4835 
4836 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4837 {
4838     BOOL ret;
4839     BYTE *buf = NULL;
4840     DWORD size = 0;
4841     CERT_ENHKEY_USAGE usage;
4842 
4843     /* Test with empty usage */
4844     usage.cUsageIdentifier = 0;
4845     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4846      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4847     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4848     if (ret)
4849     {
4850         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4851         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4852         LocalFree(buf);
4853     }
4854     /* Test with a few usages */
4855     usage.cUsageIdentifier = ARRAY_SIZE(keyUsages);
4856     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4857     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4858      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4859     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4860     if (ret)
4861     {
4862         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4863         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4864         LocalFree(buf);
4865     }
4866 }
4867 
4868 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4869 {
4870     BOOL ret;
4871     LPBYTE buf = NULL;
4872     DWORD size = 0;
4873 
4874     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4875      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4876      &buf, &size);
4877     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4878     if (ret)
4879     {
4880         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4881 
4882         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4883          "Wrong size %d\n", size);
4884         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4885          usage->cUsageIdentifier);
4886         LocalFree(buf);
4887     }
4888     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4889      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4890      &buf, &size);
4891     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4892     if (ret)
4893     {
4894         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4895         DWORD i;
4896 
4897         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4898          "Wrong size %d\n", size);
4899         ok(usage->cUsageIdentifier == ARRAY_SIZE(keyUsages),
4900            "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4901         for (i = 0; i < usage->cUsageIdentifier; i++)
4902             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4903              "Expected OID %s, got %s\n", keyUsages[i],
4904              usage->rgpszUsageIdentifier[i]);
4905         LocalFree(buf);
4906     }
4907     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4908      encodedUsage, sizeof(encodedUsage), 0, NULL, NULL, &size);
4909     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4910     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4911     if (buf)
4912     {
4913         ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4914          encodedUsage, sizeof(encodedUsage), 0, NULL, buf, &size);
4915         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4916         HeapFree(GetProcessHeap(), 0, buf);
4917     }
4918 }
4919 
4920 static BYTE keyId[] = { 1,2,3,4 };
4921 static const BYTE authorityKeyIdWithId[] = {
4922  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4923 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4924  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4925  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4926 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4927 
4928 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4929 {
4930     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4931     BOOL ret;
4932     BYTE *buf = NULL;
4933     DWORD size = 0;
4934 
4935     /* Test with empty id */
4936     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4937      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4938     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4939     if (ret)
4940     {
4941         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4942         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4943         LocalFree(buf);
4944     }
4945     /* With just a key id */
4946     info.KeyId.cbData = sizeof(keyId);
4947     info.KeyId.pbData = keyId;
4948     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4949      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4950     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4951     if (ret)
4952     {
4953         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4954         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4955         LocalFree(buf);
4956     }
4957     /* With just an issuer */
4958     info.KeyId.cbData = 0;
4959     info.CertIssuer.cbData = sizeof(encodedCommonName);
4960     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4961     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4962      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4963     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4964     if (ret)
4965     {
4966         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4967          size);
4968         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4969         LocalFree(buf);
4970     }
4971     /* With just a serial number */
4972     info.CertIssuer.cbData = 0;
4973     info.CertSerialNumber.cbData = sizeof(serialNum);
4974     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4975     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4976      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4977     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4978     if (ret)
4979     {
4980         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4981          size);
4982         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4983         LocalFree(buf);
4984     }
4985 }
4986 
4987 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4988 {
4989     BOOL ret;
4990     LPBYTE buf = NULL;
4991     DWORD size = 0;
4992 
4993     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4994      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4995      &buf, &size);
4996     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4997     if (ret)
4998     {
4999         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
5000 
5001         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
5002          size);
5003         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5004         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
5005         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
5006         LocalFree(buf);
5007     }
5008     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
5009      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5010      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5011     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5012     if (ret)
5013     {
5014         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
5015 
5016         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
5017          size);
5018         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5019         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5020          "Unexpected key id\n");
5021         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
5022         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
5023         LocalFree(buf);
5024     }
5025     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
5026      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
5027      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5028     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5029     if (ret)
5030     {
5031         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
5032 
5033         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
5034          size);
5035         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5036         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
5037          "Unexpected issuer len\n");
5038         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
5039          sizeof(encodedCommonName)), "Unexpected issuer\n");
5040         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
5041         LocalFree(buf);
5042     }
5043     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
5044      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5045      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5046     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5047     if (ret)
5048     {
5049         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
5050 
5051         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
5052          size);
5053         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5054         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
5055         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
5056          "Unexpected serial number len\n");
5057         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
5058          "Unexpected serial number\n");
5059         LocalFree(buf);
5060     }
5061 }
5062 
5063 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
5064  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
5065  0x6f,0x72,0x67 };
5066 
5067 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
5068 {
5069     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
5070     CERT_ALT_NAME_ENTRY entry = { 0 };
5071     BOOL ret;
5072     BYTE *buf = NULL;
5073     DWORD size = 0;
5074 
5075     /* Test with empty id */
5076     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5077      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5078     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5079     if (ret)
5080     {
5081         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
5082         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
5083         LocalFree(buf);
5084     }
5085     /* With just a key id */
5086     info.KeyId.cbData = sizeof(keyId);
5087     info.KeyId.pbData = keyId;
5088     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5089      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5090     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5091     if (ret)
5092     {
5093         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
5094          size);
5095         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
5096         LocalFree(buf);
5097     }
5098     /* With a bogus issuer name */
5099     info.KeyId.cbData = 0;
5100     info.AuthorityCertIssuer.cAltEntry = 1;
5101     info.AuthorityCertIssuer.rgAltEntry = &entry;
5102     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5103      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5104     ok(!ret && GetLastError() == E_INVALIDARG,
5105      "Expected E_INVALIDARG, got %08x\n", GetLastError());
5106     /* With an issuer name */
5107     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
5108     U(entry).pwszURL = (LPWSTR)url;
5109     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5110      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5111     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5112     if (ret)
5113     {
5114         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
5115          size);
5116         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
5117          "Unexpected value\n");
5118         LocalFree(buf);
5119     }
5120     /* With just a serial number */
5121     info.AuthorityCertIssuer.cAltEntry = 0;
5122     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
5123     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
5124     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5125      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5126     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5127     if (ret)
5128     {
5129         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
5130          size);
5131         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
5132         LocalFree(buf);
5133     }
5134 }
5135 
5136 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
5137 {
5138     BOOL ret;
5139     LPBYTE buf = NULL;
5140     DWORD size = 0;
5141 
5142     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5143      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5144      &buf, &size);
5145     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5146     if (ret)
5147     {
5148         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5149 
5150         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5151          size);
5152         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5153         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5154          "Expected no issuer name entries\n");
5155         ok(info->AuthorityCertSerialNumber.cbData == 0,
5156          "Expected no serial number\n");
5157         LocalFree(buf);
5158     }
5159     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5160      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5161      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5162     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5163     if (ret)
5164     {
5165         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5166 
5167         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5168          size);
5169         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5170         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5171          "Unexpected key id\n");
5172         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5173          "Expected no issuer name entries\n");
5174         ok(info->AuthorityCertSerialNumber.cbData == 0,
5175          "Expected no serial number\n");
5176         LocalFree(buf);
5177     }
5178     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5179      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5180      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5181     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5182     if (ret)
5183     {
5184         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5185 
5186         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5187          size);
5188         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5189         ok(info->AuthorityCertIssuer.cAltEntry == 1,
5190          "Expected 1 issuer entry, got %d\n",
5191          info->AuthorityCertIssuer.cAltEntry);
5192         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5193          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5194          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5195         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5196          url), "Unexpected URL\n");
5197         ok(info->AuthorityCertSerialNumber.cbData == 0,
5198          "Expected no serial number\n");
5199         LocalFree(buf);
5200     }
5201     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5202      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5203      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5204     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5205     if (ret)
5206     {
5207         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5208 
5209         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5210          size);
5211         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5212         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5213          "Expected no issuer name entries\n");
5214         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5215          "Unexpected serial number len\n");
5216         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5217          sizeof(serialNum)), "Unexpected serial number\n");
5218         LocalFree(buf);
5219     }
5220 }
5221 
5222 static const BYTE authorityInfoAccessWithUrl[] = {
5223 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5224 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5225 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5226 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5227 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5228 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5229 
5230 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5231 {
5232     static char oid1[] = "1.2.3";
5233     static char oid2[] = "1.5.6";
5234     BOOL ret;
5235     BYTE *buf = NULL;
5236     DWORD size = 0;
5237     CERT_ACCESS_DESCRIPTION accessDescription[2];
5238     CERT_AUTHORITY_INFO_ACCESS aia;
5239 
5240     memset(accessDescription, 0, sizeof(accessDescription));
5241     aia.cAccDescr = 0;
5242     aia.rgAccDescr = NULL;
5243     /* Having no access descriptions is allowed */
5244     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5245      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5246     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5247     if (ret)
5248     {
5249         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5250         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5251         LocalFree(buf);
5252         buf = NULL;
5253     }
5254     /* It can't have an empty access method */
5255     aia.cAccDescr = 1;
5256     aia.rgAccDescr = accessDescription;
5257     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5258      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5259     ok(!ret && (GetLastError() == E_INVALIDARG ||
5260      GetLastError() == OSS_LIMITED /* Win9x */),
5261      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5262     /* It can't have an empty location */
5263     accessDescription[0].pszAccessMethod = oid1;
5264     SetLastError(0xdeadbeef);
5265     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5266      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5267     ok(!ret && GetLastError() == E_INVALIDARG,
5268      "expected E_INVALIDARG, got %08x\n", GetLastError());
5269     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5270     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5271     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5272      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5273     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5274     if (ret)
5275     {
5276         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5277          size);
5278         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5279          "unexpected value\n");
5280         LocalFree(buf);
5281         buf = NULL;
5282     }
5283     accessDescription[1].pszAccessMethod = oid2;
5284     accessDescription[1].AccessLocation.dwAltNameChoice =
5285      CERT_ALT_NAME_IP_ADDRESS;
5286     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5287      sizeof(encodedIPAddr);
5288     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5289      (LPBYTE)encodedIPAddr;
5290     aia.cAccDescr = 2;
5291     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5292      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5293     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5294     if (ret)
5295     {
5296         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5297          "unexpected size %d\n", size);
5298         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5299          "unexpected value\n");
5300         LocalFree(buf);
5301         buf = NULL;
5302     }
5303 }
5304 
5305 static void compareAuthorityInfoAccess(LPCSTR header,
5306  const CERT_AUTHORITY_INFO_ACCESS *expected,
5307  const CERT_AUTHORITY_INFO_ACCESS *got)
5308 {
5309     DWORD i;
5310 
5311     ok(expected->cAccDescr == got->cAccDescr,
5312      "%s: expected %d access descriptions, got %d\n", header,
5313      expected->cAccDescr, got->cAccDescr);
5314     for (i = 0; i < expected->cAccDescr; i++)
5315     {
5316         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5317          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5318          header, i, expected->rgAccDescr[i].pszAccessMethod,
5319          got->rgAccDescr[i].pszAccessMethod);
5320         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5321          &got->rgAccDescr[i].AccessLocation);
5322     }
5323 }
5324 
5325 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5326 {
5327     static char oid1[] = "1.2.3";
5328     static char oid2[] = "1.5.6";
5329     BOOL ret;
5330     LPBYTE buf = NULL;
5331     DWORD size = 0;
5332 
5333     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5334      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5335      &buf, &size);
5336     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5337     if (ret)
5338     {
5339         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5340 
5341         compareAuthorityInfoAccess("empty AIA", &aia,
5342          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5343         LocalFree(buf);
5344         buf = NULL;
5345     }
5346     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5347      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5348      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5349     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5350     if (ret)
5351     {
5352         CERT_ACCESS_DESCRIPTION accessDescription;
5353         CERT_AUTHORITY_INFO_ACCESS aia;
5354 
5355         accessDescription.pszAccessMethod = oid1;
5356         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5357         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5358         aia.cAccDescr = 1;
5359         aia.rgAccDescr = &accessDescription;
5360         compareAuthorityInfoAccess("AIA with URL", &aia,
5361          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5362         LocalFree(buf);
5363         buf = NULL;
5364     }
5365     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5366      authorityInfoAccessWithUrlAndIPAddr,
5367      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5368      NULL, &buf, &size);
5369     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5370     if (ret)
5371     {
5372         CERT_ACCESS_DESCRIPTION accessDescription[2];
5373         CERT_AUTHORITY_INFO_ACCESS aia;
5374 
5375         accessDescription[0].pszAccessMethod = oid1;
5376         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5377         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5378         accessDescription[1].pszAccessMethod = oid2;
5379         accessDescription[1].AccessLocation.dwAltNameChoice =
5380          CERT_ALT_NAME_IP_ADDRESS;
5381         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5382          sizeof(encodedIPAddr);
5383         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5384          (LPBYTE)encodedIPAddr;
5385         aia.cAccDescr = 2;
5386         aia.rgAccDescr = accessDescription;
5387         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5388          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5389         LocalFree(buf);
5390         buf = NULL;
5391     }
5392     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5393      authorityInfoAccessWithUrlAndIPAddr,
5394      sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, NULL, &size);
5395     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5396     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
5397     if (buf)
5398     {
5399         ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5400          authorityInfoAccessWithUrlAndIPAddr,
5401          sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, buf, &size);
5402         ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5403         HeapFree(GetProcessHeap(), 0, buf);
5404     }
5405 }
5406 
5407 static const BYTE emptyCTL[] = {
5408 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5409 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5410 static const BYTE emptyCTLWithVersion1[] = {
5411 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5412 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5413 static const BYTE ctlWithUsageIdentifier[] = {
5414 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5415 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5416 static const BYTE ctlWithListIdentifier[] = {
5417 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5418 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5419 static const BYTE ctlWithSequenceNumber[] = {
5420 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5421 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5422 static const BYTE ctlWithThisUpdate[] = {
5423 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5424 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5425 static const BYTE ctlWithThisAndNextUpdate[] = {
5426 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5427 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5428 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5429 static const BYTE ctlWithAlgId[] = {
5430 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5431 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5432 static const BYTE ctlWithBogusEntry[] = {
5433 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5434 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5435 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5436 static const BYTE ctlWithOneEntry[] = {
5437 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5438 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5439 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5440 static const BYTE ctlWithTwoEntries[] = {
5441 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5442 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5443 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5444 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5445 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5446 
5447 static void test_encodeCTL(DWORD dwEncoding)
5448 {
5449     static char oid1[] = "1.2.3";
5450     static char oid2[] = "1.5.6";
5451     char *pOid1 = oid1;
5452     BOOL ret;
5453     BYTE *buf = NULL;
5454     DWORD size = 0;
5455     CTL_INFO info;
5456     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5457     CTL_ENTRY ctlEntry[2];
5458     CRYPT_ATTRIBUTE attr1, attr2;
5459     CRYPT_ATTR_BLOB value1, value2;
5460 
5461     memset(&info, 0, sizeof(info));
5462     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5463      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5464     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5465     if (ret)
5466     {
5467         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5468         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5469         LocalFree(buf);
5470         buf = NULL;
5471     }
5472     info.dwVersion = 1;
5473     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5474      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5475     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5476     if (ret)
5477     {
5478         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5479         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5480         LocalFree(buf);
5481         buf = NULL;
5482     }
5483     info.dwVersion = 0;
5484     info.SubjectUsage.cUsageIdentifier = 1;
5485     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5486     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5487      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5488     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5489     if (ret)
5490     {
5491         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5492          size);
5493         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5494         LocalFree(buf);
5495         buf = NULL;
5496     }
5497     info.SubjectUsage.cUsageIdentifier = 0;
5498     info.ListIdentifier.cbData = sizeof(serialNum);
5499     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5500     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5501      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5502     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5503     if (ret)
5504     {
5505         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5506         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5507         LocalFree(buf);
5508         buf = NULL;
5509     }
5510     info.ListIdentifier.cbData = 0;
5511     info.SequenceNumber.cbData = sizeof(serialNum);
5512     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5513     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5514      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5515     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5516     if (ret)
5517     {
5518         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5519          size);
5520         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5521         LocalFree(buf);
5522         buf = NULL;
5523     }
5524     info.SequenceNumber.cbData = 0;
5525     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5526     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5527      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5528     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5529     if (ret)
5530     {
5531         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5532         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5533         LocalFree(buf);
5534         buf = NULL;
5535     }
5536     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5537     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5538      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5539     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5540     if (ret)
5541     {
5542         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5543          size);
5544         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5545         LocalFree(buf);
5546         buf = NULL;
5547     }
5548     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5549     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5550     info.SubjectAlgorithm.pszObjId = oid2;
5551     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5552      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5553     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5554     if (ret)
5555     {
5556         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5557         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5558         LocalFree(buf);
5559         buf = NULL;
5560     }
5561     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5562      * (see tests below) but it'll encode fine.
5563      */
5564     info.SubjectAlgorithm.pszObjId = NULL;
5565     value1.cbData = sizeof(serialNum);
5566     value1.pbData = (LPBYTE)serialNum;
5567     attr1.pszObjId = oid1;
5568     attr1.cValue = 1;
5569     attr1.rgValue = &value1;
5570     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5571     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5572     ctlEntry[0].cAttribute = 1;
5573     ctlEntry[0].rgAttribute = &attr1;
5574     info.cCTLEntry = 1;
5575     info.rgCTLEntry = ctlEntry;
5576     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5577      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5578     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5579     if (ret)
5580     {
5581         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5582         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5583         LocalFree(buf);
5584         buf = NULL;
5585     }
5586     value1.cbData = sizeof(emptySequence);
5587     value1.pbData = (LPBYTE)emptySequence;
5588     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5589      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5590     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5591     if (ret)
5592     {
5593         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5594         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5595         LocalFree(buf);
5596         buf = NULL;
5597     }
5598     value2.cbData = sizeof(encodedIPAddr);
5599     value2.pbData = (LPBYTE)encodedIPAddr;
5600     attr2.pszObjId = oid2;
5601     attr2.cValue = 1;
5602     attr2.rgValue = &value2;
5603     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5604     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5605     ctlEntry[1].cAttribute = 1;
5606     ctlEntry[1].rgAttribute = &attr2;
5607     info.cCTLEntry = 2;
5608     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5609      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5610     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5611     if (ret)
5612     {
5613         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5614         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5615         LocalFree(buf);
5616         buf = NULL;
5617     }
5618 }
5619 
5620 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5621  const CTL_INFO *got)
5622 {
5623     DWORD i, j, k;
5624 
5625     ok(expected->dwVersion == got->dwVersion,
5626      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5627      got->dwVersion);
5628     ok(expected->SubjectUsage.cUsageIdentifier ==
5629      got->SubjectUsage.cUsageIdentifier,
5630      "%s: expected %d usage identifiers, got %d\n", header,
5631      expected->SubjectUsage.cUsageIdentifier,
5632      got->SubjectUsage.cUsageIdentifier);
5633     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5634         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5635          got->SubjectUsage.rgpszUsageIdentifier[i]),
5636          "%s[%d]: expected %s, got %s\n", header, i,
5637          expected->SubjectUsage.rgpszUsageIdentifier[i],
5638          got->SubjectUsage.rgpszUsageIdentifier[i]);
5639     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5640      "%s: expected list identifier of %d bytes, got %d\n", header,
5641      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5642     if (expected->ListIdentifier.cbData)
5643         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5644          expected->ListIdentifier.cbData),
5645          "%s: unexpected list identifier value\n", header);
5646     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5647      "%s: expected sequence number of %d bytes, got %d\n", header,
5648      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5649     if (expected->SequenceNumber.cbData)
5650         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5651          expected->SequenceNumber.cbData),
5652          "%s: unexpected sequence number value\n", header);
5653     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5654      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5655      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5656      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5657     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5658      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5659      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5660      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5661     if (expected->SubjectAlgorithm.pszObjId &&
5662      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5663         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5664          expected->SubjectAlgorithm.pszObjId);
5665     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5666         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5667          got->SubjectAlgorithm.pszObjId),
5668          "%s: expected subject algorithm %s, got %s\n", header,
5669          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5670     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5671      got->SubjectAlgorithm.Parameters.cbData,
5672      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5673      expected->SubjectAlgorithm.Parameters.cbData,
5674      got->SubjectAlgorithm.Parameters.cbData);
5675     if (expected->SubjectAlgorithm.Parameters.cbData)
5676         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5677          got->SubjectAlgorithm.Parameters.pbData,
5678          expected->SubjectAlgorithm.Parameters.cbData),
5679          "%s: unexpected subject algorithm parameter value\n", header);
5680     ok(expected->cCTLEntry == got->cCTLEntry,
5681      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5682      got->cCTLEntry);
5683     for (i = 0; i < expected->cCTLEntry; i++)
5684     {
5685         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5686          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5687          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5688          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5689          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5690         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5691             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5692              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5693              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5694              "%s[%d]: unexpected subject identifier value\n",
5695              header, i);
5696         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5697         {
5698             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5699              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5700              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5701              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5702              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5703             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5704             {
5705                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5706                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5707                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5708                  header, i, j, k,
5709                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5710                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5711                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5712                     ok(!memcmp(
5713                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5714                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5715                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5716                      "%s[%d][%d][%d]: unexpected value\n",
5717                      header, i, j, k);
5718             }
5719         }
5720     }
5721     ok(expected->cExtension == got->cExtension,
5722      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5723      got->cExtension);
5724     for (i = 0; i < expected->cExtension; i++)
5725     {
5726         ok(!strcmp(expected->rgExtension[i].pszObjId,
5727          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5728          header, i, expected->rgExtension[i].pszObjId,
5729          got->rgExtension[i].pszObjId);
5730         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5731          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5732          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5733         ok(expected->rgExtension[i].Value.cbData ==
5734          got->rgExtension[i].Value.cbData,
5735          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5736          header, i, expected->rgExtension[i].Value.cbData,
5737          got->rgExtension[i].Value.cbData);
5738         if (expected->rgExtension[i].Value.cbData)
5739             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5740              got->rgExtension[i].Value.pbData,
5741              expected->rgExtension[i].Value.cbData),
5742              "%s[%d]: unexpected extension value\n", header, i);
5743     }
5744 }
5745 
5746 static const BYTE signedCTL[] = {
5747 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5748 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5749 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5750 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5751 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5752 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5753 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5754 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5755 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5756 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5757 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5758 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5759 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5760 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5761 static const BYTE signedCTLWithCTLInnerContent[] = {
5762 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5763 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5764 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5765 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5766 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5767 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5768 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5769 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5770 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5771 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5772 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5773 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5774 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5775 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5776 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5777 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5778 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5779 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5780 0x57,0x6c,0x0b,0x47,0xb8 };
5781 
5782 static void test_decodeCTL(DWORD dwEncoding)
5783 {
5784     static char oid1[] = "1.2.3";
5785     static char oid2[] = "1.5.6";
5786     static BYTE nullData[] = { 5,0 };
5787     char *pOid1 = oid1;
5788     BOOL ret;
5789     BYTE *buf = NULL;
5790     DWORD size = 0;
5791     CTL_INFO info;
5792     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5793     CTL_ENTRY ctlEntry[2];
5794     CRYPT_ATTRIBUTE attr1, attr2;
5795     CRYPT_ATTR_BLOB value1, value2;
5796 
5797     memset(&info, 0, sizeof(info));
5798     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5799      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5800     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5801     if (ret)
5802     {
5803         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5804         LocalFree(buf);
5805         buf = NULL;
5806     }
5807     info.dwVersion = 1;
5808     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5809      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5810      &size);
5811     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5812     if (ret)
5813     {
5814         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5815         LocalFree(buf);
5816         buf = NULL;
5817     }
5818     info.dwVersion = 0;
5819     info.SubjectUsage.cUsageIdentifier = 1;
5820     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5821     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5822      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5823      &buf, &size);
5824     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5825     if (ret)
5826     {
5827         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5828         LocalFree(buf);
5829         buf = NULL;
5830     }
5831     info.SubjectUsage.cUsageIdentifier = 0;
5832     info.ListIdentifier.cbData = sizeof(serialNum);
5833     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5834     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5835      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5836     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5837     if (ret)
5838     {
5839         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5840         LocalFree(buf);
5841         buf = NULL;
5842     }
5843     info.ListIdentifier.cbData = 0;
5844     info.SequenceNumber.cbData = sizeof(serialNum);
5845     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5846     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5847      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5848     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5849     if (ret)
5850     {
5851         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5852         LocalFree(buf);
5853         buf = NULL;
5854     }
5855     info.SequenceNumber.cbData = 0;
5856     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5857     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5858      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5859     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5860     if (ret)
5861     {
5862         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5863         LocalFree(buf);
5864         buf = NULL;
5865     }
5866     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5867     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5868      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5869      &buf, &size);
5870     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5871     if (ret)
5872     {
5873         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5874         LocalFree(buf);
5875         buf = NULL;
5876     }
5877     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5878     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5879     info.SubjectAlgorithm.pszObjId = oid2;
5880     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5881     info.SubjectAlgorithm.Parameters.pbData = nullData;
5882     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5883      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5884     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5885     if (ret)
5886     {
5887         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5888         LocalFree(buf);
5889         buf = NULL;
5890     }
5891     SetLastError(0xdeadbeef);
5892     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5893      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5894     ok(!ret &&
5895      (GetLastError() == CRYPT_E_ASN1_EOD ||
5896       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5897       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5898      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5899      GetLastError());
5900     info.SubjectAlgorithm.Parameters.cbData = 0;
5901     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5902     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5903     info.SubjectAlgorithm.pszObjId = NULL;
5904     value1.cbData = sizeof(emptySequence);
5905     value1.pbData = (LPBYTE)emptySequence;
5906     attr1.pszObjId = oid1;
5907     attr1.cValue = 1;
5908     attr1.rgValue = &value1;
5909     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5910     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5911     ctlEntry[0].cAttribute = 1;
5912     ctlEntry[0].rgAttribute = &attr1;
5913     info.cCTLEntry = 1;
5914     info.rgCTLEntry = ctlEntry;
5915     SetLastError(0xdeadbeef);
5916     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5917      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5918     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5919     if (ret)
5920     {
5921         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5922         LocalFree(buf);
5923         buf = NULL;
5924     }
5925     value2.cbData = sizeof(encodedIPAddr);
5926     value2.pbData = (LPBYTE)encodedIPAddr;
5927     attr2.pszObjId = oid2;
5928     attr2.cValue = 1;
5929     attr2.rgValue = &value2;
5930     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5931     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5932     ctlEntry[1].cAttribute = 1;
5933     ctlEntry[1].rgAttribute = &attr2;
5934     info.cCTLEntry = 2;
5935     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5936      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5937     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5938     if (ret)
5939     {
5940         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5941         LocalFree(buf);
5942         buf = NULL;
5943     }
5944     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5945     SetLastError(0xdeadbeef);
5946     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5947      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5948     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5949      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5950      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5951      GetLastError());
5952     SetLastError(0xdeadbeef);
5953     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5954      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5955      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5956     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5957      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5958      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5959      GetLastError());
5960 }
5961 
5962 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5963 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5964  0x03,0,0,0,0,0,0 };
5965 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5966  0xa0,0x01,0x01 };
5967 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5968  0x03,0x02,0x01,0x01 };
5969 static BYTE bogusDER[] = { 1 };
5970 
5971 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5972 {
5973     BOOL ret;
5974     BYTE *buf = NULL;
5975     DWORD size = 0;
5976     CRYPT_CONTENT_INFO info = { 0 };
5977     char oid1[] = "1.2.3";
5978 
5979     if (0)
5980     {
5981         /* Crashes on win9x */
5982         SetLastError(0xdeadbeef);
5983         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5984          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5985         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5986          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5987     }
5988     SetLastError(0xdeadbeef);
5989     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5990      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5991     ok(!ret && (GetLastError() == E_INVALIDARG ||
5992      GetLastError() == OSS_LIMITED /* Win9x */),
5993      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5994     info.pszObjId = oid1;
5995     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5996      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5997     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5998     if (ret)
5999     {
6000         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
6001         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
6002         LocalFree(buf);
6003     }
6004     info.Content.pbData = bogusDER;
6005     info.Content.cbData = sizeof(bogusDER);
6006     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
6007      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6008     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
6009     if (ret)
6010     {
6011         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
6012         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
6013         LocalFree(buf);
6014     }
6015     info.Content.pbData = (BYTE *)ints[0].encoded;
6016     info.Content.cbData = ints[0].encoded[1] + 2;
6017     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
6018      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6019     if (ret)
6020     {
6021         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
6022         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
6023         LocalFree(buf);
6024     }
6025 }
6026 
6027 static const BYTE indefiniteSignedPKCSContent[] = {
6028 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
6029 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
6030 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
6031 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
6032 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
6033 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
6034 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6035 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
6036 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
6037 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
6038 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
6039 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
6040 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
6041 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
6042 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
6043 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
6044 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
6045 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
6046 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
6047 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
6048 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
6049 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
6050 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
6051 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
6052 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
6053 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
6054 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
6055 0x00,0x00,0x00,0x00,0x00,0x00 };
6056 
6057 static const BYTE content_abcd[] = {
6058     ASN_SEQUENCE, 0x80,
6059         ASN_OBJECTIDENTIFIER, 2, 42,3,
6060         ASN_CONTEXT|ASN_CONSTRUCTOR, 0x80,
6061             ASN_OCTETSTRING, 4, 'a','b','c','d',
6062         0,0,
6063     0,0,
6064 };
6065 
6066 static const BYTE encoded_abcd[] = {
6067     ASN_OCTETSTRING, 4, 'a','b','c','d',
6068 };
6069 
6070 static const BYTE content_constructed_abcd[] = {
6071     ASN_SEQUENCE, 0x80,
6072         ASN_OBJECTIDENTIFIER, 2, 42,3,
6073         ASN_CONTEXT|ASN_CONSTRUCTOR, 0x80,
6074             ASN_CONSTRUCTOR|ASN_OCTETSTRING,0x80,
6075                 ASN_OCTETSTRING, 4, 'a','b','0','0',
6076             0,0,
6077         0,0,
6078     0,0,
6079     1,2,3,4,5,6,7 /* extra garbage */
6080 };
6081 
6082 static void test_decodePKCSContentInfo(DWORD dwEncoding)
6083 {
6084     BOOL ret;
6085     LPBYTE buf = NULL;
6086     DWORD size = 0, i;
6087     CRYPT_CONTENT_INFO *info;
6088 
6089     const struct {
6090         const BYTE *encoded;
6091         UINT encoded_size;
6092         const char *obj_id;
6093         const BYTE *content;
6094         UINT content_size;
6095     } tests[] = {
6096         { emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
6097           "1.2.3", NULL, 0 },
6098         { emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
6099           "1.2.3", NULL, 0 },
6100         { intPKCSContentInfo, sizeof(intPKCSContentInfo),
6101           "1.2.3", ints[0].encoded, ints[0].encoded[1] + 2 },
6102         { indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
6103           "1.2.840.113549.1.7.2", NULL, 392 },
6104         { content_abcd, sizeof(content_abcd),
6105           "1.2.3", encoded_abcd, 6 },
6106         { content_constructed_abcd, sizeof(content_constructed_abcd),
6107           "1.2.3", content_constructed_abcd + 8, 10 }
6108     };
6109 
6110     for (i = 0; i < ARRAY_SIZE(tests); i++)
6111     {
6112         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, tests[i].encoded,
6113             tests[i].encoded_size, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6114         ok(ret, "[%u] CryptDecodeObjectEx failed: %x\n", i, GetLastError());
6115         if (!ret) continue;
6116 
6117         info = (CRYPT_CONTENT_INFO *)buf;
6118 
6119         ok(!strcmp(info->pszObjId, tests[i].obj_id), "[%u] Expected %s, got %s\n",
6120            i, tests[i].obj_id, info->pszObjId);
6121         ok(info->Content.cbData == tests[i].content_size,
6122            "[%u] Unexpected size %d expected %d\n", i, info->Content.cbData,
6123            tests[i].content_size);
6124         if (tests[i].content)
6125             ok(!memcmp(info->Content.pbData, tests[i].content, tests[i].content_size),
6126                "[%u] Unexpected value\n", i);
6127         LocalFree(buf);
6128     }
6129 
6130     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
6131      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
6132      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6133     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6134      * I doubt an app depends on that.
6135      */
6136     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6137      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
6138      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
6139      GetLastError());
6140 }
6141 
6142 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
6143  0x00 };
6144 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
6145  0x01 };
6146 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
6147  0x02,0x01,0x01 };
6148 
6149 static void test_encodePKCSAttribute(DWORD dwEncoding)
6150 {
6151     CRYPT_ATTRIBUTE attr = { 0 };
6152     BOOL ret;
6153     LPBYTE buf = NULL;
6154     DWORD size = 0;
6155     CRYPT_ATTR_BLOB blob;
6156     char oid[] = "1.2.3";
6157 
6158     if (0)
6159     {
6160         /* Crashes on win9x */
6161         SetLastError(0xdeadbeef);
6162         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
6163          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6164         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
6165          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
6166     }
6167     SetLastError(0xdeadbeef);
6168     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6169      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6170     ok(!ret && (GetLastError() == E_INVALIDARG ||
6171      GetLastError() == OSS_LIMITED /* Win9x */),
6172      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
6173     attr.pszObjId = oid;
6174     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6175      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6176     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6177     if (ret)
6178     {
6179         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
6180         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
6181         LocalFree(buf);
6182     }
6183     blob.cbData = sizeof(bogusDER);
6184     blob.pbData = bogusDER;
6185     attr.cValue = 1;
6186     attr.rgValue = &blob;
6187     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6188      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6189     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6190     if (ret)
6191     {
6192         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
6193         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6194         LocalFree(buf);
6195     }
6196     blob.pbData = (BYTE *)ints[0].encoded;
6197     blob.cbData = ints[0].encoded[1] + 2;
6198     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6199      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6200     if (ret)
6201     {
6202         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6203         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6204         LocalFree(buf);
6205     }
6206 }
6207 
6208 static void test_decodePKCSAttribute(DWORD dwEncoding)
6209 {
6210     BOOL ret;
6211     LPBYTE buf = NULL;
6212     DWORD size = 0;
6213     CRYPT_ATTRIBUTE *attr;
6214 
6215     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6216      emptyPKCSAttr, sizeof(emptyPKCSAttr),
6217      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6218     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6219     if (ret)
6220     {
6221         attr = (CRYPT_ATTRIBUTE *)buf;
6222 
6223         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6224          attr->pszObjId);
6225         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6226         LocalFree(buf);
6227     }
6228     SetLastError(0xdeadbeef);
6229     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6230      bogusPKCSAttr, sizeof(bogusPKCSAttr),
6231      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6232     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6233      * I doubt an app depends on that.
6234      */
6235     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6236      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6237      GetLastError() == OSS_MORE_INPUT /* Win9x */),
6238      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6239      GetLastError());
6240     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6241      intPKCSAttr, sizeof(intPKCSAttr),
6242      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6243     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6244     if (ret)
6245     {
6246         attr = (CRYPT_ATTRIBUTE *)buf;
6247 
6248         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6249          attr->pszObjId);
6250         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6251         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6252          "Unexpected size %d\n", attr->rgValue[0].cbData);
6253         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6254          attr->rgValue[0].cbData), "Unexpected value\n");
6255         LocalFree(buf);
6256     }
6257 }
6258 
6259 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6260 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6261  0x2a,0x03,0x31,0x00 };
6262 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6263  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6264 
6265 static void test_encodePKCSAttributes(DWORD dwEncoding)
6266 {
6267     CRYPT_ATTRIBUTES attributes = { 0 };
6268     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6269     CRYPT_ATTR_BLOB blob;
6270     BOOL ret;
6271     LPBYTE buf = NULL;
6272     DWORD size = 0;
6273     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6274 
6275     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6276      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6277     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6278     if (ret)
6279     {
6280         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6281         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6282         LocalFree(buf);
6283     }
6284     attributes.cAttr = 1;
6285     attributes.rgAttr = attr;
6286     SetLastError(0xdeadbeef);
6287     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6288      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6289     ok(!ret && (GetLastError() == E_INVALIDARG ||
6290      GetLastError() == OSS_LIMITED /* Win9x */),
6291      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6292     attr[0].pszObjId = oid1;
6293     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6294      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6295     if (ret)
6296     {
6297         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6298         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6299         LocalFree(buf);
6300     }
6301     attr[1].pszObjId = oid2;
6302     attr[1].cValue = 1;
6303     attr[1].rgValue = &blob;
6304     blob.pbData = (BYTE *)ints[0].encoded;
6305     blob.cbData = ints[0].encoded[1] + 2;
6306     attributes.cAttr = 2;
6307     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6308      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6309     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6310     if (ret)
6311     {
6312         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6313         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6314         LocalFree(buf);
6315     }
6316 }
6317 
6318 static void test_decodePKCSAttributes(DWORD dwEncoding)
6319 {
6320     BOOL ret;
6321     LPBYTE buf = NULL;
6322     DWORD size = 0;
6323     CRYPT_ATTRIBUTES *attributes;
6324 
6325     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6326      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6327      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6328     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6329     if (ret)
6330     {
6331         attributes = (CRYPT_ATTRIBUTES *)buf;
6332         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6333          attributes->cAttr);
6334         LocalFree(buf);
6335     }
6336     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6337      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6338      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6339     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6340     if (ret)
6341     {
6342         attributes = (CRYPT_ATTRIBUTES *)buf;
6343         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6344          attributes->cAttr);
6345         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6346          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6347         ok(attributes->rgAttr[0].cValue == 0,
6348          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6349         LocalFree(buf);
6350     }
6351     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6352      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6353      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6354     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6355     if (ret)
6356     {
6357         attributes = (CRYPT_ATTRIBUTES *)buf;
6358         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6359          attributes->cAttr);
6360         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6361          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6362         ok(attributes->rgAttr[0].cValue == 0,
6363          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6364         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6365          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6366         ok(attributes->rgAttr[1].cValue == 1,
6367          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6368         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6369          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6370         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6371          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6372         LocalFree(buf);
6373     }
6374     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6375      doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, NULL, &size);
6376     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6377     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6378     if (buf)
6379     {
6380         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6381          doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, buf, &size);
6382         ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6383         HeapFree(GetProcessHeap(), 0, buf);
6384     }
6385 }
6386 
6387 static const BYTE singleCapability[] = {
6388 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6389 static const BYTE twoCapabilities[] = {
6390 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6391 static const BYTE singleCapabilitywithNULL[] = {
6392 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6393 
6394 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6395 {
6396     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6397     BOOL ret;
6398     LPBYTE buf = NULL;
6399     DWORD size = 0;
6400     CRYPT_SMIME_CAPABILITY capability[2];
6401     CRYPT_SMIME_CAPABILITIES capabilities;
6402 
6403     /* An empty capabilities is allowed */
6404     capabilities.cCapability = 0;
6405     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6406      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6407     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6408     if (ret)
6409     {
6410         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6411         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6412         LocalFree(buf);
6413     }
6414     /* A non-empty capabilities with an empty capability (lacking an OID) is
6415      * not allowed
6416      */
6417     capability[0].pszObjId = NULL;
6418     capability[0].Parameters.cbData = 0;
6419     capabilities.cCapability = 1;
6420     capabilities.rgCapability = capability;
6421     SetLastError(0xdeadbeef);
6422     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6423      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6424     ok(!ret && (GetLastError() == E_INVALIDARG ||
6425      GetLastError() == OSS_LIMITED /* Win9x */),
6426      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6427     capability[0].pszObjId = oid1;
6428     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6429      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6430     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6431     if (ret)
6432     {
6433         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6434         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6435         LocalFree(buf);
6436     }
6437     capability[1].pszObjId = oid2;
6438     capability[1].Parameters.cbData = 0;
6439     capabilities.cCapability = 2;
6440     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6441      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6442     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6443     if (ret)
6444     {
6445         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6446         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6447         LocalFree(buf);
6448     }
6449 }
6450 
6451 static void compareSMimeCapabilities(LPCSTR header,
6452  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6453 {
6454     DWORD i;
6455 
6456     ok(got->cCapability == expected->cCapability,
6457      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6458      got->cCapability);
6459     for (i = 0; i < expected->cCapability; i++)
6460     {
6461         ok(!strcmp(expected->rgCapability[i].pszObjId,
6462          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6463          header, i, expected->rgCapability[i].pszObjId,
6464          got->rgCapability[i].pszObjId);
6465         ok(expected->rgCapability[i].Parameters.cbData ==
6466          got->rgCapability[i].Parameters.cbData,
6467          "%s[%d]: expected %d bytes, got %d\n", header, i,
6468          expected->rgCapability[i].Parameters.cbData,
6469          got->rgCapability[i].Parameters.cbData);
6470         if (expected->rgCapability[i].Parameters.cbData)
6471             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6472              got->rgCapability[i].Parameters.pbData,
6473              expected->rgCapability[i].Parameters.cbData),
6474              "%s[%d]: unexpected value\n", header, i);
6475     }
6476 }
6477 
6478 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6479 {
6480     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6481     BOOL ret;
6482     DWORD size = 0;
6483     CRYPT_SMIME_CAPABILITY capability[2];
6484     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6485 
6486     SetLastError(0xdeadbeef);
6487     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6488      emptySequence, sizeof(emptySequence),
6489      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6490     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6491     if (ret)
6492     {
6493         capabilities.cCapability = 0;
6494         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6495         LocalFree(ptr);
6496     }
6497     SetLastError(0xdeadbeef);
6498     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6499      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6500      &ptr, &size);
6501     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6502     if (ret)
6503     {
6504         capability[0].pszObjId = oid1;
6505         capability[0].Parameters.cbData = 0;
6506         capabilities.cCapability = 1;
6507         capabilities.rgCapability = capability;
6508         compareSMimeCapabilities("single capability", &capabilities, ptr);
6509         LocalFree(ptr);
6510     }
6511     SetLastError(0xdeadbeef);
6512     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6513      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6514      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6515     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6516     if (ret)
6517     {
6518         BYTE NULLparam[] = {0x05, 0x00};
6519         capability[0].pszObjId = oid1;
6520         capability[0].Parameters.cbData = 2;
6521         capability[0].Parameters.pbData = NULLparam;
6522         capabilities.cCapability = 1;
6523         capabilities.rgCapability = capability;
6524         compareSMimeCapabilities("single capability with NULL", &capabilities,
6525          ptr);
6526         LocalFree(ptr);
6527     }
6528     SetLastError(0xdeadbeef);
6529     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6530     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6531     &ptr, &size);
6532     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6533     if (ret)
6534     {
6535         capability[0].Parameters.cbData = 0;
6536         capability[1].pszObjId = oid2;
6537         capability[1].Parameters.cbData = 0;
6538         capabilities.cCapability = 2;
6539         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6540         LocalFree(ptr);
6541     }
6542     SetLastError(0xdeadbeef);
6543     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6544      twoCapabilities, sizeof(twoCapabilities), 0, NULL, NULL, &size);
6545     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6546     ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6547     if (ptr)
6548     {
6549         SetLastError(0xdeadbeef);
6550         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6551          twoCapabilities, sizeof(twoCapabilities), 0, NULL, ptr, &size);
6552         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6553         HeapFree(GetProcessHeap(), 0, ptr);
6554     }
6555 }
6556 
6557 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6558  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6559  0x67 };
6560 static const BYTE minimalPKCSSigner[] = {
6561  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6562  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6563  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6564 static const BYTE PKCSSignerWithSerial[] = {
6565  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6566  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6567  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6568  0x00 };
6569 static const BYTE PKCSSignerWithHashAlgo[] = {
6570  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6571  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6572  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6573  0x00,0x04,0x00 };
6574 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6575  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6576  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6577  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6578  0x06,0x05,0x00,0x04,0x00 };
6579 static const BYTE PKCSSignerWithHash[] = {
6580  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6581  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6582  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6583  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6584  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6585 static const BYTE PKCSSignerWithAuthAttr[] = {
6586 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6587 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6588 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6589 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6590 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6591 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6592 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6593 
6594 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6595 {
6596     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6597     BOOL ret;
6598     LPBYTE buf = NULL;
6599     DWORD size = 0;
6600     CMSG_SIGNER_INFO info = { 0 };
6601     char oid_common_name[] = szOID_COMMON_NAME;
6602     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6603      (LPBYTE)encodedCommonName };
6604     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6605 
6606     SetLastError(0xdeadbeef);
6607     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6608      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6609     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6610     {
6611         skip("no PKCS7_SIGNER_INFO encode support\n");
6612         return;
6613     }
6614     ok(!ret && (GetLastError() == E_INVALIDARG ||
6615      GetLastError() == OSS_LIMITED /* Win9x */),
6616      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6617     /* To be encoded, a signer must have an issuer at least, and the encoding
6618      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6619      * see decoding tests.)
6620      */
6621     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6622     info.Issuer.pbData = encodedCommonNameNoNull;
6623     SetLastError(0xdeadbeef);
6624     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6625      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6626     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6627         ok(!ret && GetLastError() == E_INVALIDARG,
6628          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6629     else
6630     {
6631         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6632          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6633         if (ret)
6634         {
6635             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6636             if (size == sizeof(minimalPKCSSigner))
6637                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6638             else
6639                 ok(0, "Unexpected value\n");
6640             LocalFree(buf);
6641         }
6642     }
6643     info.SerialNumber.cbData = sizeof(serialNum);
6644     info.SerialNumber.pbData = (BYTE *)serialNum;
6645     SetLastError(0xdeadbeef);
6646     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6647      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6648     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6649         ok(!ret && GetLastError() == E_INVALIDARG,
6650          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6651     else
6652     {
6653         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6654          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6655         if (ret)
6656         {
6657             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6658              size);
6659             if (size == sizeof(PKCSSignerWithSerial))
6660                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6661                  "Unexpected value\n");
6662             else
6663                 ok(0, "Unexpected value\n");
6664             LocalFree(buf);
6665         }
6666     }
6667     info.HashAlgorithm.pszObjId = oid1;
6668     SetLastError(0xdeadbeef);
6669     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6670      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6671     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6672         ok(!ret && GetLastError() == E_INVALIDARG,
6673          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6674     else
6675     {
6676         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6677          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6678         if (ret)
6679         {
6680             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6681              size);
6682             if (size == sizeof(PKCSSignerWithHashAlgo))
6683                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6684                  "Unexpected value\n");
6685             else
6686                 ok(0, "Unexpected value\n");
6687             LocalFree(buf);
6688         }
6689     }
6690     info.HashEncryptionAlgorithm.pszObjId = oid2;
6691     SetLastError(0xdeadbeef);
6692     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6693      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6694     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6695         ok(!ret && GetLastError() == E_INVALIDARG,
6696          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6697     else
6698     {
6699         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6700         if (ret)
6701         {
6702             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6703              "Unexpected size %d\n", size);
6704             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6705                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6706                  "Unexpected value\n");
6707             else
6708                 ok(0, "Unexpected value\n");
6709             LocalFree(buf);
6710         }
6711     }
6712     info.EncryptedHash.cbData = sizeof(hash);
6713     info.EncryptedHash.pbData = (BYTE *)hash;
6714     SetLastError(0xdeadbeef);
6715     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6716      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6717     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6718         ok(!ret && GetLastError() == E_INVALIDARG,
6719          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6720     else
6721     {
6722         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6723         if (ret)
6724         {
6725             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6726              size);
6727             if (size == sizeof(PKCSSignerWithHash))
6728                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6729                  "Unexpected value\n");
6730             else
6731                 ok(0, "Unexpected value\n");
6732             LocalFree(buf);
6733         }
6734     }
6735     info.AuthAttrs.cAttr = 1;
6736     info.AuthAttrs.rgAttr = &attr;
6737     SetLastError(0xdeadbeef);
6738     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6739      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6740     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6741         ok(!ret && GetLastError() == E_INVALIDARG,
6742          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6743     else
6744     {
6745         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6746         if (ret)
6747         {
6748             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6749              size);
6750             if (size == sizeof(PKCSSignerWithAuthAttr))
6751                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6752                  "Unexpected value\n");
6753             else
6754                 ok(0, "Unexpected value\n");
6755             LocalFree(buf);
6756         }
6757     }
6758 }
6759 
6760 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6761 {
6762     BOOL ret;
6763     LPBYTE buf = NULL;
6764     DWORD size = 0;
6765     CMSG_SIGNER_INFO *info;
6766 
6767     /* A PKCS signer can't be decoded without a serial number. */
6768     SetLastError(0xdeadbeef);
6769     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6770      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6771      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6772     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6773      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6774      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6775      GetLastError());
6776     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6777      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6778      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6779     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6780      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6781     if (ret)
6782     {
6783         info = (CMSG_SIGNER_INFO *)buf;
6784         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6785          info->dwVersion);
6786         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6787          "Unexpected size %d\n", info->Issuer.cbData);
6788         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6789          info->Issuer.cbData), "Unexpected value\n");
6790         ok(info->SerialNumber.cbData == sizeof(serialNum),
6791          "Unexpected size %d\n", info->SerialNumber.cbData);
6792         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6793          "Unexpected value\n");
6794         LocalFree(buf);
6795     }
6796     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6797      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6798      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6799     if (ret)
6800     {
6801         info = (CMSG_SIGNER_INFO *)buf;
6802         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6803          info->dwVersion);
6804         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6805          "Unexpected size %d\n", info->Issuer.cbData);
6806         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6807          info->Issuer.cbData), "Unexpected value\n");
6808         ok(info->SerialNumber.cbData == sizeof(serialNum),
6809          "Unexpected size %d\n", info->SerialNumber.cbData);
6810         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6811          "Unexpected value\n");
6812         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6813          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6814         LocalFree(buf);
6815     }
6816     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6817      PKCSSignerWithHashAndEncryptionAlgo,
6818      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6819      NULL, &buf, &size);
6820     if (ret)
6821     {
6822         info = (CMSG_SIGNER_INFO *)buf;
6823         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6824          info->dwVersion);
6825         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6826          "Unexpected size %d\n", info->Issuer.cbData);
6827         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6828          info->Issuer.cbData), "Unexpected value\n");
6829         ok(info->SerialNumber.cbData == sizeof(serialNum),
6830          "Unexpected size %d\n", info->SerialNumber.cbData);
6831         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6832          "Unexpected value\n");
6833         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6834          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6835         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6836          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6837         LocalFree(buf);
6838     }
6839     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6840      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6841      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6842     if (ret)
6843     {
6844         info = (CMSG_SIGNER_INFO *)buf;
6845         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6846          info->dwVersion);
6847         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6848          "Unexpected size %d\n", info->Issuer.cbData);
6849         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6850          info->Issuer.cbData), "Unexpected value\n");
6851         ok(info->SerialNumber.cbData == sizeof(serialNum),
6852          "Unexpected size %d\n", info->SerialNumber.cbData);
6853         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6854          "Unexpected value\n");
6855         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6856          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6857         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6858          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6859         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6860          info->EncryptedHash.cbData);
6861         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6862          "Unexpected value\n");
6863         LocalFree(buf);
6864     }
6865     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6866      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6867      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6868     if (ret)
6869     {
6870         info = (CMSG_SIGNER_INFO *)buf;
6871         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6872          info->AuthAttrs.cAttr);
6873         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6874          "Expected %s, got %s\n", szOID_COMMON_NAME,
6875          info->AuthAttrs.rgAttr[0].pszObjId);
6876         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6877          info->AuthAttrs.rgAttr[0].cValue);
6878         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6879          sizeof(encodedCommonName), "Unexpected size %d\n",
6880          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6881         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6882          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6883         LocalFree(buf);
6884     }
6885 }
6886 
6887 static const BYTE CMSSignerWithKeyId[] = {
6888 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6889 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6890 
6891 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6892 {
6893     BOOL ret;
6894     LPBYTE buf = NULL;
6895     DWORD size = 0;
6896     CMSG_CMS_SIGNER_INFO info = { 0 };
6897     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6898 
6899     SetLastError(0xdeadbeef);
6900     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6901      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6902     ok(!ret, "Expected failure, got %d\n", ret);
6903     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6904     {
6905         skip("no CMS_SIGNER_INFO encode support\n");
6906         return;
6907     }
6908     ok(GetLastError() == E_INVALIDARG,
6909        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6910     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6911     SetLastError(0xdeadbeef);
6912     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6913      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6914     ok(!ret, "Expected failure, got %d\n", ret);
6915     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6916     {
6917         skip("no CMS_SIGNER_INFO encode support\n");
6918         return;
6919     }
6920     ok(GetLastError() == E_INVALIDARG,
6921        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6922     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6923      * be a key id or an issuer serial number with at least the issuer set, and
6924      * the encoding must include PKCS_7_ASN_ENCODING.
6925      * (That isn't enough to be decoded, see decoding tests.)
6926      */
6927     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6928      sizeof(encodedCommonNameNoNull);
6929     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6930     SetLastError(0xdeadbeef);
6931     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6932      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6933     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6934         ok(!ret && GetLastError() == E_INVALIDARG,
6935          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6936     else
6937     {
6938         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6939         if (ret)
6940         {
6941             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6942             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6943             LocalFree(buf);
6944         }
6945     }
6946     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6947     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6948     SetLastError(0xdeadbeef);
6949     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6950      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6951     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6952         ok(!ret && GetLastError() == E_INVALIDARG,
6953          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6954     else
6955     {
6956         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6957         if (ret)
6958         {
6959             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6960              size);
6961             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6962             LocalFree(buf);
6963         }
6964     }
6965     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6966     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6967     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6968     SetLastError(0xdeadbeef);
6969     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6970      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6971     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6972         ok(!ret && GetLastError() == E_INVALIDARG,
6973          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6974     else
6975     {
6976         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6977         if (ret)
6978         {
6979             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6980              size);
6981             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6982             LocalFree(buf);
6983         }
6984     }
6985     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6986      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6987      * (see RFC 3852, section 5.3.)
6988      */
6989     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6990     U(info.SignerId).HashId.cbData = sizeof(hash);
6991     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6992     SetLastError(0xdeadbeef);
6993     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6994      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6995     ok(!ret && GetLastError() == E_INVALIDARG,
6996      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6997     /* Now with a hash algo */
6998     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6999     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
7000      sizeof(encodedCommonNameNoNull);
7001     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
7002     info.HashAlgorithm.pszObjId = oid1;
7003     SetLastError(0xdeadbeef);
7004     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
7005      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7006     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
7007         ok(!ret && GetLastError() == E_INVALIDARG,
7008          "Expected E_INVALIDARG, got %08x\n", GetLastError());
7009     else
7010     {
7011         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
7012         if (ret)
7013         {
7014             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
7015              size);
7016             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
7017              "Unexpected value\n");
7018             LocalFree(buf);
7019         }
7020     }
7021     info.HashEncryptionAlgorithm.pszObjId = oid2;
7022     SetLastError(0xdeadbeef);
7023     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
7024      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7025     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
7026         ok(!ret && GetLastError() == E_INVALIDARG,
7027          "Expected E_INVALIDARG, got %08x\n", GetLastError());
7028     else
7029     {
7030         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
7031         if (ret)
7032         {
7033             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
7034              "Unexpected size %d\n", size);
7035             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
7036              "Unexpected value\n");
7037             LocalFree(buf);
7038         }
7039     }
7040     info.EncryptedHash.cbData = sizeof(hash);
7041     info.EncryptedHash.pbData = (BYTE *)hash;
7042     SetLastError(0xdeadbeef);
7043     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
7044      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7045     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
7046         ok(!ret && GetLastError() == E_INVALIDARG,
7047          "Expected E_INVALIDARG, got %08x\n", GetLastError());
7048     else
7049     {
7050         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
7051         if (ret)
7052         {
7053             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
7054              size);
7055             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
7056             LocalFree(buf);
7057         }
7058     }
7059 }
7060 
7061 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
7062 {
7063     BOOL ret;
7064     LPBYTE buf = NULL;
7065     DWORD size = 0;
7066     CMSG_CMS_SIGNER_INFO *info;
7067     static const char oid1[] = "1.2.3", oid2[] = "1.5.6";
7068 
7069     /* A CMS signer can't be decoded without a serial number. */
7070     SetLastError(0xdeadbeef);
7071     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7072      minimalPKCSSigner, sizeof(minimalPKCSSigner),
7073      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7074     ok(!ret, "expected failure\n");
7075     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7076     {
7077         skip("no CMS_SIGNER_INFO decode support\n");
7078         return;
7079     }
7080     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
7081      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
7082     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7083      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
7084      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7085     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7086     if (ret)
7087     {
7088         info = (CMSG_CMS_SIGNER_INFO *)buf;
7089         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7090          info->dwVersion);
7091         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7092          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7093          info->SignerId.dwIdChoice);
7094         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7095          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7096          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7097         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7098          encodedCommonNameNoNull,
7099          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7100          "Unexpected value\n");
7101         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7102          sizeof(serialNum), "Unexpected size %d\n",
7103          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7104         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7105          serialNum, sizeof(serialNum)), "Unexpected value\n");
7106         LocalFree(buf);
7107     }
7108     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7109      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
7110      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7111     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7112     if (ret)
7113     {
7114         info = (CMSG_CMS_SIGNER_INFO *)buf;
7115         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7116          info->dwVersion);
7117         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7118          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7119          info->SignerId.dwIdChoice);
7120         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7121          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7122          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7123         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7124          encodedCommonNameNoNull,
7125          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7126          "Unexpected value\n");
7127         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7128          sizeof(serialNum), "Unexpected size %d\n",
7129          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7130         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7131          serialNum, sizeof(serialNum)), "Unexpected value\n");
7132         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7133          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7134         LocalFree(buf);
7135     }
7136     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7137      PKCSSignerWithHashAndEncryptionAlgo,
7138      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
7139      NULL, &buf, &size);
7140     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7141     if (ret)
7142     {
7143         info = (CMSG_CMS_SIGNER_INFO *)buf;
7144         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7145          info->dwVersion);
7146         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7147          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7148          info->SignerId.dwIdChoice);
7149         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7150          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7151          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7152         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7153          encodedCommonNameNoNull,
7154          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7155          "Unexpected value\n");
7156         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7157          sizeof(serialNum), "Unexpected size %d\n",
7158          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7159         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7160          serialNum, sizeof(serialNum)), "Unexpected value\n");
7161         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7162          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7163         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7164          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7165         LocalFree(buf);
7166     }
7167     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7168      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
7169      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7170     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7171     if (ret)
7172     {
7173         info = (CMSG_CMS_SIGNER_INFO *)buf;
7174         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7175          info->dwVersion);
7176         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7177          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7178          info->SignerId.dwIdChoice);
7179         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7180          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7181          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7182         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7183          encodedCommonNameNoNull,
7184          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7185          "Unexpected value\n");
7186         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7187          sizeof(serialNum), "Unexpected size %d\n",
7188          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7189         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7190          serialNum, sizeof(serialNum)), "Unexpected value\n");
7191         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7192          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7193         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7194          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7195         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
7196          info->EncryptedHash.cbData);
7197         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
7198          "Unexpected value\n");
7199         LocalFree(buf);
7200     }
7201     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7202      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
7203      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7204     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7205     if (ret)
7206     {
7207         info = (CMSG_CMS_SIGNER_INFO *)buf;
7208         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7209          info->dwVersion);
7210         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
7211          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
7212          info->SignerId.dwIdChoice);
7213         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
7214          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
7215         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
7216          "Unexpected value\n");
7217         LocalFree(buf);
7218     }
7219 }
7220 
7221 static BYTE emptyDNSPermittedConstraints[] = {
7222 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7223 static BYTE emptyDNSExcludedConstraints[] = {
7224 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7225 static BYTE DNSExcludedConstraints[] = {
7226 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7227 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7228 static BYTE permittedAndExcludedConstraints[] = {
7229 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7230 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7231 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7232 static BYTE permittedAndExcludedWithMinConstraints[] = {
7233 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7234 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7235 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7236 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7237 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7238 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7239 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7240 
7241 static void test_encodeNameConstraints(DWORD dwEncoding)
7242 {
7243     BOOL ret;
7244     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7245     CERT_GENERAL_SUBTREE permitted = { { 0 } };
7246     CERT_GENERAL_SUBTREE excluded = { { 0 } };
7247     LPBYTE buf;
7248     DWORD size;
7249 
7250     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7251      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7252     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7253     {
7254         skip("no X509_NAME_CONSTRAINTS encode support\n");
7255         return;
7256     }
7257     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7258     if (ret)
7259     {
7260         ok(size == sizeof(emptySequence), "Unexpected size\n");
7261         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7262         LocalFree(buf);
7263     }
7264     constraints.cPermittedSubtree = 1;
7265     constraints.rgPermittedSubtree = &permitted;
7266     SetLastError(0xdeadbeef);
7267     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7268      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7269     ok(!ret && GetLastError() == E_INVALIDARG,
7270      "Expected E_INVALIDARG, got %08x\n", GetLastError());
7271     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7272     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7273      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7274     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7275     if (ret)
7276     {
7277         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7278         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7279          "Unexpected value\n");
7280         LocalFree(buf);
7281     }
7282     constraints.cPermittedSubtree = 0;
7283     constraints.cExcludedSubtree = 1;
7284     constraints.rgExcludedSubtree = &excluded;
7285     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7286     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7287      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7288     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7289     if (ret)
7290     {
7291         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7292         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7293          "Unexpected value\n");
7294         LocalFree(buf);
7295     }
7296     U(excluded.Base).pwszURL = (LPWSTR)url;
7297     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7298      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7299     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7300     if (ret)
7301     {
7302         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7303         ok(!memcmp(buf, DNSExcludedConstraints, size),
7304          "Unexpected value\n");
7305         LocalFree(buf);
7306     }
7307     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7308     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7309     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7310     constraints.cPermittedSubtree = 1;
7311     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7312      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7313     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7314     if (ret)
7315     {
7316         ok(size == sizeof(permittedAndExcludedConstraints),
7317          "Unexpected size\n");
7318         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7319          "Unexpected value\n");
7320         LocalFree(buf);
7321     }
7322     permitted.dwMinimum = 5;
7323     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7324      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7325     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7326     if (ret)
7327     {
7328         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7329          "Unexpected size\n");
7330         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7331          "Unexpected value\n");
7332         LocalFree(buf);
7333     }
7334     permitted.fMaximum = TRUE;
7335     permitted.dwMaximum = 3;
7336     SetLastError(0xdeadbeef);
7337     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7338      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7339     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7340     if (ret)
7341     {
7342         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7343          "Unexpected size\n");
7344         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7345          "Unexpected value\n");
7346         LocalFree(buf);
7347     }
7348 }
7349 
7350 struct EncodedNameConstraints
7351 {
7352     CRYPT_DATA_BLOB            encoded;
7353     CERT_NAME_CONSTRAINTS_INFO constraints;
7354 };
7355 
7356 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7357  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7358 static CERT_GENERAL_SUBTREE DNSSubtree = {
7359  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7360 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7361  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7362 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7363  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7364 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7365  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7366 
7367 static const struct EncodedNameConstraints encodedNameConstraints[] = {
7368  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7369  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7370    { 1, &emptyDNSSubtree, 0, NULL } },
7371  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7372    { 0, NULL, 1, &emptyDNSSubtree } },
7373  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7374    { 0, NULL, 1, &DNSSubtree } },
7375  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7376    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7377  { { sizeof(permittedAndExcludedWithMinConstraints),
7378      permittedAndExcludedWithMinConstraints },
7379    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7380  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7381      permittedAndExcludedWithMinMaxConstraints },
7382    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7383 };
7384 
7385 static void test_decodeNameConstraints(DWORD dwEncoding)
7386 {
7387     BOOL ret;
7388     DWORD i;
7389     CERT_NAME_CONSTRAINTS_INFO *constraints;
7390 
7391     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7392     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7393     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7394     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7395     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7396     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7397     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7398     for (i = 0; i < ARRAY_SIZE(encodedNameConstraints); i++)
7399     {
7400         DWORD size;
7401 
7402         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7403          encodedNameConstraints[i].encoded.pbData,
7404          encodedNameConstraints[i].encoded.cbData,
7405          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7406         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7407         {
7408             skip("no X509_NAME_CONSTRAINTS decode support\n");
7409             return;
7410         }
7411         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7412         if (ret)
7413         {
7414             DWORD j;
7415 
7416             if (constraints->cPermittedSubtree !=
7417              encodedNameConstraints[i].constraints.cPermittedSubtree)
7418                 fprintf(stderr, "%d: expected %u permitted, got %u\n", i,
7419                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7420                  constraints->cPermittedSubtree);
7421             if (constraints->cPermittedSubtree ==
7422              encodedNameConstraints[i].constraints.cPermittedSubtree)
7423             {
7424                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7425                 {
7426                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7427                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7428                 }
7429             }
7430             if (constraints->cExcludedSubtree !=
7431              encodedNameConstraints[i].constraints.cExcludedSubtree)
7432                 fprintf(stderr, "%d: expected %u excluded, got %u\n", i,
7433                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7434                  constraints->cExcludedSubtree);
7435             if (constraints->cExcludedSubtree ==
7436              encodedNameConstraints[i].constraints.cExcludedSubtree)
7437             {
7438                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7439                 {
7440                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7441                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7442                 }
7443             }
7444             LocalFree(constraints);
7445         }
7446     }
7447 }
7448 
7449 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7450  'n','o','t','i','c','e',0 };
7451 static const BYTE noticeWithDisplayText[] = {
7452  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7453  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7454  0x00,0x69,0x00,0x63,0x00,0x65
7455 };
7456 static char org[] = "Wine";
7457 static int noticeNumbers[] = { 2,3 };
7458 static BYTE noticeWithReference[] = {
7459  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7460  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7461  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7462  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7463 };
7464 
7465 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7466 {
7467     BOOL ret;
7468     LPBYTE buf;
7469     DWORD size;
7470     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7471     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7472 
7473     memset(&notice, 0, sizeof(notice));
7474     ret = pCryptEncodeObjectEx(dwEncoding,
7475      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7476      NULL, &buf, &size);
7477     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7478     {
7479         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7480         return;
7481     }
7482     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7483     if (ret)
7484     {
7485         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7486         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7487         LocalFree(buf);
7488     }
7489     notice.pszDisplayText = noticeText;
7490     ret = pCryptEncodeObjectEx(dwEncoding,
7491      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7492      NULL, &buf, &size);
7493     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7494     if (ret)
7495     {
7496         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7497         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7498         LocalFree(buf);
7499     }
7500     reference.pszOrganization = org;
7501     reference.cNoticeNumbers = 2;
7502     reference.rgNoticeNumbers = noticeNumbers;
7503     notice.pNoticeReference = &reference;
7504     ret = pCryptEncodeObjectEx(dwEncoding,
7505      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7506      NULL, &buf, &size);
7507     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7508     if (ret)
7509     {
7510         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7511         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7512         LocalFree(buf);
7513     }
7514 }
7515 
7516 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7517 {
7518     BOOL ret;
7519     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7520     DWORD size;
7521 
7522     ret = pCryptDecodeObjectEx(dwEncoding,
7523      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7524      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7525      &notice, &size);
7526     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7527     {
7528         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7529         return;
7530     }
7531     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7532     if (ret)
7533     {
7534         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7535         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7536         LocalFree(notice);
7537     }
7538     ret = pCryptDecodeObjectEx(dwEncoding,
7539      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7540      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7541      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7542     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7543     if (ret)
7544     {
7545         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7546          "unexpected display text\n");
7547         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7548         LocalFree(notice);
7549     }
7550     ret = pCryptDecodeObjectEx(dwEncoding,
7551      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7552      noticeWithReference, sizeof(noticeWithReference),
7553      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7554     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7555     if (ret)
7556     {
7557         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7558          "unexpected display text\n");
7559         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7560         if (notice->pNoticeReference)
7561         {
7562             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7563              "unexpected organization %s\n",
7564              notice->pNoticeReference->pszOrganization);
7565             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7566              "expected 2 notice numbers, got %d\n",
7567              notice->pNoticeReference->cNoticeNumbers);
7568             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7569              "unexpected notice number %d\n",
7570              notice->pNoticeReference->rgNoticeNumbers[0]);
7571             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7572              "unexpected notice number %d\n",
7573              notice->pNoticeReference->rgNoticeNumbers[1]);
7574         }
7575         LocalFree(notice);
7576     }
7577 }
7578 
7579 static char oid_any_policy[] = "2.5.29.32.0";
7580 static const BYTE policiesWithAnyPolicy[] = {
7581  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7582 };
7583 static char oid1[] = "1.2.3";
7584 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7585 static const BYTE twoPolicies[] = {
7586  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7587  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7588  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7589  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7590  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7591  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7592 };
7593 
7594 static void test_encodeCertPolicies(DWORD dwEncoding)
7595 {
7596     BOOL ret;
7597     CERT_POLICIES_INFO info;
7598     CERT_POLICY_INFO policy[2];
7599     CERT_POLICY_QUALIFIER_INFO qualifier;
7600     LPBYTE buf;
7601     DWORD size;
7602 
7603     memset(&info, 0, sizeof(info));
7604     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7605      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7606     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7607     if (ret)
7608     {
7609         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7610         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7611         LocalFree(buf);
7612     }
7613     memset(policy, 0, sizeof(policy));
7614     info.cPolicyInfo = 1;
7615     info.rgPolicyInfo = policy;
7616     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7617      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7618     ok(!ret && (GetLastError() == E_INVALIDARG ||
7619      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7620      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7621     policy[0].pszPolicyIdentifier = oid_any_policy;
7622     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7623      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7624     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7625     if (ret)
7626     {
7627         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7628         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7629         LocalFree(buf);
7630     }
7631     policy[1].pszPolicyIdentifier = oid1;
7632     memset(&qualifier, 0, sizeof(qualifier));
7633     qualifier.pszPolicyQualifierId = oid_user_notice;
7634     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7635     qualifier.Qualifier.pbData = noticeWithReference;
7636     policy[1].cPolicyQualifier = 1;
7637     policy[1].rgPolicyQualifier = &qualifier;
7638     info.cPolicyInfo = 2;
7639     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7640      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7641     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7642     if (ret)
7643     {
7644         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7645         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7646         LocalFree(buf);
7647     }
7648 }
7649 
7650 static void test_decodeCertPolicies(DWORD dwEncoding)
7651 {
7652     BOOL ret;
7653     CERT_POLICIES_INFO *info;
7654     DWORD size;
7655 
7656     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7657      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7658      &info, &size);
7659     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7660     if (ret)
7661     {
7662         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7663          info->cPolicyInfo);
7664         LocalFree(info);
7665     }
7666     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7667      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7668      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7669     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7670     if (ret)
7671     {
7672         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7673          info->cPolicyInfo);
7674         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7675          "unexpected policy id %s\n",
7676          info->rgPolicyInfo[0].pszPolicyIdentifier);
7677         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7678          "unexpected policy qualifier count %d\n",
7679          info->rgPolicyInfo[0].cPolicyQualifier);
7680         LocalFree(info);
7681     }
7682     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7683      twoPolicies, sizeof(twoPolicies),
7684      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7685     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7686     if (ret)
7687     {
7688         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7689          info->cPolicyInfo);
7690         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7691          "unexpected policy id %s\n",
7692          info->rgPolicyInfo[0].pszPolicyIdentifier);
7693         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7694          "unexpected policy qualifier count %d\n",
7695          info->rgPolicyInfo[0].cPolicyQualifier);
7696         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7697          "unexpected policy id %s\n",
7698          info->rgPolicyInfo[1].pszPolicyIdentifier);
7699         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7700          "unexpected policy qualifier count %d\n",
7701          info->rgPolicyInfo[1].cPolicyQualifier);
7702         ok(!strcmp(
7703          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7704          oid_user_notice), "unexpected policy qualifier id %s\n",
7705          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7706         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7707          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7708          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7709         ok(!memcmp(
7710          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7711          noticeWithReference, sizeof(noticeWithReference)),
7712          "unexpected qualifier value\n");
7713         LocalFree(info);
7714     }
7715     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7716      twoPolicies, sizeof(twoPolicies), 0, NULL, NULL, &size);
7717     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7718     info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7719     if (info)
7720     {
7721         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7722          twoPolicies, sizeof(twoPolicies), 0, NULL, info, &size);
7723         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7724         HeapFree(GetProcessHeap(), 0, info);
7725     }
7726 }
7727 
7728 static const BYTE policyMappingWithOneMapping[] = {
7729 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7730 static const BYTE policyMappingWithTwoMappings[] = {
7731 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7732 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7733 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7734  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7735 
7736 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7737 {
7738     static char oid2[] = "2.3.4";
7739     static char oid3[] = "1.3.4";
7740     static char oid4[] = "2.5.6";
7741     BOOL ret;
7742     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7743     CERT_POLICY_MAPPING mapping[2];
7744     LPBYTE buf;
7745     DWORD size, i;
7746 
7747     /* Each of the mapping OIDs is equivalent, so check with all of them */
7748     for (i = 0; i < ARRAY_SIZE(mappingOids); i++)
7749     {
7750         memset(&info, 0, sizeof(info));
7751         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7752          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7753         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7754          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7755         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7756         {
7757             win_skip("no policy mappings support\n");
7758             return;
7759         }
7760         if (ret)
7761         {
7762             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7763             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7764              "unexpected value\n");
7765             LocalFree(buf);
7766         }
7767         mapping[0].pszIssuerDomainPolicy = NULL;
7768         mapping[0].pszSubjectDomainPolicy = NULL;
7769         info.cPolicyMapping = 1;
7770         info.rgPolicyMapping = mapping;
7771         SetLastError(0xdeadbeef);
7772         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7773          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7774         ok(!ret && GetLastError() == E_INVALIDARG,
7775          "expected E_INVALIDARG, got %08x\n", GetLastError());
7776         mapping[0].pszIssuerDomainPolicy = oid1;
7777         mapping[0].pszSubjectDomainPolicy = oid2;
7778         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7779          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7780         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7781         if (ret)
7782         {
7783             ok(size == sizeof(policyMappingWithOneMapping),
7784              "unexpected size %d\n", size);
7785             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7786              "unexpected value\n");
7787             LocalFree(buf);
7788         }
7789         mapping[1].pszIssuerDomainPolicy = oid3;
7790         mapping[1].pszSubjectDomainPolicy = oid4;
7791         info.cPolicyMapping = 2;
7792         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7793          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7794         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7795         if (ret)
7796         {
7797             ok(size == sizeof(policyMappingWithTwoMappings),
7798              "unexpected size %d\n", size);
7799             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7800              "unexpected value\n");
7801             LocalFree(buf);
7802         }
7803     }
7804 }
7805 
7806 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7807 {
7808     DWORD size, i;
7809     CERT_POLICY_MAPPINGS_INFO *info;
7810     BOOL ret;
7811 
7812     /* Each of the mapping OIDs is equivalent, so check with all of them */
7813     for (i = 0; i < ARRAY_SIZE(mappingOids); i++)
7814     {
7815         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7816          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7817          &info, &size);
7818         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7819          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7820         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7821         {
7822             win_skip("no policy mappings support\n");
7823             return;
7824         }
7825         if (ret)
7826         {
7827             ok(info->cPolicyMapping == 0,
7828              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7829             LocalFree(info);
7830         }
7831         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7832          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7833          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7834         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7835         if (ret)
7836         {
7837             ok(info->cPolicyMapping == 1,
7838              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7839             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7840              "unexpected issuer policy %s\n",
7841              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7842             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7843              "2.3.4"), "unexpected subject policy %s\n",
7844              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7845             LocalFree(info);
7846         }
7847         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7848          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7849          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7850         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7851         if (ret)
7852         {
7853             ok(info->cPolicyMapping == 2,
7854              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7855             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7856              "unexpected issuer policy %s\n",
7857              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7858             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7859              "2.3.4"), "unexpected subject policy %s\n",
7860              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7861             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7862              "unexpected issuer policy %s\n",
7863              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7864             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7865              "2.5.6"), "unexpected subject policy %s\n",
7866              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7867             LocalFree(info);
7868         }
7869         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7870          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7871          NULL, NULL, &size);
7872         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7873         info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7874         if (info)
7875         {
7876             ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7877              policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7878              NULL, info, &size);
7879             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7880             HeapFree(GetProcessHeap(), 0, info);
7881         }
7882     }
7883 }
7884 
7885 static const BYTE policyConstraintsWithRequireExplicit[] = {
7886 0x30,0x03,0x80,0x01,0x00 };
7887 static const BYTE policyConstraintsWithInhibitMapping[] = {
7888 0x30,0x03,0x81,0x01,0x01 };
7889 static const BYTE policyConstraintsWithBoth[] = {
7890 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7891 
7892 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7893 {
7894     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7895     LPBYTE buf;
7896     DWORD size;
7897     BOOL ret;
7898 
7899     /* Even though RFC 5280 explicitly states CAs must not issue empty
7900      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7901      */
7902     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7903      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7904     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7905      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7906     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7907     {
7908         win_skip("no policy constraints support\n");
7909         return;
7910     }
7911     if (ret)
7912     {
7913         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7914         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7915          "unexpected value\n");
7916         LocalFree(buf);
7917     }
7918     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7919      * is not, then a skip of 0 is encoded.
7920      */
7921     info.fRequireExplicitPolicy = TRUE;
7922     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7923      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7924     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7925     if (ret)
7926     {
7927         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7928          "unexpected size %d\n", size);
7929         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7930          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7931         LocalFree(buf);
7932     }
7933     /* With inhibit policy mapping */
7934     info.fRequireExplicitPolicy = FALSE;
7935     info.dwRequireExplicitPolicySkipCerts = 0;
7936     info.fInhibitPolicyMapping = TRUE;
7937     info.dwInhibitPolicyMappingSkipCerts = 1;
7938     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7939      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7940     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7941     if (ret)
7942     {
7943         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7944          "unexpected size %d\n", size);
7945         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7946          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7947         LocalFree(buf);
7948     }
7949     /* And with both */
7950     info.fRequireExplicitPolicy = TRUE;
7951     info.dwRequireExplicitPolicySkipCerts = 1;
7952     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7953      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7954     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7955     if (ret)
7956     {
7957         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7958          size);
7959         ok(!memcmp(buf, policyConstraintsWithBoth,
7960          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7961         LocalFree(buf);
7962     }
7963 }
7964 
7965 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7966 {
7967     CERT_POLICY_CONSTRAINTS_INFO *info;
7968     DWORD size;
7969     BOOL ret;
7970 
7971     /* Again, even though CAs must not issue such constraints, they can be
7972      * decoded.
7973      */
7974     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7975      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7976      &info, &size);
7977     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7978      "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7979     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7980     {
7981         win_skip("no policy mappings support\n");
7982         return;
7983     }
7984     if (ret)
7985     {
7986         ok(!info->fRequireExplicitPolicy,
7987          "expected require explicit = FALSE\n");
7988         ok(!info->fInhibitPolicyMapping,
7989          "expected implicit mapping = FALSE\n");
7990         LocalFree(info);
7991     }
7992     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7993      policyConstraintsWithRequireExplicit,
7994      sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7995      NULL, &info, &size);
7996     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7997     if (ret)
7998     {
7999         ok(info->fRequireExplicitPolicy,
8000          "expected require explicit = TRUE\n");
8001         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
8002          info->dwRequireExplicitPolicySkipCerts);
8003         ok(!info->fInhibitPolicyMapping,
8004          "expected implicit mapping = FALSE\n");
8005         LocalFree(info);
8006     }
8007     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
8008      policyConstraintsWithInhibitMapping,
8009      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
8010      NULL, &info, &size);
8011     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
8012     if (ret)
8013     {
8014         ok(!info->fRequireExplicitPolicy,
8015          "expected require explicit = FALSE\n");
8016         ok(info->fInhibitPolicyMapping,
8017          "expected implicit mapping = TRUE\n");
8018         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
8019          info->dwInhibitPolicyMappingSkipCerts);
8020         LocalFree(info);
8021     }
8022     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
8023      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
8024      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
8025     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
8026     if (ret)
8027     {
8028         ok(info->fRequireExplicitPolicy,
8029          "expected require explicit = TRUE\n");
8030         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
8031          info->dwRequireExplicitPolicySkipCerts);
8032         ok(info->fInhibitPolicyMapping,
8033          "expected implicit mapping = TRUE\n");
8034         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
8035          info->dwInhibitPolicyMappingSkipCerts);
8036         LocalFree(info);
8037     }
8038 }
8039 
8040 static const BYTE rsaPrivKeyDer[] = {
8041 0x30,0x82,0x04,0xa5,0x02,0x01,0x00,0x02,0x82,0x01,0x01,0x00,
8042 0xae,0xba,0x3c,0x41,0xeb,0x25,0x41,0xb0,0x1c,0x41,0xd4,0x26,
8043 0xf9,0xf8,0x31,0x64,0x7e,0x97,0x65,0x54,0x9c,0x90,0xdf,0x34,
8044 0x07,0xfb,0xb0,0x69,0x99,0x3b,0x45,0x39,0x06,0xe4,0x3a,0x7a,
8045 0x01,0xe0,0xeb,0x3f,0xe1,0xd5,0x91,0xe0,0x16,0xe0,0xf2,0x35,
8046 0x59,0xdf,0x32,0x2d,0x69,0x3a,0x4a,0xbc,0xd1,0xba,0x1b,0x3b,
8047 0x7a,0x55,0x76,0xba,0x11,0xdd,0x2f,0xc7,0x58,0x66,0xf2,0x6c,
8048 0xd1,0x68,0x27,0x6c,0x85,0x74,0x0b,0xc9,0x7b,0x1a,0xde,0x3c,
8049 0x62,0x73,0xe2,0x9e,0x36,0x3a,0x29,0x3b,0x91,0x85,0x3d,0xd2,
8050 0xe1,0xe5,0x61,0x84,0x1e,0x28,0xfd,0xb7,0x97,0x68,0xc1,0xbb,
8051 0x0f,0x93,0x14,0xc2,0x03,0x60,0x41,0x11,0x7a,0xda,0x76,0x01,
8052 0x65,0x08,0xe6,0x0c,0xf6,0xfc,0x1d,0x64,0x12,0x7b,0x42,0xb0,
8053 0xb8,0xfe,0x61,0xe5,0xe2,0xe5,0x61,0x44,0xcc,0x94,0xe8,0xc0,
8054 0x4f,0x58,0x9a,0xea,0x99,0xaf,0x9c,0xa4,0xf2,0xd7,0x2b,0x31,
8055 0x90,0x3b,0x41,0x2e,0x4a,0x74,0x7c,0x1a,0xfc,0x42,0xa9,0x17,
8056 0xff,0x53,0x20,0x76,0xa7,0xf0,0x2c,0xb9,0xd5,0x1f,0xa9,0x8a,
8057 0x77,0xa8,0x09,0x5c,0x0e,0xd1,0x54,0xc5,0xf2,0x86,0xf1,0x2f,
8058 0x23,0xd6,0x63,0xba,0xe9,0x2b,0x73,0xf9,0xf0,0xdc,0xcb,0xf9,
8059 0xcb,0xe8,0x40,0x62,0x47,0x09,0x85,0xe1,0x9c,0xfd,0xcf,0x75,
8060 0x5a,0x65,0xfd,0x86,0x1c,0x50,0xfa,0x24,0x36,0x0f,0x54,0x5e,
8061 0x81,0xe7,0xf6,0x63,0x2d,0x87,0x0c,0x50,0x03,0x25,0x49,0xe7,
8062 0xc5,0x20,0xaa,0xbc,0x6c,0xf9,0xbe,0x49,0x8f,0x4f,0xb8,0x9a,
8063 0x73,0x9f,0x55,0x43,0x02,0x03,0x01,0x00,0x01,0x02,0x82,0x01,
8064 0x01,0x00,0x99,0x03,0xcd,0x5b,0x69,0x03,0x32,0x98,0x78,0xd6,
8065 0x89,0x65,0x2c,0xc9,0xd6,0xef,0x8c,0x11,0x27,0x93,0x46,0x9d,
8066 0x74,0x6a,0xcb,0x86,0xf6,0x02,0x34,0x47,0xfc,0xa2,0x29,0x4f,
8067 0xdb,0x8a,0x17,0x75,0x12,0x6f,0xda,0x65,0x3f,0x1f,0xc0,0xc9,
8068 0x74,0x33,0x96,0xa5,0xe8,0xfa,0x6d,0xc9,0xb7,0xc3,0xcd,0xe3,
8069 0x2e,0x90,0x12,0xdd,0x1f,0x61,0x69,0xdd,0x8b,0x47,0x07,0x3a,
8070 0xf8,0x98,0xa5,0x76,0x91,0xf7,0xee,0x93,0x26,0xf3,0x66,0x54,
8071 0xac,0x44,0xb3,0x6f,0x8b,0x09,0x44,0xb2,0x00,0x84,0x03,0x37,
8072 0x6d,0x61,0xed,0xa4,0x04,0x97,0x40,0x16,0x63,0xc2,0xd0,0xdc,
8073 0xd3,0xb3,0xee,0xba,0xbe,0x95,0xfd,0x80,0xe0,0xda,0xde,0xfc,
8074 0xcc,0x15,0x02,0x97,0x1d,0x68,0x43,0x2f,0x9c,0xc8,0x20,0x23,
8075 0xeb,0x00,0x4c,0x74,0x3d,0x27,0x20,0x14,0x23,0x95,0xfc,0x8c,
8076 0xb7,0x7e,0x7f,0xb0,0xdb,0xaf,0x8a,0x48,0x1b,0xfe,0x59,0xab,
8077 0x75,0xe2,0xbf,0x69,0xf2,0x73,0xe3,0xb9,0x92,0xa9,0x90,0x03,
8078 0xe5,0xd4,0x2d,0x86,0xff,0x12,0x54,0xb3,0xbb,0xe2,0xce,0x81,
8079 0x58,0x71,0xa4,0xde,0x45,0x05,0xf8,0x2d,0x45,0xf5,0xd8,0x5e,
8080 0x4c,0x5d,0x06,0x69,0x0c,0x86,0x9f,0x66,0x9f,0xb1,0x60,0xfd,
8081 0xf2,0x33,0x85,0x15,0xd5,0x18,0xf7,0xba,0x99,0x65,0x15,0x1d,
8082 0xfa,0xaa,0x76,0xdd,0x25,0xed,0xdf,0x90,0x6e,0xba,0x61,0x96,
8083 0x79,0xde,0xd2,0xda,0x66,0x03,0x74,0x3b,0x13,0x39,0x68,0xbc,
8084 0x94,0x01,0x00,0x2d,0xf8,0xf0,0x8c,0xbd,0x4c,0x9c,0x7e,0x87,
8085 0x9c,0x62,0x9f,0xb6,0x90,0x11,0x02,0x81,0x81,0x00,0xe3,0x5e,
8086 0xfe,0xdd,0xed,0x76,0xb6,0x4e,0xfc,0x5b,0xe0,0x20,0x99,0x7b,
8087 0x48,0x3b,0x1e,0x5f,0x7f,0x9f,0xa4,0x68,0xbe,0xc3,0x7f,0xb8,
8088 0x62,0x98,0xb0,0x95,0x8a,0xfa,0x0d,0xa3,0x79,0x63,0x39,0xf7,
8089 0xdb,0x76,0x3d,0x53,0x4a,0x0a,0x33,0xdf,0xe0,0x47,0x22,0xd5,
8090 0x96,0x80,0xc7,0xcd,0x24,0xef,0xac,0x49,0x46,0x37,0x6c,0x25,
8091 0xcf,0x6c,0x4d,0xe5,0x31,0xf8,0x2f,0xd2,0x59,0x74,0x00,0x38,
8092 0xdb,0xce,0xd1,0x72,0xc3,0xa8,0x30,0x70,0xd8,0x02,0x20,0xe7,
8093 0x56,0xe7,0xca,0xf0,0x3b,0x52,0x5d,0x11,0xbe,0x53,0x4e,0xd0,
8094 0xd9,0x2e,0xa6,0xb8,0xe2,0xd9,0xbf,0xb9,0x77,0xe7,0x3b,0xed,
8095 0x5e,0xd7,0x16,0x4a,0x3a,0xc5,0x86,0xd7,0x74,0x20,0xa7,0x8e,
8096 0xbf,0xb7,0x33,0xdb,0x51,0xe9,0x02,0x81,0x81,0x00,0xc4,0xba,
8097 0x57,0xf0,0x6e,0xcf,0xe8,0xce,0xce,0x9d,0x4a,0xe9,0x0f,0xe1,
8098 0xab,0x91,0x62,0xaa,0x66,0x5d,0x82,0x66,0x1c,0x72,0x18,0x6f,
8099 0x68,0x9c,0x7d,0x5e,0xfc,0xaf,0x4a,0xd6,0x8e,0xc6,0xae,0x40,
8100 0xf2,0x40,0x84,0x93,0xee,0x7c,0x87,0xa9,0xa6,0xcd,0x2b,0xc3,
8101 0xe6,0x29,0x3a,0xe2,0x4a,0xed,0xb0,0x4d,0x9f,0xc0,0xe9,0xd6,
8102 0xa3,0xca,0x97,0xee,0xac,0xab,0xa4,0x32,0x05,0x40,0x4d,0xf2,
8103 0x95,0x99,0xaf,0xa0,0xe1,0xe1,0xe7,0x3a,0x64,0xa4,0x70,0x6b,
8104 0x3d,0x1d,0x7b,0xf1,0x53,0xfa,0xb0,0xe0,0xe2,0x68,0x1a,0x61,
8105 0x2c,0x37,0xa5,0x39,0x7b,0xb2,0xcf,0xe6,0x5f,0x9b,0xc6,0x64,
8106 0xaf,0x48,0x86,0xfb,0xc1,0xf3,0x39,0x97,0x10,0x36,0xf5,0xa9,
8107 0x3d,0x08,0xa5,0x2f,0xe6,0x4b,0x02,0x81,0x81,0x00,0x86,0xe7,
8108 0x02,0x08,0xe2,0xaf,0xa0,0x93,0x54,0x9f,0x9e,0x67,0x39,0x29,
8109 0x30,0x3e,0x03,0x53,0x5e,0x01,0x76,0x26,0xbf,0xa8,0x76,0xcb,
8110 0x0b,0x94,0xd4,0x90,0xa5,0x98,0x9f,0x26,0xf3,0x0a,0xb0,0x86,
8111 0x22,0xac,0x10,0xce,0xae,0x0b,0x47,0xa3,0xf9,0x09,0xbb,0xdd,
8112 0x46,0x22,0xba,0x69,0x39,0x15,0x0a,0xff,0x9e,0xad,0x9b,0x79,
8113 0x03,0x8c,0x9a,0xda,0xf5,0xbe,0xef,0x80,0xba,0x9a,0x5c,0xd7,
8114 0x5f,0x73,0x62,0x49,0xd9,0x54,0x9d,0x09,0x16,0xe0,0x8c,0x6d,
8115 0x35,0xde,0xe9,0x45,0x87,0xac,0xe2,0x93,0x78,0x7d,0x2d,0x32,
8116 0x34,0xe9,0xbc,0xf9,0xcd,0x7e,0xac,0x86,0x7a,0x61,0xb3,0xe8,
8117 0xae,0x70,0xa7,0x44,0xfb,0x81,0xde,0xf3,0x4e,0x6f,0x61,0x7b,
8118 0x0c,0xbc,0xc2,0x03,0xca,0xa1,0x02,0x81,0x80,0x69,0x5b,0x4a,
8119 0xa1,0x4f,0x17,0x35,0x9d,0x1b,0xf6,0x0d,0x1a,0x48,0x11,0x19,
8120 0xab,0x20,0xe6,0x15,0x30,0x5b,0x17,0x88,0x80,0x6a,0x29,0xb0,
8121 0x22,0xae,0xd9,0xe2,0x05,0x96,0xd4,0xd5,0x5d,0xfe,0x10,0x76,
8122 0x2c,0xab,0x53,0xf6,0x52,0xe6,0xec,0xaa,0x92,0x12,0xb0,0x35,
8123 0x61,0x3b,0x51,0xd9,0xc2,0xf5,0xba,0x7c,0xa5,0xfa,0x15,0xa3,
8124 0x5e,0x6a,0x83,0xbe,0x21,0xa6,0x2b,0xcb,0xb8,0x26,0x86,0x96,
8125 0x2b,0xda,0x6d,0x14,0xcb,0xc0,0xe3,0xfa,0xe6,0x3d,0xf6,0x90,
8126 0xa2,0x6b,0xb0,0x50,0xc3,0x5f,0x5a,0xf0,0xa5,0xc4,0x0a,0xea,
8127 0x7d,0x5a,0x95,0x30,0x74,0x10,0xf7,0x55,0x98,0xbd,0x65,0x4a,
8128 0xa2,0x52,0xf8,0x1d,0x64,0xbf,0x20,0xf1,0xe4,0x1d,0x28,0x67,
8129 0xb1,0x6b,0x95,0xfd,0x85,0x02,0x81,0x81,0x00,0xda,0xb4,0x31,
8130 0x34,0xe1,0xec,0x9a,0x1e,0x07,0xd7,0xda,0x20,0x46,0xbf,0x6b,
8131 0xf0,0x45,0xbd,0x50,0xa2,0x0f,0x8a,0x14,0x51,0x52,0x83,0x7c,
8132 0x47,0xc8,0x9c,0x4e,0x68,0x6b,0xae,0x00,0x25,0x63,0xdd,0x13,
8133 0x2a,0x66,0x65,0xb6,0x74,0x91,0x5b,0xb6,0x47,0x3e,0x8e,0x46,
8134 0x62,0xcd,0x9d,0xc1,0xf7,0x14,0x14,0xbc,0x60,0xd6,0x3c,0x7c,
8135 0x3a,0xce,0xff,0x96,0x04,0x84,0xf6,0x44,0x1a,0xf8,0xdb,0x40,
8136 0x1c,0xf2,0xf1,0x4d,0xb2,0x68,0x3e,0xa3,0x0b,0xc6,0xb1,0xd0,
8137 0xa6,0x88,0x18,0x68,0xa1,0x05,0x2a,0xfc,0x2b,0x3a,0xa1,0xe6,
8138 0x31,0x4a,0x46,0x88,0x39,0x1e,0x44,0x11,0x6c,0xc5,0x8b,0xb6,
8139 0x8b,0xce,0x3d,0xd5,0xcb,0xbd,0xf0,0xd4,0xd9,0xfb,0x02,0x35,
8140 0x96,0x39,0x26,0x85,0xf9 };
8141 static const BYTE rsaPrivKeyModulus[] = {
8142 0x43,0x55,0x9f,0x73,0x9a,0xb8,0x4f,0x8f,0x49,0xbe,0xf9,0x6c,
8143 0xbc,0xaa,0x20,0xc5,0xe7,0x49,0x25,0x03,0x50,0x0c,0x87,0x2d,
8144 0x63,0xf6,0xe7,0x81,0x5e,0x54,0x0f,0x36,0x24,0xfa,0x50,0x1c,
8145 0x86,0xfd,0x65,0x5a,0x75,0xcf,0xfd,0x9c,0xe1,0x85,0x09,0x47,
8146 0x62,0x40,0xe8,0xcb,0xf9,0xcb,0xdc,0xf0,0xf9,0x73,0x2b,0xe9,
8147 0xba,0x63,0xd6,0x23,0x2f,0xf1,0x86,0xf2,0xc5,0x54,0xd1,0x0e,
8148 0x5c,0x09,0xa8,0x77,0x8a,0xa9,0x1f,0xd5,0xb9,0x2c,0xf0,0xa7,
8149 0x76,0x20,0x53,0xff,0x17,0xa9,0x42,0xfc,0x1a,0x7c,0x74,0x4a,
8150 0x2e,0x41,0x3b,0x90,0x31,0x2b,0xd7,0xf2,0xa4,0x9c,0xaf,0x99,
8151 0xea,0x9a,0x58,0x4f,0xc0,0xe8,0x94,0xcc,0x44,0x61,0xe5,0xe2,
8152 0xe5,0x61,0xfe,0xb8,0xb0,0x42,0x7b,0x12,0x64,0x1d,0xfc,0xf6,
8153 0x0c,0xe6,0x08,0x65,0x01,0x76,0xda,0x7a,0x11,0x41,0x60,0x03,
8154 0xc2,0x14,0x93,0x0f,0xbb,0xc1,0x68,0x97,0xb7,0xfd,0x28,0x1e,
8155 0x84,0x61,0xe5,0xe1,0xd2,0x3d,0x85,0x91,0x3b,0x29,0x3a,0x36,
8156 0x9e,0xe2,0x73,0x62,0x3c,0xde,0x1a,0x7b,0xc9,0x0b,0x74,0x85,
8157 0x6c,0x27,0x68,0xd1,0x6c,0xf2,0x66,0x58,0xc7,0x2f,0xdd,0x11,
8158 0xba,0x76,0x55,0x7a,0x3b,0x1b,0xba,0xd1,0xbc,0x4a,0x3a,0x69,
8159 0x2d,0x32,0xdf,0x59,0x35,0xf2,0xe0,0x16,0xe0,0x91,0xd5,0xe1,
8160 0x3f,0xeb,0xe0,0x01,0x7a,0x3a,0xe4,0x06,0x39,0x45,0x3b,0x99,
8161 0x69,0xb0,0xfb,0x07,0x34,0xdf,0x90,0x9c,0x54,0x65,0x97,0x7e,
8162 0x64,0x31,0xf8,0xf9,0x26,0xd4,0x41,0x1c,0xb0,0x41,0x25,0xeb,
8163 0x41,0x3c,0xba,0xae };
8164 static const BYTE rsaPrivKeyPrime1[] = {
8165 0xe9,0x51,0xdb,0x33,0xb7,0xbf,0x8e,0xa7,0x20,0x74,0xd7,0x86,
8166 0xc5,0x3a,0x4a,0x16,0xd7,0x5e,0xed,0x3b,0xe7,0x77,0xb9,0xbf,
8167 0xd9,0xe2,0xb8,0xa6,0x2e,0xd9,0xd0,0x4e,0x53,0xbe,0x11,0x5d,
8168 0x52,0x3b,0xf0,0xca,0xe7,0x56,0xe7,0x20,0x02,0xd8,0x70,0x30,
8169 0xa8,0xc3,0x72,0xd1,0xce,0xdb,0x38,0x00,0x74,0x59,0xd2,0x2f,
8170 0xf8,0x31,0xe5,0x4d,0x6c,0xcf,0x25,0x6c,0x37,0x46,0x49,0xac,
8171 0xef,0x24,0xcd,0xc7,0x80,0x96,0xd5,0x22,0x47,0xe0,0xdf,0x33,
8172 0x0a,0x4a,0x53,0x3d,0x76,0xdb,0xf7,0x39,0x63,0x79,0xa3,0x0d,
8173 0xfa,0x8a,0x95,0xb0,0x98,0x62,0xb8,0x7f,0xc3,0xbe,0x68,0xa4,
8174 0x9f,0x7f,0x5f,0x1e,0x3b,0x48,0x7b,0x99,0x20,0xe0,0x5b,0xfc,
8175 0x4e,0xb6,0x76,0xed,0xdd,0xfe,0x5e,0xe3 };
8176 static const BYTE rsaPrivKeyPrime2[] = {
8177 0x4b,0xe6,0x2f,0xa5,0x08,0x3d,0xa9,0xf5,0x36,0x10,0x97,0x39,
8178 0xf3,0xc1,0xfb,0x86,0x48,0xaf,0x64,0xc6,0x9b,0x5f,0xe6,0xcf,
8179 0xb2,0x7b,0x39,0xa5,0x37,0x2c,0x61,0x1a,0x68,0xe2,0xe0,0xb0,
8180 0xfa,0x53,0xf1,0x7b,0x1d,0x3d,0x6b,0x70,0xa4,0x64,0x3a,0xe7,
8181 0xe1,0xe1,0xa0,0xaf,0x99,0x95,0xf2,0x4d,0x40,0x05,0x32,0xa4,
8182 0xab,0xac,0xee,0x97,0xca,0xa3,0xd6,0xe9,0xc0,0x9f,0x4d,0xb0,
8183 0xed,0x4a,0xe2,0x3a,0x29,0xe6,0xc3,0x2b,0xcd,0xa6,0xa9,0x87,
8184 0x7c,0xee,0x93,0x84,0x40,0xf2,0x40,0xae,0xc6,0x8e,0xd6,0x4a,
8185 0xaf,0xfc,0x5e,0x7d,0x9c,0x68,0x6f,0x18,0x72,0x1c,0x66,0x82,
8186 0x5d,0x66,0xaa,0x62,0x91,0xab,0xe1,0x0f,0xe9,0x4a,0x9d,0xce,
8187 0xce,0xe8,0xcf,0x6e,0xf0,0x57,0xba,0xc4 };
8188 static const BYTE rsaPrivKeyExponent1[] = {
8189 0xa1,0xca,0x03,0xc2,0xbc,0x0c,0x7b,0x61,0x6f,0x4e,0xf3,0xde,
8190 0x81,0xfb,0x44,0xa7,0x70,0xae,0xe8,0xb3,0x61,0x7a,0x86,0xac,
8191 0x7e,0xcd,0xf9,0xbc,0xe9,0x34,0x32,0x2d,0x7d,0x78,0x93,0xe2,
8192 0xac,0x87,0x45,0xe9,0xde,0x35,0x6d,0x8c,0xe0,0x16,0x09,0x9d,
8193 0x54,0xd9,0x49,0x62,0x73,0x5f,0xd7,0x5c,0x9a,0xba,0x80,0xef,
8194 0xbe,0xf5,0xda,0x9a,0x8c,0x03,0x79,0x9b,0xad,0x9e,0xff,0x0a,
8195 0x15,0x39,0x69,0xba,0x22,0x46,0xdd,0xbb,0x09,0xf9,0xa3,0x47,
8196 0x0b,0xae,0xce,0x10,0xac,0x22,0x86,0xb0,0x0a,0xf3,0x26,0x9f,
8197 0x98,0xa5,0x90,0xd4,0x94,0x0b,0xcb,0x76,0xa8,0xbf,0x26,0x76,
8198 0x01,0x5e,0x53,0x03,0x3e,0x30,0x29,0x39,0x67,0x9e,0x9f,0x54,
8199 0x93,0xa0,0xaf,0xe2,0x08,0x02,0xe7,0x86 };
8200 static const BYTE rsaPrivKeyExponent2[] = {
8201 0x85,0xfd,0x95,0x6b,0xb1,0x67,0x28,0x1d,0xe4,0xf1,0x20,0xbf,
8202 0x64,0x1d,0xf8,0x52,0xa2,0x4a,0x65,0xbd,0x98,0x55,0xf7,0x10,
8203 0x74,0x30,0x95,0x5a,0x7d,0xea,0x0a,0xc4,0xa5,0xf0,0x5a,0x5f,
8204 0xc3,0x50,0xb0,0x6b,0xa2,0x90,0xf6,0x3d,0xe6,0xfa,0xe3,0xc0,
8205 0xcb,0x14,0x6d,0xda,0x2b,0x96,0x86,0x26,0xb8,0xcb,0x2b,0xa6,
8206 0x21,0xbe,0x83,0x6a,0x5e,0xa3,0x15,0xfa,0xa5,0x7c,0xba,0xf5,
8207 0xc2,0xd9,0x51,0x3b,0x61,0x35,0xb0,0x12,0x92,0xaa,0xec,0xe6,
8208 0x52,0xf6,0x53,0xab,0x2c,0x76,0x10,0xfe,0x5d,0xd5,0xd4,0x96,
8209 0x05,0xe2,0xd9,0xae,0x22,0xb0,0x29,0x6a,0x80,0x88,0x17,0x5b,
8210 0x30,0x15,0xe6,0x20,0xab,0x19,0x11,0x48,0x1a,0x0d,0xf6,0x1b,
8211 0x9d,0x35,0x17,0x4f,0xa1,0x4a,0x5b,0x69 };
8212 static const BYTE rsaPrivKeyCoefficient[] = {
8213 0xf9,0x85,0x26,0x39,0x96,0x35,0x02,0xfb,0xd9,0xd4,0xf0,0xbd,
8214 0xcb,0xd5,0x3d,0xce,0x8b,0xb6,0x8b,0xc5,0x6c,0x11,0x44,0x1e,
8215 0x39,0x88,0x46,0x4a,0x31,0xe6,0xa1,0x3a,0x2b,0xfc,0x2a,0x05,
8216 0xa1,0x68,0x18,0x88,0xa6,0xd0,0xb1,0xc6,0x0b,0xa3,0x3e,0x68,
8217 0xb2,0x4d,0xf1,0xf2,0x1c,0x40,0xdb,0xf8,0x1a,0x44,0xf6,0x84,
8218 0x04,0x96,0xff,0xce,0x3a,0x7c,0x3c,0xd6,0x60,0xbc,0x14,0x14,
8219 0xf7,0xc1,0x9d,0xcd,0x62,0x46,0x8e,0x3e,0x47,0xb6,0x5b,0x91,
8220 0x74,0xb6,0x65,0x66,0x2a,0x13,0xdd,0x63,0x25,0x00,0xae,0x6b,
8221 0x68,0x4e,0x9c,0xc8,0x47,0x7c,0x83,0x52,0x51,0x14,0x8a,0x0f,
8222 0xa2,0x50,0xbd,0x45,0xf0,0x6b,0xbf,0x46,0x20,0xda,0xd7,0x07,
8223 0x1e,0x9a,0xec,0xe1,0x34,0x31,0xb4,0xda };
8224 static const BYTE rsaPrivKeyPrivateExponent[] = {
8225 0x11,0x90,0xb6,0x9f,0x62,0x9c,0x87,0x7e,0x9c,0x4c,0xbd,0x8c,
8226 0xf0,0xf8,0x2d,0x00,0x01,0x94,0xbc,0x68,0x39,0x13,0x3b,0x74,
8227 0x03,0x66,0xda,0xd2,0xde,0x79,0x96,0x61,0xba,0x6e,0x90,0xdf,
8228 0xed,0x25,0xdd,0x76,0xaa,0xfa,0x1d,0x15,0x65,0x99,0xba,0xf7,
8229 0x18,0xd5,0x15,0x85,0x33,0xf2,0xfd,0x60,0xb1,0x9f,0x66,0x9f,
8230 0x86,0x0c,0x69,0x06,0x5d,0x4c,0x5e,0xd8,0xf5,0x45,0x2d,0xf8,
8231 0x05,0x45,0xde,0xa4,0x71,0x58,0x81,0xce,0xe2,0xbb,0xb3,0x54,
8232 0x12,0xff,0x86,0x2d,0xd4,0xe5,0x03,0x90,0xa9,0x92,0xb9,0xe3,
8233 0x73,0xf2,0x69,0xbf,0xe2,0x75,0xab,0x59,0xfe,0x1b,0x48,0x8a,
8234 0xaf,0xdb,0xb0,0x7f,0x7e,0xb7,0x8c,0xfc,0x95,0x23,0x14,0x20,
8235 0x27,0x3d,0x74,0x4c,0x00,0xeb,0x23,0x20,0xc8,0x9c,0x2f,0x43,
8236 0x68,0x1d,0x97,0x02,0x15,0xcc,0xfc,0xde,0xda,0xe0,0x80,0xfd,
8237 0x95,0xbe,0xba,0xee,0xb3,0xd3,0xdc,0xd0,0xc2,0x63,0x16,0x40,
8238 0x97,0x04,0xa4,0xed,0x61,0x6d,0x37,0x03,0x84,0x00,0xb2,0x44,
8239 0x09,0x8b,0x6f,0xb3,0x44,0xac,0x54,0x66,0xf3,0x26,0x93,0xee,
8240 0xf7,0x91,0x76,0xa5,0x98,0xf8,0x3a,0x07,0x47,0x8b,0xdd,0x69,
8241 0x61,0x1f,0xdd,0x12,0x90,0x2e,0xe3,0xcd,0xc3,0xb7,0xc9,0x6d,
8242 0xfa,0xe8,0xa5,0x96,0x33,0x74,0xc9,0xc0,0x1f,0x3f,0x65,0xda,
8243 0x6f,0x12,0x75,0x17,0x8a,0xdb,0x4f,0x29,0xa2,0xfc,0x47,0x34,
8244 0x02,0xf6,0x86,0xcb,0x6a,0x74,0x9d,0x46,0x93,0x27,0x11,0x8c,
8245 0xef,0xd6,0xc9,0x2c,0x65,0x89,0xd6,0x78,0x98,0x32,0x03,0x69,
8246 0x5b,0xcd,0x03,0x99 };
8247 
8248 static void test_decodeRsaPrivateKey(DWORD dwEncoding)
8249 {
8250     LPBYTE buf = NULL;
8251     DWORD bufSize = 0;
8252     BOOL ret;
8253 
8254     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
8255      rsaPrivKeyDer, sizeof(rsaPrivKeyDer)-10,
8256      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
8257     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD),
8258      "Expected CRYPT_E_ASN1_EOD, got %08x\n",
8259      GetLastError());
8260 
8261     buf = NULL;
8262     bufSize = 0;
8263     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
8264      rsaPrivKeyDer, sizeof(rsaPrivKeyDer),
8265      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
8266     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
8267 
8268     if (ret)
8269     {
8270         BLOBHEADER *hdr = (BLOBHEADER *)buf;
8271         RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
8272         static const int bitlen = 2048;
8273         BYTE *modulus = (BYTE*)(rsaPubKey + 1);
8274         BYTE *prime1 = modulus + bitlen/8;
8275         BYTE *prime2 = prime1 + bitlen/16;
8276         BYTE *exponent1 = prime2 + bitlen/16;
8277         BYTE *exponent2 = exponent1 + bitlen/16;
8278         BYTE *coefficient = exponent2 + bitlen/16;
8279         BYTE *privateExponent = coefficient + bitlen/16;
8280 
8281         ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
8282             (bitlen * 9 / 16),
8283          "Wrong size %d\n", bufSize);
8284 
8285         ok(hdr->bType == PRIVATEKEYBLOB,
8286          "Expected type PRIVATEKEYBLOB (%d), got %d\n", PRIVATEKEYBLOB,
8287          hdr->bType);
8288         ok(hdr->bVersion == CUR_BLOB_VERSION,
8289          "Expected version CUR_BLOB_VERSION (%d), got %d\n",
8290          CUR_BLOB_VERSION, hdr->bVersion);
8291         ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
8292          hdr->reserved);
8293         ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
8294          "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
8295 
8296         ok(rsaPubKey->magic == 0x32415352,
8297          "Expected magic 0x32415352, got 0x%x\n", rsaPubKey->magic);
8298         ok(rsaPubKey->bitlen == bitlen,
8299          "Expected bitlen %d, got %d\n", bitlen, rsaPubKey->bitlen);
8300         ok(rsaPubKey->pubexp == 65537,
8301          "Expected pubexp 65537, got %d\n", rsaPubKey->pubexp);
8302 
8303         ok(!memcmp(modulus, rsaPrivKeyModulus, bitlen/8),
8304          "unexpected modulus\n");
8305         ok(!memcmp(prime1, rsaPrivKeyPrime1, bitlen/16),
8306          "unexpected prime1\n");
8307         ok(!memcmp(prime2, rsaPrivKeyPrime2, bitlen/16),
8308          "unexpected prime2\n");
8309         ok(!memcmp(exponent1, rsaPrivKeyExponent1, bitlen/16),
8310          "unexpected exponent1\n");
8311         ok(!memcmp(exponent2, rsaPrivKeyExponent2, bitlen/16),
8312          "unexpected exponent2\n");
8313         ok(!memcmp(coefficient, rsaPrivKeyCoefficient, bitlen/16),
8314          "unexpected coefficient\n");
8315         ok(!memcmp(privateExponent, rsaPrivKeyPrivateExponent, bitlen/8),
8316          "unexpected privateExponent\n");
8317 
8318         LocalFree(buf);
8319     }
8320 }
8321 
8322 /* Free *pInfo with HeapFree */
8323 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
8324 {
8325     BOOL ret;
8326     DWORD size = 0;
8327     HCRYPTKEY key;
8328 
8329     /* This crashes
8330     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
8331      */
8332     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
8333     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8334      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8335     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
8336      &size);
8337     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8338      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8339     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
8340      NULL, &size);
8341     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8342      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8343     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
8344      0, NULL, NULL, &size);
8345     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8346      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8347     /* Test with no key */
8348     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
8349      0, NULL, NULL, &size);
8350     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
8351      GetLastError());
8352     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
8353     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
8354     if (ret)
8355     {
8356         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
8357          NULL, 0, NULL, NULL, &size);
8358         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
8359         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
8360         if (*pInfo)
8361         {
8362             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
8363              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
8364             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
8365              GetLastError());
8366             if (ret)
8367             {
8368                 /* By default (we passed NULL as the OID) the OID is
8369                  * szOID_RSA_RSA.
8370                  */
8371                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
8372                  "Expected %s, got %s\n", szOID_RSA_RSA,
8373                  (*pInfo)->Algorithm.pszObjId);
8374             }
8375         }
8376     }
8377     CryptDestroyKey(key);
8378 }
8379 
8380 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
8381  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
8382  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
8383  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
8384  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
8385  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
8386  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
8387  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
8388  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
8389  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
8390  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
8391  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
8392  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
8393  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
8394  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
8395  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
8396  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
8397  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
8398  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
8399  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
8400  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
8401  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
8402  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
8403  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
8404  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
8405 
8406 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
8407 {
8408     BOOL ret;
8409     HCRYPTKEY key;
8410     PCCERT_CONTEXT context;
8411     DWORD dwSize;
8412     ALG_ID ai;
8413 
8414     /* These crash
8415     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
8416     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
8417     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
8418     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
8419      NULL);
8420      */
8421     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
8422     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
8423      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
8424     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
8425     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
8426      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
8427     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
8428      &key);
8429     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8430      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8431 
8432     /* Export key with standard algorithm (CALG_RSA_KEYX) */
8433     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
8434      &key);
8435     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8436 
8437     dwSize = sizeof(ai);
8438     ret = CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8439     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8440     if(ret)
8441     {
8442       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8443       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
8444     }
8445 
8446     CryptDestroyKey(key);
8447 
8448     /* Repeat with forced algorithm */
8449     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
8450      &key);
8451     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8452 
8453     dwSize = sizeof(ai);
8454     ret = CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8455     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8456     if(ret)
8457     {
8458       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8459       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
8460     }
8461 
8462     CryptDestroyKey(key);
8463 
8464     /* Test importing a public key from a certificate context */
8465     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
8466      sizeof(expiredCert));
8467     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
8468      GetLastError());
8469     if (context)
8470     {
8471         ok(!strcmp(szOID_RSA_RSA,
8472          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
8473          "Expected %s, got %s\n", szOID_RSA_RSA,
8474          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
8475         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
8476          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
8477         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8478         CryptDestroyKey(key);
8479         CertFreeCertificateContext(context);
8480     }
8481 }
8482 
8483 static const char cspName[] = "WineCryptTemp";
8484 
8485 static void testPortPublicKeyInfo(void)
8486 {
8487     HCRYPTPROV csp;
8488     BOOL ret;
8489     PCERT_PUBLIC_KEY_INFO info = NULL;
8490 
8491     /* Just in case a previous run failed, delete this thing */
8492     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8493      CRYPT_DELETEKEYSET);
8494     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8495      CRYPT_NEWKEYSET);
8496     ok(ret,"CryptAcquireContextA failed\n");
8497 
8498     testExportPublicKey(csp, &info);
8499     testImportPublicKey(csp, info);
8500 
8501     HeapFree(GetProcessHeap(), 0, info);
8502     CryptReleaseContext(csp, 0);
8503     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8504      CRYPT_DELETEKEYSET);
8505     ok(ret,"CryptAcquireContextA failed\n");
8506 }
8507 
8508 START_TEST(encode)
8509 {
8510     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
8511      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
8512     HMODULE hCrypt32;
8513     DWORD i;
8514 
8515     hCrypt32 = GetModuleHandleA("crypt32.dll");
8516     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
8517     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
8518     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
8519     {
8520         win_skip("CryptDecodeObjectEx() is not available\n");
8521         return;
8522     }
8523 
8524     for (i = 0; i < ARRAY_SIZE(encodings); i++)
8525     {
8526         test_encodeInt(encodings[i]);
8527         test_decodeInt(encodings[i]);
8528         test_encodeEnumerated(encodings[i]);
8529         test_decodeEnumerated(encodings[i]);
8530         test_encodeFiletime(encodings[i]);
8531         test_decodeFiletime(encodings[i]);
8532         test_encodeName(encodings[i]);
8533         test_decodeName(encodings[i]);
8534         test_encodeUnicodeName(encodings[i]);
8535         test_decodeUnicodeName(encodings[i]);
8536         test_encodeNameValue(encodings[i]);
8537         test_decodeNameValue(encodings[i]);
8538         test_encodeUnicodeNameValue(encodings[i]);
8539         test_decodeUnicodeNameValue(encodings[i]);
8540         test_encodeAltName(encodings[i]);
8541         test_decodeAltName(encodings[i]);
8542         test_encodeOctets(encodings[i]);
8543         test_decodeOctets(encodings[i]);
8544         test_encodeBits(encodings[i]);
8545         test_decodeBits(encodings[i]);
8546         test_encodeBasicConstraints(encodings[i]);
8547         test_decodeBasicConstraints(encodings[i]);
8548         test_encodeRsaPublicKey(encodings[i]);
8549         test_decodeRsaPublicKey(encodings[i]);
8550         test_encodeSequenceOfAny(encodings[i]);
8551         test_decodeSequenceOfAny(encodings[i]);
8552         test_encodeExtensions(encodings[i]);
8553         test_decodeExtensions(encodings[i]);
8554         test_encodePublicKeyInfo(encodings[i]);
8555         test_decodePublicKeyInfo(encodings[i]);
8556         test_encodeCertToBeSigned(encodings[i]);
8557         test_decodeCertToBeSigned(encodings[i]);
8558         test_encodeCert(encodings[i]);
8559         test_decodeCert(encodings[i]);
8560         test_encodeCRLDistPoints(encodings[i]);
8561         test_decodeCRLDistPoints(encodings[i]);
8562         test_encodeCRLIssuingDistPoint(encodings[i]);
8563         test_decodeCRLIssuingDistPoint(encodings[i]);
8564         test_encodeCRLToBeSigned(encodings[i]);
8565         test_decodeCRLToBeSigned(encodings[i]);
8566         test_encodeEnhancedKeyUsage(encodings[i]);
8567         test_decodeEnhancedKeyUsage(encodings[i]);
8568         test_encodeAuthorityKeyId(encodings[i]);
8569         test_decodeAuthorityKeyId(encodings[i]);
8570         test_encodeAuthorityKeyId2(encodings[i]);
8571         test_decodeAuthorityKeyId2(encodings[i]);
8572         test_encodeAuthorityInfoAccess(encodings[i]);
8573         test_decodeAuthorityInfoAccess(encodings[i]);
8574         test_encodeCTL(encodings[i]);
8575         test_decodeCTL(encodings[i]);
8576         test_encodePKCSContentInfo(encodings[i]);
8577         test_decodePKCSContentInfo(encodings[i]);
8578         test_encodePKCSAttribute(encodings[i]);
8579         test_decodePKCSAttribute(encodings[i]);
8580         test_encodePKCSAttributes(encodings[i]);
8581         test_decodePKCSAttributes(encodings[i]);
8582         test_encodePKCSSMimeCapabilities(encodings[i]);
8583         test_decodePKCSSMimeCapabilities(encodings[i]);
8584         test_encodePKCSSignerInfo(encodings[i]);
8585         test_decodePKCSSignerInfo(encodings[i]);
8586         test_encodeCMSSignerInfo(encodings[i]);
8587         test_decodeCMSSignerInfo(encodings[i]);
8588         test_encodeNameConstraints(encodings[i]);
8589         test_decodeNameConstraints(encodings[i]);
8590         test_encodePolicyQualifierUserNotice(encodings[i]);
8591         test_decodePolicyQualifierUserNotice(encodings[i]);
8592         test_encodeCertPolicies(encodings[i]);
8593         test_decodeCertPolicies(encodings[i]);
8594         test_encodeCertPolicyMappings(encodings[i]);
8595         test_decodeCertPolicyMappings(encodings[i]);
8596         test_encodeCertPolicyConstraints(encodings[i]);
8597         test_decodeCertPolicyConstraints(encodings[i]);
8598         test_decodeRsaPrivateKey(encodings[i]);
8599     }
8600     testPortPublicKeyInfo();
8601 }
8602