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 < sizeof(ints) / sizeof(ints[0]); 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 < sizeof(bigInts) / sizeof(bigInts[0]); 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 < sizeof(bigUInts) / sizeof(bigUInts[0]); 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 < sizeof(ints) / sizeof(ints[0]); 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 < sizeof(bigInts) / sizeof(bigInts[0]); 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 < sizeof(bigUInts) / sizeof(bigUInts[0]); 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 < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
381     {
382         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); 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 < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
414     {
415         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); 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 < sizeof(times) / sizeof(times[0]); 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 < sizeof(times) / sizeof(times[0]); 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 < sizeof(otherTimes) / sizeof(otherTimes[0]); 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 < sizeof(bogusTimes) / sizeof(bogusTimes[0]); 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 = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
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 && strlen(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 = sizeof(attrs) / sizeof(attrs[0]);
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 = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
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 = sizeof(attrs) / sizeof(attrs[0]);
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 < sizeof(nameValues) / sizeof(nameValues[0]); 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 < sizeof(nameValues) / sizeof(nameValues[0]); 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 < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); 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 < sizeof(unicodeResults) / sizeof(unicodeResults[0]); 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 < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); 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 < sizeof(unicodeResults) / sizeof(unicodeResults[0]); 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 < sizeof(tests) / sizeof(tests[0]); 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 < sizeof(tests) / sizeof(tests[0]); 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 < sizeof(bits) / sizeof(bits[0]); 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 < sizeof(bits) / sizeof(bits[0]); 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 < sizeof(constraints2) / sizeof(constraints2[0]); 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 < sizeof(constraints2) / sizeof(constraints2[0]); 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 < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); 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 < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); 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[sizeof(ints) / sizeof(ints[0])];
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 < sizeof(ints) / sizeof(ints[0]); i++)
2602     {
2603         blobs[i].cbData = ints[i].encoded[1] + 2;
2604         blobs[i].pbData = (BYTE *)ints[i].encoded;
2605     }
2606     seq.cValue = sizeof(ints) / sizeof(ints[0]);
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 == sizeof(ints) / sizeof(ints[0]),
2650          "Wrong elements %d\n", seq->cValue);
2651         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2652         {
2653             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2654              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2655              seq->rgValue[i].cbData);
2656             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2657              ints[i].encoded[1] + 2), "Unexpected value\n");
2658         }
2659         LocalFree(buf);
2660     }
2661     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2662      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2663      &bufSize);
2664     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2665     if (ret)
2666     {
2667         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2668 
2669         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2670          "Wrong elements %d\n", seq->cValue);
2671         /* Just check the first element since it's all that changed */
2672         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2673          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2674          seq->rgValue[0].cbData);
2675         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2676          times[0].encodedTime[1] + 2), "Unexpected value\n");
2677         LocalFree(buf);
2678     }
2679 }
2680 
2681 struct encodedExtensions
2682 {
2683     CERT_EXTENSIONS exts;
2684     const BYTE *encoded;
2685 };
2686 
2687 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2688 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2689 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2690 static CERT_EXTENSION criticalExt =
2691  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2692 static CERT_EXTENSION nonCriticalExt =
2693  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2694 static CHAR oid_short[] = "1.1";
2695 static CERT_EXTENSION extWithShortOid =
2696  { oid_short, FALSE, { 0, NULL } };
2697 
2698 static const BYTE ext0[] = { 0x30,0x00 };
2699 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2700                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2701 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2702                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2703 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2704 
2705 static const struct encodedExtensions exts[] = {
2706  { { 0, NULL }, ext0 },
2707  { { 1, &criticalExt }, ext1 },
2708  { { 1, &nonCriticalExt }, ext2 },
2709  { { 1, &extWithShortOid }, ext3 }
2710 };
2711 
2712 static void test_encodeExtensions(DWORD dwEncoding)
2713 {
2714     DWORD i;
2715 
2716     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2717     {
2718         BOOL ret;
2719         BYTE *buf = NULL;
2720         DWORD bufSize = 0;
2721 
2722         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2723          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2724         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2725         if (ret)
2726         {
2727             ok(bufSize == exts[i].encoded[1] + 2,
2728              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2729             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2730              "Unexpected value\n");
2731             LocalFree(buf);
2732         }
2733     }
2734 }
2735 
2736 static void test_decodeExtensions(DWORD dwEncoding)
2737 {
2738     DWORD i;
2739 
2740     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2741     {
2742         BOOL ret;
2743         BYTE *buf = NULL;
2744         DWORD bufSize = 0;
2745 
2746         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2747          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2748          NULL, &buf, &bufSize);
2749         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2750         if (ret)
2751         {
2752             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2753             DWORD j;
2754 
2755             ok(ext->cExtension == exts[i].exts.cExtension,
2756              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2757              ext->cExtension);
2758             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2759             {
2760                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2761                  exts[i].exts.rgExtension[j].pszObjId),
2762                  "Expected OID %s, got %s\n",
2763                  exts[i].exts.rgExtension[j].pszObjId,
2764                  ext->rgExtension[j].pszObjId);
2765                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2766                  exts[i].exts.rgExtension[j].Value.pbData,
2767                  exts[i].exts.rgExtension[j].Value.cbData),
2768                  "Unexpected value\n");
2769             }
2770             LocalFree(buf);
2771         }
2772         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2773          exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
2774         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2775         buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);
2776         if (buf)
2777         {
2778             ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2779              exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, buf, &bufSize);
2780             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2781             HeapFree(GetProcessHeap(), 0, buf);
2782         }
2783     }
2784 }
2785 
2786 /* MS encodes public key info with a NULL if the algorithm identifier's
2787  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2788  * it encodes them by omitting the algorithm parameters.  It accepts either
2789  * form for decoding.
2790  */
2791 struct encodedPublicKey
2792 {
2793     CERT_PUBLIC_KEY_INFO info;
2794     const BYTE *encoded;
2795     const BYTE *encodedNoNull;
2796     CERT_PUBLIC_KEY_INFO decoded;
2797 };
2798 
2799 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2800  0xe, 0xf };
2801 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2802 
2803 static const unsigned char bin64[] = {
2804     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2805 static const unsigned char bin65[] = {
2806     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2807 static const unsigned char bin66[] = {
2808     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2809 static const unsigned char bin67[] = {
2810     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2811 static const unsigned char bin68[] = {
2812     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2813     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2814 static const unsigned char bin69[] = {
2815     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2816     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2817 static const unsigned char bin70[] = {
2818     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2819     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2820     0x0f};
2821 static const unsigned char bin71[] = {
2822     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2823     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2824     0x0f};
2825 static unsigned char bin72[] = { 0x05,0x00};
2826 
2827 static CHAR oid_bogus[] = "1.2.3",
2828             oid_rsa[]   = szOID_RSA;
2829 
2830 static const struct encodedPublicKey pubKeys[] = {
2831  /* with a bogus OID */
2832  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2833   bin64, bin65,
2834   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2835  /* some normal keys */
2836  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2837   bin66, bin67,
2838   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2839  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2840   bin68, bin69,
2841   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2842  /* with add'l parameters--note they must be DER-encoded */
2843  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2844   (BYTE *)aKey, 0 } },
2845   bin70, bin71,
2846   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2847   (BYTE *)aKey, 0 } } },
2848 };
2849 
2850 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2851 {
2852     DWORD i;
2853 
2854     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2855     {
2856         BOOL ret;
2857         BYTE *buf = NULL;
2858         DWORD bufSize = 0;
2859 
2860         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2861          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2862          &bufSize);
2863         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2864          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2865         if (ret)
2866         {
2867             ok(bufSize == pubKeys[i].encoded[1] + 2,
2868              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2869             if (bufSize == pubKeys[i].encoded[1] + 2)
2870                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2871                  "Unexpected value\n");
2872             LocalFree(buf);
2873         }
2874     }
2875 }
2876 
2877 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2878  const CERT_PUBLIC_KEY_INFO *got)
2879 {
2880     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2881      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2882      got->Algorithm.pszObjId);
2883     ok(expected->Algorithm.Parameters.cbData ==
2884      got->Algorithm.Parameters.cbData,
2885      "Expected parameters of %d bytes, got %d\n",
2886      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2887     if (expected->Algorithm.Parameters.cbData)
2888         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2889          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2890          "Unexpected algorithm parameters\n");
2891     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2892      "Expected public key of %d bytes, got %d\n",
2893      expected->PublicKey.cbData, got->PublicKey.cbData);
2894     if (expected->PublicKey.cbData)
2895         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2896          got->PublicKey.cbData), "Unexpected public key value\n");
2897 }
2898 
2899 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2900 {
2901     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2902      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2903      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2904      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2905     DWORD i;
2906     BOOL ret;
2907     BYTE *buf = NULL;
2908     DWORD bufSize = 0;
2909 
2910     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2911     {
2912         /* The NULL form decodes to the decoded member */
2913         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2914          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2915          NULL, &buf, &bufSize);
2916         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2917         if (ret)
2918         {
2919             comparePublicKeyInfo(&pubKeys[i].decoded,
2920              (CERT_PUBLIC_KEY_INFO *)buf);
2921             LocalFree(buf);
2922         }
2923         /* The non-NULL form decodes to the original */
2924         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2925          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2926          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2927         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2928         if (ret)
2929         {
2930             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2931             LocalFree(buf);
2932         }
2933     }
2934     /* Test with bogus (not valid DER) parameters */
2935     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2936      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2937      NULL, &buf, &bufSize);
2938     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2939      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2940      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2941      GetLastError());
2942 }
2943 
2944 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2945  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2946  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2947  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2948  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2949 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2950  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2951  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2952  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2953  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2954 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2955  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2956  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2957  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2958  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2959 static const BYTE v4Cert[] = {
2960 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2961 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2962 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2963 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2964 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2965  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2966  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2967  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2968  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2969  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2970  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2971 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2972  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2973  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2974  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2975  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2976  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2977  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2978 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2979  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2980  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2981  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2982  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2983  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2984  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2985  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2986  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2987  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2988 static const BYTE v1CertWithPubKey[] = {
2989 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2990 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2991 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2992 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2993 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2994 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2995 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2996 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2997 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2998 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2999 0x01,0x01 };
3000 static const BYTE v1CertWithPubKeyNoNull[] = {
3001 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
3002 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
3003 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
3004 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3005 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
3006 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
3007 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
3008 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
3009 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
3010 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3011 static const BYTE v1CertWithSubjectKeyId[] = {
3012 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
3013 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
3014 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
3015 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3016 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
3017 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
3018 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
3019 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
3020 0x4c,0x61,0x6e,0x67,0x00 };
3021 static const BYTE v1CertWithIssuerUniqueId[] = {
3022 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
3023 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
3024 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3025 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
3026 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
3027 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
3028 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
3029 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
3030 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3031 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
3032 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
3033 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
3034 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
3035 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
3036 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
3037 0x01,0x01,0xff,0x02,0x01,0x01 };
3038 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
3039 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
3040 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
3041 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
3042 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3043 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
3044 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
3045 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
3046 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
3047 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
3048 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
3049 0xff,0x02,0x01,0x01 };
3050 
3051 static const BYTE serialNum[] = { 0x01 };
3052 
3053 static void test_encodeCertToBeSigned(DWORD dwEncoding)
3054 {
3055     BOOL ret;
3056     BYTE *buf = NULL;
3057     DWORD size = 0;
3058     CERT_INFO info = { 0 };
3059     static char oid_rsa_rsa[] = szOID_RSA_RSA;
3060     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
3061     CERT_EXTENSION ext;
3062 
3063     if (0)
3064     {
3065         /* Test with NULL pvStructInfo (crashes on win9x) */
3066         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
3067          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3068         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3069          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3070     }
3071     /* Test with a V1 cert */
3072     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3073      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3074     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3075      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3076     if (ret)
3077     {
3078         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3079          v1Cert[1] + 2, size);
3080         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3081         LocalFree(buf);
3082     }
3083     /* Test v2 cert */
3084     info.dwVersion = CERT_V2;
3085     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3086      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3087     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3088      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3089     if (ret)
3090     {
3091         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3092         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3093         LocalFree(buf);
3094     }
3095     /* Test v3 cert */
3096     info.dwVersion = CERT_V3;
3097     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3098      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3099     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3100      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3101     if (ret)
3102     {
3103         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3104         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3105         LocalFree(buf);
3106     }
3107     /* A v4 cert? */
3108     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3109     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3110      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3111     if (ret)
3112     {
3113         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3114         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3115         LocalFree(buf);
3116     }
3117     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3118      * API doesn't prevent it)
3119      */
3120     info.dwVersion = CERT_V1;
3121     info.cExtension = 1;
3122     info.rgExtension = &criticalExt;
3123     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3124      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3125     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3126      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3127     if (ret)
3128     {
3129         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3130         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3131         LocalFree(buf);
3132     }
3133     /* test v1 cert with a serial number */
3134     info.SerialNumber.cbData = sizeof(serialNum);
3135     info.SerialNumber.pbData = (BYTE *)serialNum;
3136     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3137      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3138     if (ret)
3139     {
3140         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3141         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3142         LocalFree(buf);
3143     }
3144     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3145     info.dwVersion = CERT_V1;
3146     info.cExtension = 0;
3147     info.IssuerUniqueId.cbData = sizeof(serialNum);
3148     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3149     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3150      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3151     ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3152      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3153     if (ret)
3154     {
3155         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3156         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3157          "Got unexpected value\n");
3158         LocalFree(buf);
3159     }
3160     /* Test v1 cert with an issuer name, a subject name, and a serial number */
3161     info.IssuerUniqueId.cbData = 0;
3162     info.IssuerUniqueId.pbData = NULL;
3163     info.cExtension = 1;
3164     info.rgExtension = &criticalExt;
3165     info.Issuer.cbData = sizeof(encodedCommonName);
3166     info.Issuer.pbData = (BYTE *)encodedCommonName;
3167     info.Subject.cbData = sizeof(encodedCommonName);
3168     info.Subject.pbData = (BYTE *)encodedCommonName;
3169     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3170      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3171     if (ret)
3172     {
3173         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3174         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3175         LocalFree(buf);
3176     }
3177     /* Add a public key */
3178     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3179     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3180     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3181     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3182      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3183     if (ret)
3184     {
3185         ok(size == sizeof(v1CertWithPubKey) ||
3186          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3187         if (size == sizeof(v1CertWithPubKey))
3188             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3189         else if (size == sizeof(v1CertWithPubKeyNoNull))
3190             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3191              "Got unexpected value\n");
3192         LocalFree(buf);
3193     }
3194     /* Again add an issuer unique id */
3195     info.IssuerUniqueId.cbData = sizeof(serialNum);
3196     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3197     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3198      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3199     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3200     if (ret)
3201     {
3202         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3203          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3204          "Wrong size %d\n", size);
3205         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3206             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3207              size), "unexpected value\n");
3208         else if (size ==
3209          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3210             ok(!memcmp(buf,
3211              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3212              "unexpected value\n");
3213         LocalFree(buf);
3214     }
3215     /* Remove the public key, and add a subject key identifier extension */
3216     info.IssuerUniqueId.cbData = 0;
3217     info.IssuerUniqueId.pbData = NULL;
3218     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3219     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3220     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3221     ext.pszObjId = oid_subject_key_identifier;
3222     ext.fCritical = FALSE;
3223     ext.Value.cbData = sizeof(octetCommonNameValue);
3224     ext.Value.pbData = octetCommonNameValue;
3225     info.cExtension = 1;
3226     info.rgExtension = &ext;
3227     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3228      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3229     if (ret)
3230     {
3231         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3232         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3233         LocalFree(buf);
3234     }
3235 }
3236 
3237 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3238 {
3239     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3240      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3241     BOOL ret;
3242     BYTE *buf = NULL;
3243     DWORD size = 0, i;
3244 
3245     /* Test with NULL pbEncoded */
3246     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3247      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3248     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3249      GetLastError() == OSS_BAD_ARG /* Win9x */),
3250      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3251     if (0)
3252     {
3253         /* Crashes on win9x */
3254         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3255          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3256         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3257          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3258     }
3259     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3260      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3261      * serial number, an issuer, a subject, and a public key.
3262      */
3263     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3264     {
3265         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3266          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3267          &buf, &size);
3268         ok(!ret, "Expected failure\n");
3269     }
3270     /* The following succeeds, even though v1 certs are not allowed to have
3271      * extensions.
3272      */
3273     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3274      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3275      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3276     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3277     if (ret)
3278     {
3279         CERT_INFO *info = (CERT_INFO *)buf;
3280 
3281         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3282         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3283          info->dwVersion);
3284         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3285          info->cExtension);
3286         LocalFree(buf);
3287     }
3288     /* The following also succeeds, even though V1 certs are not allowed to
3289      * have issuer unique ids.
3290      */
3291     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3292      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3293      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3294      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3295     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3296     if (ret)
3297     {
3298         CERT_INFO *info = (CERT_INFO *)buf;
3299 
3300         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3301         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3302          info->dwVersion);
3303         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3304          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3305         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3306          "unexpected issuer unique id value\n");
3307         LocalFree(buf);
3308     }
3309     /* Now check with serial number, subject and issuer specified */
3310     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3311      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3312     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3313     if (ret)
3314     {
3315         CERT_INFO *info = (CERT_INFO *)buf;
3316 
3317         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3318         ok(info->SerialNumber.cbData == 1,
3319          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3320         ok(*info->SerialNumber.pbData == *serialNum,
3321          "Expected serial number %d, got %d\n", *serialNum,
3322          *info->SerialNumber.pbData);
3323         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3324          "Wrong size %d\n", info->Issuer.cbData);
3325         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3326          "Unexpected issuer\n");
3327         ok(info->Subject.cbData == sizeof(encodedCommonName),
3328          "Wrong size %d\n", info->Subject.cbData);
3329         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3330          info->Subject.cbData), "Unexpected subject\n");
3331         LocalFree(buf);
3332     }
3333     /* Check again with pub key specified */
3334     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3335      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3336      &buf, &size);
3337     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3338     if (ret)
3339     {
3340         CERT_INFO *info = (CERT_INFO *)buf;
3341 
3342         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3343         ok(info->SerialNumber.cbData == 1,
3344          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3345         ok(*info->SerialNumber.pbData == *serialNum,
3346          "Expected serial number %d, got %d\n", *serialNum,
3347          *info->SerialNumber.pbData);
3348         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3349          "Wrong size %d\n", info->Issuer.cbData);
3350         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3351          "Unexpected issuer\n");
3352         ok(info->Subject.cbData == sizeof(encodedCommonName),
3353          "Wrong size %d\n", info->Subject.cbData);
3354         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3355          info->Subject.cbData), "Unexpected subject\n");
3356         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3357          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3358          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3359         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3360          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3361         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3362          sizeof(aKey)), "Unexpected public key\n");
3363         LocalFree(buf);
3364     }
3365 }
3366 
3367 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3368  0xe, 0xf };
3369 
3370 static const BYTE signedBigCert[] = {
3371  ASN_SEQUENCE,0x81,147,
3372    ASN_SEQUENCE,122,
3373      ASN_INTEGER,1, 0x01,
3374      ASN_SEQUENCE,2,
3375        ASN_OBJECTIDENTIFIER,0,
3376      ASN_SEQUENCE,21,
3377        0x31,19,
3378          ASN_SEQUENCE,17,
3379            ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03,
3380            0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
3381      ASN_SEQUENCE,34,
3382        0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3383        0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3384      ASN_SEQUENCE,21,
3385        0x31,19,
3386          ASN_SEQUENCE,17,
3387            ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03,
3388            0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
3389      ASN_SEQUENCE,7,
3390        ASN_SEQUENCE,2,
3391          ASN_OBJECTIDENTIFIER,0,
3392        ASN_BITS,1, 0x00,
3393    0xa3,22,
3394      ASN_SEQUENCE,20,
3395        ASN_SEQUENCE,18,
3396          ASN_OBJECTIDENTIFIER,3, 0x55,0x1d,0x13,
3397          0x01,1, 0xff,
3398          ASN_OCTETSTRING,8, 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,
3399      ASN_SEQUENCE,2,
3400        ASN_OBJECTIDENTIFIER,0,
3401  ASN_BITS,17, 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,
3402               0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00
3403 };
3404 
3405 static const BYTE signedBigCertWithIndefiniteSeq[] = {
3406  ASN_SEQUENCE,0x81,151,
3407    ASN_SEQUENCE,126,
3408      ASN_INTEGER,1, 0x01,
3409      ASN_SEQUENCE,2,
3410        ASN_OBJECTIDENTIFIER,0,
3411      ASN_SEQUENCE,21,
3412        0x31,19,
3413          ASN_SEQUENCE,17,
3414            ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03,
3415            0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
3416      ASN_SEQUENCE,0x80,
3417        0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3418        0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3419      0,0,
3420      ASN_SEQUENCE,21,
3421        0x31,19,
3422          ASN_SEQUENCE,17,
3423            ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03,
3424            0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
3425      ASN_SEQUENCE,0x80,
3426        ASN_SEQUENCE,2,
3427          ASN_OBJECTIDENTIFIER,0,
3428        ASN_BITS,1, 0x00,
3429      0,0,
3430    0xa3,22,
3431      ASN_SEQUENCE,20,
3432        ASN_SEQUENCE,18,
3433          ASN_OBJECTIDENTIFIER,3, 0x55,0x1d,0x13,
3434          0x01,1, 0xff,
3435          ASN_OCTETSTRING,8, 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,
3436      ASN_SEQUENCE,2,
3437        ASN_OBJECTIDENTIFIER,0,
3438  ASN_BITS,17, 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,
3439               0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00
3440 };
3441 
3442 static void test_encodeCert(DWORD dwEncoding)
3443 {
3444     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3445      * also that bigCert is a NULL-terminated string, so don't count its
3446      * last byte (otherwise the signed cert won't decode.)
3447      */
3448     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3449      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3450     BOOL ret;
3451     BYTE *buf = NULL;
3452     DWORD bufSize = 0;
3453 
3454     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3455      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3456     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3457     if (ret)
3458     {
3459         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3460         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3461         LocalFree(buf);
3462     }
3463 }
3464 
3465 static void test_decodeCert(DWORD dwEncoding)
3466 {
3467     BOOL ret;
3468     BYTE *buf = NULL;
3469     DWORD size = 0;
3470 
3471     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3472      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3473     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3474     if (ret)
3475     {
3476         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3477 
3478         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3479          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3480         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3481          "Unexpected cert\n");
3482         ok(info->Signature.cbData == sizeof(hash),
3483          "Wrong signature size %d\n", info->Signature.cbData);
3484         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3485          "Unexpected signature\n");
3486         LocalFree(buf);
3487     }
3488     /* A signed cert decodes as a CERT_INFO too */
3489     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3490      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3491     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3492     if (ret)
3493     {
3494         CERT_INFO *info = (CERT_INFO *)buf;
3495 
3496         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3497         ok(info->SerialNumber.cbData == 1,
3498          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3499         ok(*info->SerialNumber.pbData == *serialNum,
3500          "Expected serial number %d, got %d\n", *serialNum,
3501          *info->SerialNumber.pbData);
3502         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3503          "Wrong size %d\n", info->Issuer.cbData);
3504         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3505          "Unexpected issuer\n");
3506         ok(info->Subject.cbData == sizeof(encodedCommonName),
3507          "Wrong size %d\n", info->Subject.cbData);
3508         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3509          info->Subject.cbData), "Unexpected subject\n");
3510         LocalFree(buf);
3511     }
3512     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCertWithIndefiniteSeq,
3513      sizeof(signedBigCertWithIndefiniteSeq), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3514     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3515     if (ret)
3516     {
3517         CERT_INFO *info = (CERT_INFO *)buf;
3518 
3519         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3520         ok(info->SerialNumber.cbData == 1,
3521          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3522         ok(*info->SerialNumber.pbData == *serialNum,
3523          "Expected serial number %d, got %d\n", *serialNum,
3524          *info->SerialNumber.pbData);
3525         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3526          "Wrong size %d\n", info->Issuer.cbData);
3527         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3528          "Unexpected issuer\n");
3529         ok(info->Subject.cbData == sizeof(encodedCommonName),
3530          "Wrong size %d\n", info->Subject.cbData);
3531         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3532          info->Subject.cbData), "Unexpected subject\n");
3533         LocalFree(buf);
3534     }
3535 }
3536 
3537 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3538 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3539  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3540  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3541 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3542  0x00, 0x03 };
3543 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3544  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3545  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3546 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3547  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3548  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3549  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3550  0x2e, 0x6f, 0x72, 0x67 };
3551 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3552  CRL_REASON_AFFILIATION_CHANGED;
3553 
3554 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3555 {
3556     CRL_DIST_POINTS_INFO info = { 0 };
3557     CRL_DIST_POINT point = { { 0 } };
3558     CERT_ALT_NAME_ENTRY entry = { 0 };
3559     BOOL ret;
3560     BYTE *buf = NULL;
3561     DWORD size = 0;
3562 
3563     /* Test with an empty info */
3564     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3565      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3566     ok(!ret && GetLastError() == E_INVALIDARG,
3567      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3568     /* Test with one empty dist point */
3569     info.cDistPoint = 1;
3570     info.rgDistPoint = &point;
3571     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3572      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3573     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3574     if (ret)
3575     {
3576         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3577         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3578         LocalFree(buf);
3579     }
3580     /* A dist point with an invalid name */
3581     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3582     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3583     U(entry).pwszURL = (LPWSTR)nihongoURL;
3584     U(point.DistPointName).FullName.cAltEntry = 1;
3585     U(point.DistPointName).FullName.rgAltEntry = &entry;
3586     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3587      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3588     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3589      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3590     /* The first invalid character is at index 7 */
3591     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3592      "Expected invalid char at index 7, got %d\n",
3593      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3594     /* A dist point with (just) a valid name */
3595     U(entry).pwszURL = (LPWSTR)url;
3596     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3597      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3598     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3599     if (ret)
3600     {
3601         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3602         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3603         LocalFree(buf);
3604     }
3605     /* A dist point with (just) reason flags */
3606     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3607     point.ReasonFlags.cbData = sizeof(crlReason);
3608     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3609     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3610      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3611     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3612     if (ret)
3613     {
3614         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3615         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3616         LocalFree(buf);
3617     }
3618     /* A dist point with just an issuer */
3619     point.ReasonFlags.cbData = 0;
3620     point.CRLIssuer.cAltEntry = 1;
3621     point.CRLIssuer.rgAltEntry = &entry;
3622     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3623      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3624     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3625     if (ret)
3626     {
3627         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3628         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3629         LocalFree(buf);
3630     }
3631     /* A dist point with both a name and an issuer */
3632     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3633     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3634      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3635     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3636     if (ret)
3637     {
3638         ok(size == sizeof(distPointWithUrlAndIssuer),
3639          "Wrong size %d\n", size);
3640         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3641         LocalFree(buf);
3642     }
3643 }
3644 
3645 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3646 {
3647     BOOL ret;
3648     BYTE *buf = NULL;
3649     DWORD size = 0;
3650     PCRL_DIST_POINTS_INFO info;
3651     PCRL_DIST_POINT point;
3652     PCERT_ALT_NAME_ENTRY entry;
3653 
3654     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3655      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3656      &buf, &size);
3657     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3658     if (ret)
3659     {
3660         info = (PCRL_DIST_POINTS_INFO)buf;
3661         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3662          "Wrong size %d\n", size);
3663         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3664          info->cDistPoint);
3665         point = info->rgDistPoint;
3666         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3667          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3668          point->DistPointName.dwDistPointNameChoice);
3669         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3670         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3671         LocalFree(buf);
3672     }
3673     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3674      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3675      &buf, &size);
3676     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3677     if (ret)
3678     {
3679         info = (PCRL_DIST_POINTS_INFO)buf;
3680         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3681          "Wrong size %d\n", size);
3682         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3683          info->cDistPoint);
3684         point = info->rgDistPoint;
3685         ok(point->DistPointName.dwDistPointNameChoice ==
3686          CRL_DIST_POINT_FULL_NAME,
3687          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3688          point->DistPointName.dwDistPointNameChoice);
3689         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3690          "Expected 1 name entry, got %d\n",
3691          U(point->DistPointName).FullName.cAltEntry);
3692         entry = U(point->DistPointName).FullName.rgAltEntry;
3693         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3694          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3695         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3696         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3697         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3698         LocalFree(buf);
3699     }
3700     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3701      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3702      NULL, &buf, &size);
3703     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3704     if (ret)
3705     {
3706         info = (PCRL_DIST_POINTS_INFO)buf;
3707         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3708          "Wrong size %d\n", size);
3709         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3710          info->cDistPoint);
3711         point = info->rgDistPoint;
3712         ok(point->DistPointName.dwDistPointNameChoice ==
3713          CRL_DIST_POINT_NO_NAME,
3714          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3715          point->DistPointName.dwDistPointNameChoice);
3716         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3717          "Expected reason length\n");
3718         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3719          "Unexpected reason\n");
3720         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3721         LocalFree(buf);
3722     }
3723     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3724      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3725      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3726     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3727     if (ret)
3728     {
3729         info = (PCRL_DIST_POINTS_INFO)buf;
3730         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3731          "Wrong size %d\n", size);
3732         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3733          info->cDistPoint);
3734         point = info->rgDistPoint;
3735         ok(point->DistPointName.dwDistPointNameChoice ==
3736          CRL_DIST_POINT_FULL_NAME,
3737          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3738          point->DistPointName.dwDistPointNameChoice);
3739         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3740          "Expected 1 name entry, got %d\n",
3741          U(point->DistPointName).FullName.cAltEntry);
3742         entry = U(point->DistPointName).FullName.rgAltEntry;
3743         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3744          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3745         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3746         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3747         ok(point->CRLIssuer.cAltEntry == 1,
3748          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3749         entry = point->CRLIssuer.rgAltEntry;
3750         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3751          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3752         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3753         LocalFree(buf);
3754     }
3755     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3756      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3757      NULL, NULL, &size);
3758     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3759     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3760     if (buf)
3761     {
3762         ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3763          distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3764          NULL, buf, &size);
3765         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3766         HeapFree(GetProcessHeap(), 0, buf);
3767     }
3768 }
3769 
3770 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3771 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3772 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3773  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3774  0x67 };
3775 
3776 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3777 {
3778     BOOL ret;
3779     BYTE *buf = NULL;
3780     DWORD size = 0;
3781     CRL_ISSUING_DIST_POINT point = { { 0 } };
3782     CERT_ALT_NAME_ENTRY entry;
3783 
3784     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3785      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3786     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3787     {
3788         skip("no X509_ISSUING_DIST_POINT encode support\n");
3789         return;
3790     }
3791     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3792      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3793     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3794      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3795     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3796     if (ret)
3797     {
3798         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3799         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3800         LocalFree(buf);
3801     }
3802     /* nonsensical flags */
3803     point.fOnlyContainsUserCerts = TRUE;
3804     point.fOnlyContainsCACerts = TRUE;
3805     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3806      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3807     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3808     if (ret)
3809     {
3810         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3811         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3812         LocalFree(buf);
3813     }
3814     /* unimplemented name type */
3815     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3816     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3817     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3818      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3819     ok(!ret && GetLastError() == E_INVALIDARG,
3820      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3821     /* empty name */
3822     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3823     U(point.DistPointName).FullName.cAltEntry = 0;
3824     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3825      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3826     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3827     if (ret)
3828     {
3829         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3830         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3831         LocalFree(buf);
3832     }
3833     /* name with URL entry */
3834     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3835     U(entry).pwszURL = (LPWSTR)url;
3836     U(point.DistPointName).FullName.cAltEntry = 1;
3837     U(point.DistPointName).FullName.rgAltEntry = &entry;
3838     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3839      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3840     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3841     if (ret)
3842     {
3843         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3844         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3845         LocalFree(buf);
3846     }
3847 }
3848 
3849 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3850  const CERT_ALT_NAME_ENTRY *got)
3851 {
3852     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3853      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3854      got->dwAltNameChoice);
3855     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3856     {
3857         switch (got->dwAltNameChoice)
3858         {
3859         case CERT_ALT_NAME_RFC822_NAME:
3860         case CERT_ALT_NAME_DNS_NAME:
3861         case CERT_ALT_NAME_EDI_PARTY_NAME:
3862         case CERT_ALT_NAME_URL:
3863         case CERT_ALT_NAME_REGISTERED_ID:
3864             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3865              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3866              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3867              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3868              "Unexpected name\n");
3869             break;
3870         case CERT_ALT_NAME_X400_ADDRESS:
3871         case CERT_ALT_NAME_DIRECTORY_NAME:
3872         case CERT_ALT_NAME_IP_ADDRESS:
3873             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3874                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3875             ok(!memcmp(U(*got).IPAddress.pbData, U(*expected).IPAddress.pbData,
3876                        U(*got).IPAddress.cbData), "Unexpected value\n");
3877             break;
3878         }
3879     }
3880 }
3881 
3882 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3883  const CERT_ALT_NAME_INFO *got)
3884 {
3885     DWORD i;
3886 
3887     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3888      expected->cAltEntry, got->cAltEntry);
3889     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3890         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3891 }
3892 
3893 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3894  const CRL_DIST_POINT_NAME *got)
3895 {
3896     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3897      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3898     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3899         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3900 }
3901 
3902 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3903  const CRL_ISSUING_DIST_POINT *got)
3904 {
3905     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3906     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3907      "Unexpected fOnlyContainsUserCerts\n");
3908     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3909      "Unexpected fOnlyContainsCACerts\n");
3910     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3911      "Unexpected reason flags\n");
3912     ok(got->fIndirectCRL == expected->fIndirectCRL,
3913      "Unexpected fIndirectCRL\n");
3914 }
3915 
3916 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3917 {
3918     BOOL ret;
3919     BYTE *buf = NULL;
3920     DWORD size = 0;
3921     CRL_ISSUING_DIST_POINT point = { { 0 } };
3922 
3923     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3924      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3925      &buf, &size);
3926     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3927     {
3928         skip("no X509_ISSUING_DIST_POINT decode support\n");
3929         return;
3930     }
3931     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3932     if (ret)
3933     {
3934         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3935         LocalFree(buf);
3936     }
3937     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3938      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3939      &buf, &size);
3940     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3941     if (ret)
3942     {
3943         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3944         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3945         LocalFree(buf);
3946     }
3947     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3948      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3949      &buf, &size);
3950     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3951     if (ret)
3952     {
3953         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3954         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3955         U(point.DistPointName).FullName.cAltEntry = 0;
3956         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3957         LocalFree(buf);
3958     }
3959     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3960      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3961     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3962     if (ret)
3963     {
3964         CERT_ALT_NAME_ENTRY entry;
3965 
3966         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3967         U(entry).pwszURL = (LPWSTR)url;
3968         U(point.DistPointName).FullName.cAltEntry = 1;
3969         U(point.DistPointName).FullName.rgAltEntry = &entry;
3970         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3971         LocalFree(buf);
3972     }
3973 }
3974 
3975 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3976  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3977  0x30, 0x5a };
3978 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3979  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3980  0x30, 0x30, 0x30, 0x30, 0x5a };
3981 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3982  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3983  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3984  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3985  0x5a };
3986 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3987  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3988  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3989  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3990  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3991  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3992 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3993  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3994  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3995  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3996  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3997  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3998 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3999  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
4000  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4001  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
4002  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
4003  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
4004  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
4005 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
4006  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4007  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
4008  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
4009  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
4010  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
4011  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
4012 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
4013  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
4014  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
4015  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
4016  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
4017  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
4018  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
4019 
4020 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
4021 {
4022     BOOL ret;
4023     BYTE *buf = NULL;
4024     DWORD size = 0;
4025     CRL_INFO info = { 0 };
4026     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
4027 
4028     /* Test with a V1 CRL */
4029     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4030      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4031     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
4032      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4033     if (ret)
4034     {
4035         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
4036         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
4037         LocalFree(buf);
4038     }
4039     /* Test v2 CRL */
4040     info.dwVersion = CRL_V2;
4041     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4042      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4043     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
4044      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4045     if (ret)
4046     {
4047         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
4048          v2CRL[1] + 2, size);
4049         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
4050         LocalFree(buf);
4051     }
4052     /* v1 CRL with a name */
4053     info.dwVersion = CRL_V1;
4054     info.Issuer.cbData = sizeof(encodedCommonName);
4055     info.Issuer.pbData = (BYTE *)encodedCommonName;
4056     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4057      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4058     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4059     if (ret)
4060     {
4061         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
4062         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
4063         LocalFree(buf);
4064     }
4065     if (0)
4066     {
4067         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
4068         info.cCRLEntry = 1;
4069         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4070          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4071         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4072          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
4073     }
4074     /* now set an empty entry */
4075     info.cCRLEntry = 1;
4076     info.rgCRLEntry = &entry;
4077     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4078      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4079     if (ret)
4080     {
4081         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
4082          "Wrong size %d\n", size);
4083         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
4084          "Got unexpected value\n");
4085         LocalFree(buf);
4086     }
4087     /* an entry with a serial number */
4088     entry.SerialNumber.cbData = sizeof(serialNum);
4089     entry.SerialNumber.pbData = (BYTE *)serialNum;
4090     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4091      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4092     if (ret)
4093     {
4094         ok(size == sizeof(v1CRLWithIssuerAndEntry),
4095          "Wrong size %d\n", size);
4096         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
4097          "Got unexpected value\n");
4098         LocalFree(buf);
4099     }
4100     /* an entry with an extension */
4101     entry.cExtension = 1;
4102     entry.rgExtension = &criticalExt;
4103     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4104      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4105     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4106     if (ret)
4107     {
4108         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
4109         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
4110         LocalFree(buf);
4111     }
4112     /* a CRL with an extension */
4113     entry.cExtension = 0;
4114     info.cExtension = 1;
4115     info.rgExtension = &criticalExt;
4116     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4117      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4118     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4119     if (ret)
4120     {
4121         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
4122         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
4123         LocalFree(buf);
4124     }
4125     /* a v2 CRL with an extension, this time non-critical */
4126     info.dwVersion = CRL_V2;
4127     info.rgExtension = &nonCriticalExt;
4128     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
4129      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4130     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4131     if (ret)
4132     {
4133         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
4134         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
4135         LocalFree(buf);
4136     }
4137 }
4138 
4139 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
4140  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4141  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
4142  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
4143  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
4144  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
4145  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
4146  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
4147  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
4148  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
4149  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
4150  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
4151  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
4152  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
4153  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
4154  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
4155  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
4156  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
4157  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
4158  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
4159  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
4160  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
4161  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
4162  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
4163  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4164  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4165  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4166  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4167  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4168  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4169  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4170  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4171  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4172  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4173  0xcd };
4174 static const BYTE verisignCRLWithLotsOfEntries[] = {
4175 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4176 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4177 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4178 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4179 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4180 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4181 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4182 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4183 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4184 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4185 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4186 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4187 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4188 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4189 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4190 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4191 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4192 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4193 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4194 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4195 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4196 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4197 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4198 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4199 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4200 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4201 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4202 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4203 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4204 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4205 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4206 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4207 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4208 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4209 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4210 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4211 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4212 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4213 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4214 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4215 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4216 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4217 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4218 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4219 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4220 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4221 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4222 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4223 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4224 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4225 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4226 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4227 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4228 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4229 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4230 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4231 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4232 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4233 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4234 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4235 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4236 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4237 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4238 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4239 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4240 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4241 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4242 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4243 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4244 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4245 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4246 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4247 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4248 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4249 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4250 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4251 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4252 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4253 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4254 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4255 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4256 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4257 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4258 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4259 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4260 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4261 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4262 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4263 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4264 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4265 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4266 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4267 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4268 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4269 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4270 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4271 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4272 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4273 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4274 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4275 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4276 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4277 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4278 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4279 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4280 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4281 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4282 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4283 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4284 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4285 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4286 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4287 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4288 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4289 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4290 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4291 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4292 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4293 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4294 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4295 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4296 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4297 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4298 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4299 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4300 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4301 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4302 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4303 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4304 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4305 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4306 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4307 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4308 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4309 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4310 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4311 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4312 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4313 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4314 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4315 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4316 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4317 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4318 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4319 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4320 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4321 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4322 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4323 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4324 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4325 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4326 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4327 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4328 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4329 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4330 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4331 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4332 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4333 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4334 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4335 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4336 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4337 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4338 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4339 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4340 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4341 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4342 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4343 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4344 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4345 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4346 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4347 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4348 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4349 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4350 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4351 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4352 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4353 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4354 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4355 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4356 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4357 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4358 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4359 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4360 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4361 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4362 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4363 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4364 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4365 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4366 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4367 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4368 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4369 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4370 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4371 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4372 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4373 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4374 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4375 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4376 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4377 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4378 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4379 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4380 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4381 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4382 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4383 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4384 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4385 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4386 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4387 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4388 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4389 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4390 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4391 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4392 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4393 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4394 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4395 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4396 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4397 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4398 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4399 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4400 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4401 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4402 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4403 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4404 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4405 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4406 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4407 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4408 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4409 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4410 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4411 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4412 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4413 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4414 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4415 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4416 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4417 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4418 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4419 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4420 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4421 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4422 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4423 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4424 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4425 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4426 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4427 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4428 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4429 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4430 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4431 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4432 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4433 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4434 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4435 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4436 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4437 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4438 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4439 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4440 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4441 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4442 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4443 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4444 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4445 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4446 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4447 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4448 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4449 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4450 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4451 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4452 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4453 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4454 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4455 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4456 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4457 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4458 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4459 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4460 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4461 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4462 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4463 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4464 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4465 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4466 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4467 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4468 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4469 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4470 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4471 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4472 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4473 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4474 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4475 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4476 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4477 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4478 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4479 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4480 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4481 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4482 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4483 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4484 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4485 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4486 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4487 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4488 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4489 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4490 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4491 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4492 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4493 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4494 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4495 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4496 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4497 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4498 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4499 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4500 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4501 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4502 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4503 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4504 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4505 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4506 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4507 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4508 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4509 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4510 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4511 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4512 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4513 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4514 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4515 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4516 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4517 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4518 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4519 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4520 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4521 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4522 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4523 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4524 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4525 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4526 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4527 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4528 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4529 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4530 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4531 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4532 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4533 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4534 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4535 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4536 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4537 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4538 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4539 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4540 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4541 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4542 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4543 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4544 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4545 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4546 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4547 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4548 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4549 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4550 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4551 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4552 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4553 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4554 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4555 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4556 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4557 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4558 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4559 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4560 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4561 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4562 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4563 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4564 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4565 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4566 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4567 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4568 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4569 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4570 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4571 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4572 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4573 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4574 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4575 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4576 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4577 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4578 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4579 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4580 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4581 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4582 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4583 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4584 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4585 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4586 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4587 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4588 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4589 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4590 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4591 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4592 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4593 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4594 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4595 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4596 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4597 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4598 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4599 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4600 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4601 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4602 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4603 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4604 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4605 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4606 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4607 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4608 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4609 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4610 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4611 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4612 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4613 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4614 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4615 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4616 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4617 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4618 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4619 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4620 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4621 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4622 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4623 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4624 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4625 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4626 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4627 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4628 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4629 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4630 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4631 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4632 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4633 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4634 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4635 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4636 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4637 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4638 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4639 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4640 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4641 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4642 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4643 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4644 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4645 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4646 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4647 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4648 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4649 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4650 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4651 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4652 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4653 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4654 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4655 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4656 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4657 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4658 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4659 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4660 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4661 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4662 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4663 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4664 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4665 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4666 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4667 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4668 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4669 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4670 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4671 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4672 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4673 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4674 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4675 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4676 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4677 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4678 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4679 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4680 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4681 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4682 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4683 
4684 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4685 {
4686     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4687     BOOL ret;
4688     BYTE *buf = NULL;
4689     DWORD size = 0, i;
4690 
4691     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4692     {
4693         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4694          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4695          &buf, &size);
4696         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4697          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4698          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4699          GetLastError());
4700     }
4701     /* at a minimum, a CRL must contain an issuer: */
4702     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4703      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4704      &buf, &size);
4705     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4706     if (ret)
4707     {
4708         CRL_INFO *info = (CRL_INFO *)buf;
4709 
4710         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4711         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4712          info->cCRLEntry);
4713         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4714          "Wrong issuer size %d\n", info->Issuer.cbData);
4715         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4716          "Unexpected issuer\n");
4717         LocalFree(buf);
4718     }
4719     /* check decoding with an empty CRL entry */
4720     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4721      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4722      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4723     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4724      GetLastError() == OSS_DATA_ERROR /* Win9x */ ||
4725      GetLastError() == CRYPT_E_BAD_ENCODE /* Win8 */),
4726      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4727      GetLastError());
4728     /* with a real CRL entry */
4729     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4730      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4731      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4732     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4733     if (ret)
4734     {
4735         CRL_INFO *info = (CRL_INFO *)buf;
4736         CRL_ENTRY *entry;
4737 
4738         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4739         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4740          info->cCRLEntry);
4741         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4742         entry = info->rgCRLEntry;
4743         ok(entry->SerialNumber.cbData == 1,
4744          "Expected serial number size 1, got %d\n",
4745          entry->SerialNumber.cbData);
4746         ok(*entry->SerialNumber.pbData == *serialNum,
4747          "Expected serial number %d, got %d\n", *serialNum,
4748          *entry->SerialNumber.pbData);
4749         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4750          "Wrong issuer size %d\n", info->Issuer.cbData);
4751         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4752          "Unexpected issuer\n");
4753         LocalFree(buf);
4754     }
4755     /* a real CRL from verisign that has extensions */
4756     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4757      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4758      NULL, &buf, &size);
4759     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4760     if (ret)
4761     {
4762         CRL_INFO *info = (CRL_INFO *)buf;
4763 
4764         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4765         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4766          info->cCRLEntry);
4767         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4768         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4769          info->cExtension);
4770         LocalFree(buf);
4771     }
4772     /* another real CRL from verisign that has lots of entries */
4773     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4774      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4775      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4776     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4777     if (ret)
4778     {
4779         CRL_INFO *info = (CRL_INFO *)buf;
4780 
4781         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4782         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4783          info->cCRLEntry);
4784         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4785          info->cExtension);
4786         LocalFree(buf);
4787     }
4788     /* and finally, with an extension */
4789     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4790      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4791      NULL, &buf, &size);
4792     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4793     if (ret)
4794     {
4795         CRL_INFO *info = (CRL_INFO *)buf;
4796         CRL_ENTRY *entry;
4797 
4798         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4799         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4800          info->cCRLEntry);
4801         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4802         entry = info->rgCRLEntry;
4803         ok(entry->SerialNumber.cbData == 1,
4804          "Expected serial number size 1, got %d\n",
4805          entry->SerialNumber.cbData);
4806         ok(*entry->SerialNumber.pbData == *serialNum,
4807          "Expected serial number %d, got %d\n", *serialNum,
4808          *entry->SerialNumber.pbData);
4809         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4810          "Wrong issuer size %d\n", info->Issuer.cbData);
4811         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4812          "Unexpected issuer\n");
4813         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4814          info->cExtension);
4815         LocalFree(buf);
4816     }
4817     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4818      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4819      NULL, &buf, &size);
4820     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4821     if (ret)
4822     {
4823         CRL_INFO *info = (CRL_INFO *)buf;
4824 
4825         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4826          info->cExtension);
4827         LocalFree(buf);
4828     }
4829 }
4830 
4831 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4832  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4833 static const BYTE encodedUsage[] = {
4834  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4835  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4836  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4837 
4838 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4839 {
4840     BOOL ret;
4841     BYTE *buf = NULL;
4842     DWORD size = 0;
4843     CERT_ENHKEY_USAGE usage;
4844 
4845     /* Test with empty usage */
4846     usage.cUsageIdentifier = 0;
4847     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4848      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4849     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4850     if (ret)
4851     {
4852         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4853         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4854         LocalFree(buf);
4855     }
4856     /* Test with a few usages */
4857     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4858     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4859     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4860      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4861     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4862     if (ret)
4863     {
4864         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4865         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4866         LocalFree(buf);
4867     }
4868 }
4869 
4870 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4871 {
4872     BOOL ret;
4873     LPBYTE buf = NULL;
4874     DWORD size = 0;
4875 
4876     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4877      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4878      &buf, &size);
4879     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4880     if (ret)
4881     {
4882         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4883 
4884         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4885          "Wrong size %d\n", size);
4886         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4887          usage->cUsageIdentifier);
4888         LocalFree(buf);
4889     }
4890     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4891      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4892      &buf, &size);
4893     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4894     if (ret)
4895     {
4896         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4897         DWORD i;
4898 
4899         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4900          "Wrong size %d\n", size);
4901         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4902          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4903         for (i = 0; i < usage->cUsageIdentifier; i++)
4904             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4905              "Expected OID %s, got %s\n", keyUsages[i],
4906              usage->rgpszUsageIdentifier[i]);
4907         LocalFree(buf);
4908     }
4909     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4910      encodedUsage, sizeof(encodedUsage), 0, NULL, NULL, &size);
4911     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4912     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4913     if (buf)
4914     {
4915         ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4916          encodedUsage, sizeof(encodedUsage), 0, NULL, buf, &size);
4917         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4918         HeapFree(GetProcessHeap(), 0, buf);
4919     }
4920 }
4921 
4922 static BYTE keyId[] = { 1,2,3,4 };
4923 static const BYTE authorityKeyIdWithId[] = {
4924  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4925 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4926  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4927  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4928 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4929 
4930 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4931 {
4932     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4933     BOOL ret;
4934     BYTE *buf = NULL;
4935     DWORD size = 0;
4936 
4937     /* Test with empty id */
4938     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4939      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4940     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4941     if (ret)
4942     {
4943         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4944         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4945         LocalFree(buf);
4946     }
4947     /* With just a key id */
4948     info.KeyId.cbData = sizeof(keyId);
4949     info.KeyId.pbData = keyId;
4950     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4951      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4952     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4953     if (ret)
4954     {
4955         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4956         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4957         LocalFree(buf);
4958     }
4959     /* With just an issuer */
4960     info.KeyId.cbData = 0;
4961     info.CertIssuer.cbData = sizeof(encodedCommonName);
4962     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4963     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4964      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4965     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4966     if (ret)
4967     {
4968         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4969          size);
4970         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4971         LocalFree(buf);
4972     }
4973     /* With just a serial number */
4974     info.CertIssuer.cbData = 0;
4975     info.CertSerialNumber.cbData = sizeof(serialNum);
4976     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4977     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4978      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4979     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4980     if (ret)
4981     {
4982         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4983          size);
4984         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4985         LocalFree(buf);
4986     }
4987 }
4988 
4989 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4990 {
4991     BOOL ret;
4992     LPBYTE buf = NULL;
4993     DWORD size = 0;
4994 
4995     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4996      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4997      &buf, &size);
4998     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4999     if (ret)
5000     {
5001         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
5002 
5003         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
5004          size);
5005         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5006         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
5007         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
5008         LocalFree(buf);
5009     }
5010     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
5011      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5012      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5013     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5014     if (ret)
5015     {
5016         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
5017 
5018         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
5019          size);
5020         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5021         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5022          "Unexpected key id\n");
5023         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
5024         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
5025         LocalFree(buf);
5026     }
5027     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
5028      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
5029      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5030     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5031     if (ret)
5032     {
5033         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
5034 
5035         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
5036          size);
5037         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5038         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
5039          "Unexpected issuer len\n");
5040         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
5041          sizeof(encodedCommonName)), "Unexpected issuer\n");
5042         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
5043         LocalFree(buf);
5044     }
5045     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
5046      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5047      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5048     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5049     if (ret)
5050     {
5051         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
5052 
5053         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
5054          size);
5055         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5056         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
5057         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
5058          "Unexpected serial number len\n");
5059         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
5060          "Unexpected serial number\n");
5061         LocalFree(buf);
5062     }
5063 }
5064 
5065 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
5066  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
5067  0x6f,0x72,0x67 };
5068 
5069 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
5070 {
5071     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
5072     CERT_ALT_NAME_ENTRY entry = { 0 };
5073     BOOL ret;
5074     BYTE *buf = NULL;
5075     DWORD size = 0;
5076 
5077     /* Test with empty id */
5078     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5079      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5080     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5081     if (ret)
5082     {
5083         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
5084         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
5085         LocalFree(buf);
5086     }
5087     /* With just a key id */
5088     info.KeyId.cbData = sizeof(keyId);
5089     info.KeyId.pbData = keyId;
5090     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5091      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5092     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5093     if (ret)
5094     {
5095         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
5096          size);
5097         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
5098         LocalFree(buf);
5099     }
5100     /* With a bogus issuer name */
5101     info.KeyId.cbData = 0;
5102     info.AuthorityCertIssuer.cAltEntry = 1;
5103     info.AuthorityCertIssuer.rgAltEntry = &entry;
5104     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5105      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5106     ok(!ret && GetLastError() == E_INVALIDARG,
5107      "Expected E_INVALIDARG, got %08x\n", GetLastError());
5108     /* With an issuer name */
5109     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
5110     U(entry).pwszURL = (LPWSTR)url;
5111     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5112      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5113     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5114     if (ret)
5115     {
5116         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
5117          size);
5118         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
5119          "Unexpected value\n");
5120         LocalFree(buf);
5121     }
5122     /* With just a serial number */
5123     info.AuthorityCertIssuer.cAltEntry = 0;
5124     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
5125     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
5126     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
5127      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5128     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5129     if (ret)
5130     {
5131         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
5132          size);
5133         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
5134         LocalFree(buf);
5135     }
5136 }
5137 
5138 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
5139 {
5140     BOOL ret;
5141     LPBYTE buf = NULL;
5142     DWORD size = 0;
5143 
5144     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5145      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5146      &buf, &size);
5147     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5148     if (ret)
5149     {
5150         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5151 
5152         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5153          size);
5154         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5155         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5156          "Expected no issuer name entries\n");
5157         ok(info->AuthorityCertSerialNumber.cbData == 0,
5158          "Expected no serial number\n");
5159         LocalFree(buf);
5160     }
5161     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5162      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5163      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5164     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5165     if (ret)
5166     {
5167         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5168 
5169         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5170          size);
5171         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5172         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5173          "Unexpected key id\n");
5174         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5175          "Expected no issuer name entries\n");
5176         ok(info->AuthorityCertSerialNumber.cbData == 0,
5177          "Expected no serial number\n");
5178         LocalFree(buf);
5179     }
5180     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5181      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5182      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5183     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5184     if (ret)
5185     {
5186         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5187 
5188         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5189          size);
5190         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5191         ok(info->AuthorityCertIssuer.cAltEntry == 1,
5192          "Expected 1 issuer entry, got %d\n",
5193          info->AuthorityCertIssuer.cAltEntry);
5194         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5195          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5196          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5197         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5198          url), "Unexpected URL\n");
5199         ok(info->AuthorityCertSerialNumber.cbData == 0,
5200          "Expected no serial number\n");
5201         LocalFree(buf);
5202     }
5203     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5204      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5205      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5206     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5207     if (ret)
5208     {
5209         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5210 
5211         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5212          size);
5213         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5214         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5215          "Expected no issuer name entries\n");
5216         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5217          "Unexpected serial number len\n");
5218         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5219          sizeof(serialNum)), "Unexpected serial number\n");
5220         LocalFree(buf);
5221     }
5222 }
5223 
5224 static const BYTE authorityInfoAccessWithUrl[] = {
5225 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5226 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5227 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5228 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5229 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5230 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5231 
5232 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5233 {
5234     static char oid1[] = "1.2.3";
5235     static char oid2[] = "1.5.6";
5236     BOOL ret;
5237     BYTE *buf = NULL;
5238     DWORD size = 0;
5239     CERT_ACCESS_DESCRIPTION accessDescription[2];
5240     CERT_AUTHORITY_INFO_ACCESS aia;
5241 
5242     memset(accessDescription, 0, sizeof(accessDescription));
5243     aia.cAccDescr = 0;
5244     aia.rgAccDescr = NULL;
5245     /* Having no access descriptions is allowed */
5246     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5247      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5248     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5249     if (ret)
5250     {
5251         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5252         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5253         LocalFree(buf);
5254         buf = NULL;
5255     }
5256     /* It can't have an empty access method */
5257     aia.cAccDescr = 1;
5258     aia.rgAccDescr = accessDescription;
5259     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5260      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5261     ok(!ret && (GetLastError() == E_INVALIDARG ||
5262      GetLastError() == OSS_LIMITED /* Win9x */),
5263      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5264     /* It can't have an empty location */
5265     accessDescription[0].pszAccessMethod = oid1;
5266     SetLastError(0xdeadbeef);
5267     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5268      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5269     ok(!ret && GetLastError() == E_INVALIDARG,
5270      "expected E_INVALIDARG, got %08x\n", GetLastError());
5271     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5272     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5273     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5274      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5275     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5276     if (ret)
5277     {
5278         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5279          size);
5280         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5281          "unexpected value\n");
5282         LocalFree(buf);
5283         buf = NULL;
5284     }
5285     accessDescription[1].pszAccessMethod = oid2;
5286     accessDescription[1].AccessLocation.dwAltNameChoice =
5287      CERT_ALT_NAME_IP_ADDRESS;
5288     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5289      sizeof(encodedIPAddr);
5290     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5291      (LPBYTE)encodedIPAddr;
5292     aia.cAccDescr = 2;
5293     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5294      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5295     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5296     if (ret)
5297     {
5298         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5299          "unexpected size %d\n", size);
5300         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5301          "unexpected value\n");
5302         LocalFree(buf);
5303         buf = NULL;
5304     }
5305 }
5306 
5307 static void compareAuthorityInfoAccess(LPCSTR header,
5308  const CERT_AUTHORITY_INFO_ACCESS *expected,
5309  const CERT_AUTHORITY_INFO_ACCESS *got)
5310 {
5311     DWORD i;
5312 
5313     ok(expected->cAccDescr == got->cAccDescr,
5314      "%s: expected %d access descriptions, got %d\n", header,
5315      expected->cAccDescr, got->cAccDescr);
5316     for (i = 0; i < expected->cAccDescr; i++)
5317     {
5318         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5319          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5320          header, i, expected->rgAccDescr[i].pszAccessMethod,
5321          got->rgAccDescr[i].pszAccessMethod);
5322         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5323          &got->rgAccDescr[i].AccessLocation);
5324     }
5325 }
5326 
5327 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5328 {
5329     static char oid1[] = "1.2.3";
5330     static char oid2[] = "1.5.6";
5331     BOOL ret;
5332     LPBYTE buf = NULL;
5333     DWORD size = 0;
5334 
5335     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5336      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5337      &buf, &size);
5338     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5339     if (ret)
5340     {
5341         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5342 
5343         compareAuthorityInfoAccess("empty AIA", &aia,
5344          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5345         LocalFree(buf);
5346         buf = NULL;
5347     }
5348     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5349      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5350      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5351     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5352     if (ret)
5353     {
5354         CERT_ACCESS_DESCRIPTION accessDescription;
5355         CERT_AUTHORITY_INFO_ACCESS aia;
5356 
5357         accessDescription.pszAccessMethod = oid1;
5358         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5359         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5360         aia.cAccDescr = 1;
5361         aia.rgAccDescr = &accessDescription;
5362         compareAuthorityInfoAccess("AIA with URL", &aia,
5363          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5364         LocalFree(buf);
5365         buf = NULL;
5366     }
5367     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5368      authorityInfoAccessWithUrlAndIPAddr,
5369      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5370      NULL, &buf, &size);
5371     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5372     if (ret)
5373     {
5374         CERT_ACCESS_DESCRIPTION accessDescription[2];
5375         CERT_AUTHORITY_INFO_ACCESS aia;
5376 
5377         accessDescription[0].pszAccessMethod = oid1;
5378         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5379         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5380         accessDescription[1].pszAccessMethod = oid2;
5381         accessDescription[1].AccessLocation.dwAltNameChoice =
5382          CERT_ALT_NAME_IP_ADDRESS;
5383         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5384          sizeof(encodedIPAddr);
5385         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5386          (LPBYTE)encodedIPAddr;
5387         aia.cAccDescr = 2;
5388         aia.rgAccDescr = accessDescription;
5389         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5390          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5391         LocalFree(buf);
5392         buf = NULL;
5393     }
5394     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5395      authorityInfoAccessWithUrlAndIPAddr,
5396      sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, NULL, &size);
5397     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5398     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
5399     if (buf)
5400     {
5401         ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5402          authorityInfoAccessWithUrlAndIPAddr,
5403          sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, buf, &size);
5404         ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5405         HeapFree(GetProcessHeap(), 0, buf);
5406     }
5407 }
5408 
5409 static const BYTE emptyCTL[] = {
5410 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5411 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5412 static const BYTE emptyCTLWithVersion1[] = {
5413 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5414 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5415 static const BYTE ctlWithUsageIdentifier[] = {
5416 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5417 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5418 static const BYTE ctlWithListIdentifier[] = {
5419 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5420 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5421 static const BYTE ctlWithSequenceNumber[] = {
5422 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5423 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5424 static const BYTE ctlWithThisUpdate[] = {
5425 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5426 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5427 static const BYTE ctlWithThisAndNextUpdate[] = {
5428 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5429 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5430 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5431 static const BYTE ctlWithAlgId[] = {
5432 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5433 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5434 static const BYTE ctlWithBogusEntry[] = {
5435 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5436 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5437 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5438 static const BYTE ctlWithOneEntry[] = {
5439 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5440 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5441 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5442 static const BYTE ctlWithTwoEntries[] = {
5443 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5444 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5445 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5446 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5447 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5448 
5449 static void test_encodeCTL(DWORD dwEncoding)
5450 {
5451     static char oid1[] = "1.2.3";
5452     static char oid2[] = "1.5.6";
5453     char *pOid1 = oid1;
5454     BOOL ret;
5455     BYTE *buf = NULL;
5456     DWORD size = 0;
5457     CTL_INFO info;
5458     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5459     CTL_ENTRY ctlEntry[2];
5460     CRYPT_ATTRIBUTE attr1, attr2;
5461     CRYPT_ATTR_BLOB value1, value2;
5462 
5463     memset(&info, 0, sizeof(info));
5464     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5465      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5466     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5467     if (ret)
5468     {
5469         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5470         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5471         LocalFree(buf);
5472         buf = NULL;
5473     }
5474     info.dwVersion = 1;
5475     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5476      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5477     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5478     if (ret)
5479     {
5480         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5481         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5482         LocalFree(buf);
5483         buf = NULL;
5484     }
5485     info.dwVersion = 0;
5486     info.SubjectUsage.cUsageIdentifier = 1;
5487     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5488     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5489      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5490     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5491     if (ret)
5492     {
5493         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5494          size);
5495         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5496         LocalFree(buf);
5497         buf = NULL;
5498     }
5499     info.SubjectUsage.cUsageIdentifier = 0;
5500     info.ListIdentifier.cbData = sizeof(serialNum);
5501     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5502     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5503      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5504     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5505     if (ret)
5506     {
5507         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5508         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5509         LocalFree(buf);
5510         buf = NULL;
5511     }
5512     info.ListIdentifier.cbData = 0;
5513     info.SequenceNumber.cbData = sizeof(serialNum);
5514     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5515     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5516      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5517     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5518     if (ret)
5519     {
5520         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5521          size);
5522         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5523         LocalFree(buf);
5524         buf = NULL;
5525     }
5526     info.SequenceNumber.cbData = 0;
5527     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5528     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5529      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5530     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5531     if (ret)
5532     {
5533         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5534         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5535         LocalFree(buf);
5536         buf = NULL;
5537     }
5538     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5539     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5540      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5541     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5542     if (ret)
5543     {
5544         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5545          size);
5546         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5547         LocalFree(buf);
5548         buf = NULL;
5549     }
5550     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5551     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5552     info.SubjectAlgorithm.pszObjId = oid2;
5553     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5554      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5555     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5556     if (ret)
5557     {
5558         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5559         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5560         LocalFree(buf);
5561         buf = NULL;
5562     }
5563     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5564      * (see tests below) but it'll encode fine.
5565      */
5566     info.SubjectAlgorithm.pszObjId = NULL;
5567     value1.cbData = sizeof(serialNum);
5568     value1.pbData = (LPBYTE)serialNum;
5569     attr1.pszObjId = oid1;
5570     attr1.cValue = 1;
5571     attr1.rgValue = &value1;
5572     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5573     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5574     ctlEntry[0].cAttribute = 1;
5575     ctlEntry[0].rgAttribute = &attr1;
5576     info.cCTLEntry = 1;
5577     info.rgCTLEntry = ctlEntry;
5578     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5579      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5580     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5581     if (ret)
5582     {
5583         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5584         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5585         LocalFree(buf);
5586         buf = NULL;
5587     }
5588     value1.cbData = sizeof(emptySequence);
5589     value1.pbData = (LPBYTE)emptySequence;
5590     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5591      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5592     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5593     if (ret)
5594     {
5595         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5596         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5597         LocalFree(buf);
5598         buf = NULL;
5599     }
5600     value2.cbData = sizeof(encodedIPAddr);
5601     value2.pbData = (LPBYTE)encodedIPAddr;
5602     attr2.pszObjId = oid2;
5603     attr2.cValue = 1;
5604     attr2.rgValue = &value2;
5605     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5606     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5607     ctlEntry[1].cAttribute = 1;
5608     ctlEntry[1].rgAttribute = &attr2;
5609     info.cCTLEntry = 2;
5610     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5611      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5612     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5613     if (ret)
5614     {
5615         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5616         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5617         LocalFree(buf);
5618         buf = NULL;
5619     }
5620 }
5621 
5622 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5623  const CTL_INFO *got)
5624 {
5625     DWORD i, j, k;
5626 
5627     ok(expected->dwVersion == got->dwVersion,
5628      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5629      got->dwVersion);
5630     ok(expected->SubjectUsage.cUsageIdentifier ==
5631      got->SubjectUsage.cUsageIdentifier,
5632      "%s: expected %d usage identifiers, got %d\n", header,
5633      expected->SubjectUsage.cUsageIdentifier,
5634      got->SubjectUsage.cUsageIdentifier);
5635     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5636         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5637          got->SubjectUsage.rgpszUsageIdentifier[i]),
5638          "%s[%d]: expected %s, got %s\n", header, i,
5639          expected->SubjectUsage.rgpszUsageIdentifier[i],
5640          got->SubjectUsage.rgpszUsageIdentifier[i]);
5641     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5642      "%s: expected list identifier of %d bytes, got %d\n", header,
5643      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5644     if (expected->ListIdentifier.cbData)
5645         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5646          expected->ListIdentifier.cbData),
5647          "%s: unexpected list identifier value\n", header);
5648     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5649      "%s: expected sequence number of %d bytes, got %d\n", header,
5650      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5651     if (expected->SequenceNumber.cbData)
5652         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5653          expected->SequenceNumber.cbData),
5654          "%s: unexpected sequence number value\n", header);
5655     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5656      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5657      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5658      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5659     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5660      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5661      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5662      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5663     if (expected->SubjectAlgorithm.pszObjId &&
5664      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5665         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5666          expected->SubjectAlgorithm.pszObjId);
5667     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5668         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5669          got->SubjectAlgorithm.pszObjId),
5670          "%s: expected subject algorithm %s, got %s\n", header,
5671          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5672     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5673      got->SubjectAlgorithm.Parameters.cbData,
5674      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5675      expected->SubjectAlgorithm.Parameters.cbData,
5676      got->SubjectAlgorithm.Parameters.cbData);
5677     if (expected->SubjectAlgorithm.Parameters.cbData)
5678         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5679          got->SubjectAlgorithm.Parameters.pbData,
5680          expected->SubjectAlgorithm.Parameters.cbData),
5681          "%s: unexpected subject algorithm parameter value\n", header);
5682     ok(expected->cCTLEntry == got->cCTLEntry,
5683      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5684      got->cCTLEntry);
5685     for (i = 0; i < expected->cCTLEntry; i++)
5686     {
5687         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5688          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5689          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5690          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5691          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5692         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5693             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5694              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5695              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5696              "%s[%d]: unexpected subject identifier value\n",
5697              header, i);
5698         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5699         {
5700             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5701              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5702              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5703              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5704              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5705             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5706             {
5707                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5708                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5709                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5710                  header, i, j, k,
5711                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5712                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5713                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5714                     ok(!memcmp(
5715                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5716                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5717                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5718                      "%s[%d][%d][%d]: unexpected value\n",
5719                      header, i, j, k);
5720             }
5721         }
5722     }
5723     ok(expected->cExtension == got->cExtension,
5724      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5725      got->cExtension);
5726     for (i = 0; i < expected->cExtension; i++)
5727     {
5728         ok(!strcmp(expected->rgExtension[i].pszObjId,
5729          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5730          header, i, expected->rgExtension[i].pszObjId,
5731          got->rgExtension[i].pszObjId);
5732         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5733          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5734          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5735         ok(expected->rgExtension[i].Value.cbData ==
5736          got->rgExtension[i].Value.cbData,
5737          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5738          header, i, expected->rgExtension[i].Value.cbData,
5739          got->rgExtension[i].Value.cbData);
5740         if (expected->rgExtension[i].Value.cbData)
5741             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5742              got->rgExtension[i].Value.pbData,
5743              expected->rgExtension[i].Value.cbData),
5744              "%s[%d]: unexpected extension value\n", header, i);
5745     }
5746 }
5747 
5748 static const BYTE signedCTL[] = {
5749 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5750 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5751 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5752 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5753 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5754 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5755 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5756 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5757 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5758 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5759 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5760 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5761 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5762 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5763 static const BYTE signedCTLWithCTLInnerContent[] = {
5764 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5765 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5766 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5767 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5768 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5769 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5770 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5771 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5772 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5773 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5774 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5775 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5776 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5777 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5778 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5779 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5780 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5781 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5782 0x57,0x6c,0x0b,0x47,0xb8 };
5783 
5784 static void test_decodeCTL(DWORD dwEncoding)
5785 {
5786     static char oid1[] = "1.2.3";
5787     static char oid2[] = "1.5.6";
5788     static BYTE nullData[] = { 5,0 };
5789     char *pOid1 = oid1;
5790     BOOL ret;
5791     BYTE *buf = NULL;
5792     DWORD size = 0;
5793     CTL_INFO info;
5794     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5795     CTL_ENTRY ctlEntry[2];
5796     CRYPT_ATTRIBUTE attr1, attr2;
5797     CRYPT_ATTR_BLOB value1, value2;
5798 
5799     memset(&info, 0, sizeof(info));
5800     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5801      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5802     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5803     if (ret)
5804     {
5805         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5806         LocalFree(buf);
5807         buf = NULL;
5808     }
5809     info.dwVersion = 1;
5810     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5811      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5812      &size);
5813     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5814     if (ret)
5815     {
5816         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5817         LocalFree(buf);
5818         buf = NULL;
5819     }
5820     info.dwVersion = 0;
5821     info.SubjectUsage.cUsageIdentifier = 1;
5822     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5823     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5824      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5825      &buf, &size);
5826     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5827     if (ret)
5828     {
5829         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5830         LocalFree(buf);
5831         buf = NULL;
5832     }
5833     info.SubjectUsage.cUsageIdentifier = 0;
5834     info.ListIdentifier.cbData = sizeof(serialNum);
5835     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5836     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5837      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5838     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5839     if (ret)
5840     {
5841         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5842         LocalFree(buf);
5843         buf = NULL;
5844     }
5845     info.ListIdentifier.cbData = 0;
5846     info.SequenceNumber.cbData = sizeof(serialNum);
5847     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5848     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5849      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5850     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5851     if (ret)
5852     {
5853         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5854         LocalFree(buf);
5855         buf = NULL;
5856     }
5857     info.SequenceNumber.cbData = 0;
5858     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5859     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5860      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5861     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5862     if (ret)
5863     {
5864         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5865         LocalFree(buf);
5866         buf = NULL;
5867     }
5868     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5869     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5870      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5871      &buf, &size);
5872     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5873     if (ret)
5874     {
5875         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5876         LocalFree(buf);
5877         buf = NULL;
5878     }
5879     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5880     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5881     info.SubjectAlgorithm.pszObjId = oid2;
5882     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5883     info.SubjectAlgorithm.Parameters.pbData = nullData;
5884     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5885      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5886     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5887     if (ret)
5888     {
5889         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5890         LocalFree(buf);
5891         buf = NULL;
5892     }
5893     SetLastError(0xdeadbeef);
5894     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5895      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5896     ok(!ret &&
5897      (GetLastError() == CRYPT_E_ASN1_EOD ||
5898       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5899       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5900      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5901      GetLastError());
5902     info.SubjectAlgorithm.Parameters.cbData = 0;
5903     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5904     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5905     info.SubjectAlgorithm.pszObjId = NULL;
5906     value1.cbData = sizeof(emptySequence);
5907     value1.pbData = (LPBYTE)emptySequence;
5908     attr1.pszObjId = oid1;
5909     attr1.cValue = 1;
5910     attr1.rgValue = &value1;
5911     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5912     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5913     ctlEntry[0].cAttribute = 1;
5914     ctlEntry[0].rgAttribute = &attr1;
5915     info.cCTLEntry = 1;
5916     info.rgCTLEntry = ctlEntry;
5917     SetLastError(0xdeadbeef);
5918     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5919      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5920     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5921     if (ret)
5922     {
5923         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5924         LocalFree(buf);
5925         buf = NULL;
5926     }
5927     value2.cbData = sizeof(encodedIPAddr);
5928     value2.pbData = (LPBYTE)encodedIPAddr;
5929     attr2.pszObjId = oid2;
5930     attr2.cValue = 1;
5931     attr2.rgValue = &value2;
5932     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5933     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5934     ctlEntry[1].cAttribute = 1;
5935     ctlEntry[1].rgAttribute = &attr2;
5936     info.cCTLEntry = 2;
5937     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5938      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5939     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5940     if (ret)
5941     {
5942         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5943         LocalFree(buf);
5944         buf = NULL;
5945     }
5946     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5947     SetLastError(0xdeadbeef);
5948     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5949      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5950     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5951      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5952      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5953      GetLastError());
5954     SetLastError(0xdeadbeef);
5955     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5956      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5957      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5958     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5959      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5960      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5961      GetLastError());
5962 }
5963 
5964 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5965 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5966  0x03,0,0,0,0,0,0 };
5967 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5968  0xa0,0x01,0x01 };
5969 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5970  0x03,0x02,0x01,0x01 };
5971 static BYTE bogusDER[] = { 1 };
5972 
5973 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5974 {
5975     BOOL ret;
5976     BYTE *buf = NULL;
5977     DWORD size = 0;
5978     CRYPT_CONTENT_INFO info = { 0 };
5979     char oid1[] = "1.2.3";
5980 
5981     if (0)
5982     {
5983         /* Crashes on win9x */
5984         SetLastError(0xdeadbeef);
5985         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5986          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5987         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5988          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5989     }
5990     SetLastError(0xdeadbeef);
5991     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5992      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5993     ok(!ret && (GetLastError() == E_INVALIDARG ||
5994      GetLastError() == OSS_LIMITED /* Win9x */),
5995      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5996     info.pszObjId = oid1;
5997     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5998      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5999     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6000     if (ret)
6001     {
6002         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
6003         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
6004         LocalFree(buf);
6005     }
6006     info.Content.pbData = bogusDER;
6007     info.Content.cbData = sizeof(bogusDER);
6008     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
6009      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6010     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
6011     if (ret)
6012     {
6013         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
6014         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
6015         LocalFree(buf);
6016     }
6017     info.Content.pbData = (BYTE *)ints[0].encoded;
6018     info.Content.cbData = ints[0].encoded[1] + 2;
6019     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
6020      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6021     if (ret)
6022     {
6023         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
6024         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
6025         LocalFree(buf);
6026     }
6027 }
6028 
6029 static const BYTE indefiniteSignedPKCSContent[] = {
6030 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
6031 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
6032 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
6033 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
6034 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
6035 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
6036 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6037 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
6038 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
6039 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
6040 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
6041 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
6042 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
6043 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
6044 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
6045 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
6046 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
6047 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
6048 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
6049 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
6050 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
6051 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
6052 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
6053 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
6054 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
6055 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
6056 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
6057 0x00,0x00,0x00,0x00,0x00,0x00 };
6058 
6059 static const BYTE content_abcd[] = {
6060     ASN_SEQUENCE, 0x80,
6061         ASN_OBJECTIDENTIFIER, 2, 42,3,
6062         ASN_CONTEXT|ASN_CONSTRUCTOR, 0x80,
6063             ASN_OCTETSTRING, 4, 'a','b','c','d',
6064         0,0,
6065     0,0,
6066 };
6067 
6068 static const BYTE encoded_abcd[] = {
6069     ASN_OCTETSTRING, 4, 'a','b','c','d',
6070 };
6071 
6072 static const BYTE content_constructed_abcd[] = {
6073     ASN_SEQUENCE, 0x80,
6074         ASN_OBJECTIDENTIFIER, 2, 42,3,
6075         ASN_CONTEXT|ASN_CONSTRUCTOR, 0x80,
6076             ASN_CONSTRUCTOR|ASN_OCTETSTRING,0x80,
6077                 ASN_OCTETSTRING, 4, 'a','b','0','0',
6078             0,0,
6079         0,0,
6080     0,0,
6081     1,2,3,4,5,6,7 /* extra garbage */
6082 };
6083 
6084 static void test_decodePKCSContentInfo(DWORD dwEncoding)
6085 {
6086     BOOL ret;
6087     LPBYTE buf = NULL;
6088     DWORD size = 0, i;
6089     CRYPT_CONTENT_INFO *info;
6090 
6091     const struct {
6092         const BYTE *encoded;
6093         UINT encoded_size;
6094         const char *obj_id;
6095         const BYTE *content;
6096         UINT content_size;
6097     } tests[] = {
6098         { emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
6099           "1.2.3", NULL, 0 },
6100         { emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
6101           "1.2.3", NULL, 0 },
6102         { intPKCSContentInfo, sizeof(intPKCSContentInfo),
6103           "1.2.3", ints[0].encoded, ints[0].encoded[1] + 2 },
6104         { indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
6105           "1.2.840.113549.1.7.2", NULL, 392 },
6106         { content_abcd, sizeof(content_abcd),
6107           "1.2.3", encoded_abcd, 6 },
6108         { content_constructed_abcd, sizeof(content_constructed_abcd),
6109           "1.2.3", content_constructed_abcd + 8, 10 }
6110     };
6111 
6112     for (i = 0; i < sizeof(tests)/sizeof(*tests); i++)
6113     {
6114         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, tests[i].encoded,
6115             tests[i].encoded_size, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6116         ok(ret, "[%u] CryptDecodeObjectEx failed: %x\n", i, GetLastError());
6117         if (!ret) continue;
6118 
6119         info = (CRYPT_CONTENT_INFO *)buf;
6120 
6121         ok(!strcmp(info->pszObjId, tests[i].obj_id), "[%u] Expected %s, got %s\n",
6122            i, tests[i].obj_id, info->pszObjId);
6123         ok(info->Content.cbData == tests[i].content_size,
6124            "[%u] Unexpected size %d expected %d\n", i, info->Content.cbData,
6125            tests[i].content_size);
6126         if (tests[i].content)
6127             ok(!memcmp(info->Content.pbData, tests[i].content, tests[i].content_size),
6128                "[%u] Unexpected value\n", i);
6129         LocalFree(buf);
6130     }
6131 
6132     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
6133      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
6134      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6135     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6136      * I doubt an app depends on that.
6137      */
6138     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6139      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
6140      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
6141      GetLastError());
6142 }
6143 
6144 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
6145  0x00 };
6146 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
6147  0x01 };
6148 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
6149  0x02,0x01,0x01 };
6150 
6151 static void test_encodePKCSAttribute(DWORD dwEncoding)
6152 {
6153     CRYPT_ATTRIBUTE attr = { 0 };
6154     BOOL ret;
6155     LPBYTE buf = NULL;
6156     DWORD size = 0;
6157     CRYPT_ATTR_BLOB blob;
6158     char oid[] = "1.2.3";
6159 
6160     if (0)
6161     {
6162         /* Crashes on win9x */
6163         SetLastError(0xdeadbeef);
6164         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
6165          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6166         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
6167          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
6168     }
6169     SetLastError(0xdeadbeef);
6170     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6171      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6172     ok(!ret && (GetLastError() == E_INVALIDARG ||
6173      GetLastError() == OSS_LIMITED /* Win9x */),
6174      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
6175     attr.pszObjId = oid;
6176     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6177      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6178     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6179     if (ret)
6180     {
6181         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
6182         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
6183         LocalFree(buf);
6184     }
6185     blob.cbData = sizeof(bogusDER);
6186     blob.pbData = bogusDER;
6187     attr.cValue = 1;
6188     attr.rgValue = &blob;
6189     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6190      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6191     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6192     if (ret)
6193     {
6194         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
6195         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6196         LocalFree(buf);
6197     }
6198     blob.pbData = (BYTE *)ints[0].encoded;
6199     blob.cbData = ints[0].encoded[1] + 2;
6200     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6201      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6202     if (ret)
6203     {
6204         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6205         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6206         LocalFree(buf);
6207     }
6208 }
6209 
6210 static void test_decodePKCSAttribute(DWORD dwEncoding)
6211 {
6212     BOOL ret;
6213     LPBYTE buf = NULL;
6214     DWORD size = 0;
6215     CRYPT_ATTRIBUTE *attr;
6216 
6217     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6218      emptyPKCSAttr, sizeof(emptyPKCSAttr),
6219      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6220     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6221     if (ret)
6222     {
6223         attr = (CRYPT_ATTRIBUTE *)buf;
6224 
6225         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6226          attr->pszObjId);
6227         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6228         LocalFree(buf);
6229     }
6230     SetLastError(0xdeadbeef);
6231     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6232      bogusPKCSAttr, sizeof(bogusPKCSAttr),
6233      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6234     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6235      * I doubt an app depends on that.
6236      */
6237     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6238      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6239      GetLastError() == OSS_MORE_INPUT /* Win9x */),
6240      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6241      GetLastError());
6242     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6243      intPKCSAttr, sizeof(intPKCSAttr),
6244      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6245     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6246     if (ret)
6247     {
6248         attr = (CRYPT_ATTRIBUTE *)buf;
6249 
6250         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6251          attr->pszObjId);
6252         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6253         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6254          "Unexpected size %d\n", attr->rgValue[0].cbData);
6255         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6256          attr->rgValue[0].cbData), "Unexpected value\n");
6257         LocalFree(buf);
6258     }
6259 }
6260 
6261 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6262 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6263  0x2a,0x03,0x31,0x00 };
6264 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6265  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6266 
6267 static void test_encodePKCSAttributes(DWORD dwEncoding)
6268 {
6269     CRYPT_ATTRIBUTES attributes = { 0 };
6270     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6271     CRYPT_ATTR_BLOB blob;
6272     BOOL ret;
6273     LPBYTE buf = NULL;
6274     DWORD size = 0;
6275     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6276 
6277     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6278      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6279     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6280     if (ret)
6281     {
6282         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6283         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6284         LocalFree(buf);
6285     }
6286     attributes.cAttr = 1;
6287     attributes.rgAttr = attr;
6288     SetLastError(0xdeadbeef);
6289     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6290      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6291     ok(!ret && (GetLastError() == E_INVALIDARG ||
6292      GetLastError() == OSS_LIMITED /* Win9x */),
6293      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6294     attr[0].pszObjId = oid1;
6295     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6296      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6297     if (ret)
6298     {
6299         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6300         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6301         LocalFree(buf);
6302     }
6303     attr[1].pszObjId = oid2;
6304     attr[1].cValue = 1;
6305     attr[1].rgValue = &blob;
6306     blob.pbData = (BYTE *)ints[0].encoded;
6307     blob.cbData = ints[0].encoded[1] + 2;
6308     attributes.cAttr = 2;
6309     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6310      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6311     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6312     if (ret)
6313     {
6314         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6315         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6316         LocalFree(buf);
6317     }
6318 }
6319 
6320 static void test_decodePKCSAttributes(DWORD dwEncoding)
6321 {
6322     BOOL ret;
6323     LPBYTE buf = NULL;
6324     DWORD size = 0;
6325     CRYPT_ATTRIBUTES *attributes;
6326 
6327     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6328      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6329      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6330     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6331     if (ret)
6332     {
6333         attributes = (CRYPT_ATTRIBUTES *)buf;
6334         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6335          attributes->cAttr);
6336         LocalFree(buf);
6337     }
6338     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6339      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6340      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6341     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6342     if (ret)
6343     {
6344         attributes = (CRYPT_ATTRIBUTES *)buf;
6345         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6346          attributes->cAttr);
6347         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6348          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6349         ok(attributes->rgAttr[0].cValue == 0,
6350          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6351         LocalFree(buf);
6352     }
6353     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6354      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6355      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6356     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6357     if (ret)
6358     {
6359         attributes = (CRYPT_ATTRIBUTES *)buf;
6360         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6361          attributes->cAttr);
6362         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6363          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6364         ok(attributes->rgAttr[0].cValue == 0,
6365          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6366         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6367          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6368         ok(attributes->rgAttr[1].cValue == 1,
6369          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6370         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6371          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6372         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6373          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6374         LocalFree(buf);
6375     }
6376     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6377      doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, NULL, &size);
6378     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6379     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6380     if (buf)
6381     {
6382         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6383          doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, buf, &size);
6384         ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6385         HeapFree(GetProcessHeap(), 0, buf);
6386     }
6387 }
6388 
6389 static const BYTE singleCapability[] = {
6390 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6391 static const BYTE twoCapabilities[] = {
6392 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6393 static const BYTE singleCapabilitywithNULL[] = {
6394 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6395 
6396 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6397 {
6398     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6399     BOOL ret;
6400     LPBYTE buf = NULL;
6401     DWORD size = 0;
6402     CRYPT_SMIME_CAPABILITY capability[2];
6403     CRYPT_SMIME_CAPABILITIES capabilities;
6404 
6405     /* An empty capabilities is allowed */
6406     capabilities.cCapability = 0;
6407     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6408      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6409     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6410     if (ret)
6411     {
6412         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6413         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6414         LocalFree(buf);
6415     }
6416     /* A non-empty capabilities with an empty capability (lacking an OID) is
6417      * not allowed
6418      */
6419     capability[0].pszObjId = NULL;
6420     capability[0].Parameters.cbData = 0;
6421     capabilities.cCapability = 1;
6422     capabilities.rgCapability = capability;
6423     SetLastError(0xdeadbeef);
6424     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6425      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6426     ok(!ret && (GetLastError() == E_INVALIDARG ||
6427      GetLastError() == OSS_LIMITED /* Win9x */),
6428      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6429     capability[0].pszObjId = oid1;
6430     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6431      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6432     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6433     if (ret)
6434     {
6435         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6436         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6437         LocalFree(buf);
6438     }
6439     capability[1].pszObjId = oid2;
6440     capability[1].Parameters.cbData = 0;
6441     capabilities.cCapability = 2;
6442     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6443      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6444     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6445     if (ret)
6446     {
6447         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6448         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6449         LocalFree(buf);
6450     }
6451 }
6452 
6453 static void compareSMimeCapabilities(LPCSTR header,
6454  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6455 {
6456     DWORD i;
6457 
6458     ok(got->cCapability == expected->cCapability,
6459      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6460      got->cCapability);
6461     for (i = 0; i < expected->cCapability; i++)
6462     {
6463         ok(!strcmp(expected->rgCapability[i].pszObjId,
6464          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6465          header, i, expected->rgCapability[i].pszObjId,
6466          got->rgCapability[i].pszObjId);
6467         ok(expected->rgCapability[i].Parameters.cbData ==
6468          got->rgCapability[i].Parameters.cbData,
6469          "%s[%d]: expected %d bytes, got %d\n", header, i,
6470          expected->rgCapability[i].Parameters.cbData,
6471          got->rgCapability[i].Parameters.cbData);
6472         if (expected->rgCapability[i].Parameters.cbData)
6473             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6474              got->rgCapability[i].Parameters.pbData,
6475              expected->rgCapability[i].Parameters.cbData),
6476              "%s[%d]: unexpected value\n", header, i);
6477     }
6478 }
6479 
6480 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6481 {
6482     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6483     BOOL ret;
6484     DWORD size = 0;
6485     CRYPT_SMIME_CAPABILITY capability[2];
6486     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6487 
6488     SetLastError(0xdeadbeef);
6489     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6490      emptySequence, sizeof(emptySequence),
6491      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6492     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6493     if (ret)
6494     {
6495         capabilities.cCapability = 0;
6496         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6497         LocalFree(ptr);
6498     }
6499     SetLastError(0xdeadbeef);
6500     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6501      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6502      &ptr, &size);
6503     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6504     if (ret)
6505     {
6506         capability[0].pszObjId = oid1;
6507         capability[0].Parameters.cbData = 0;
6508         capabilities.cCapability = 1;
6509         capabilities.rgCapability = capability;
6510         compareSMimeCapabilities("single capability", &capabilities, ptr);
6511         LocalFree(ptr);
6512     }
6513     SetLastError(0xdeadbeef);
6514     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6515      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6516      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6517     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6518     if (ret)
6519     {
6520         BYTE NULLparam[] = {0x05, 0x00};
6521         capability[0].pszObjId = oid1;
6522         capability[0].Parameters.cbData = 2;
6523         capability[0].Parameters.pbData = NULLparam;
6524         capabilities.cCapability = 1;
6525         capabilities.rgCapability = capability;
6526         compareSMimeCapabilities("single capability with NULL", &capabilities,
6527          ptr);
6528         LocalFree(ptr);
6529     }
6530     SetLastError(0xdeadbeef);
6531     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6532     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6533     &ptr, &size);
6534     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6535     if (ret)
6536     {
6537         capability[0].Parameters.cbData = 0;
6538         capability[1].pszObjId = oid2;
6539         capability[1].Parameters.cbData = 0;
6540         capabilities.cCapability = 2;
6541         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6542         LocalFree(ptr);
6543     }
6544     SetLastError(0xdeadbeef);
6545     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6546      twoCapabilities, sizeof(twoCapabilities), 0, NULL, NULL, &size);
6547     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6548     ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6549     if (ptr)
6550     {
6551         SetLastError(0xdeadbeef);
6552         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6553          twoCapabilities, sizeof(twoCapabilities), 0, NULL, ptr, &size);
6554         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6555         HeapFree(GetProcessHeap(), 0, ptr);
6556     }
6557 }
6558 
6559 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6560  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6561  0x67 };
6562 static const BYTE minimalPKCSSigner[] = {
6563  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6564  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6565  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6566 static const BYTE PKCSSignerWithSerial[] = {
6567  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6568  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6569  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6570  0x00 };
6571 static const BYTE PKCSSignerWithHashAlgo[] = {
6572  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6573  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6574  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6575  0x00,0x04,0x00 };
6576 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6577  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6578  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6579  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6580  0x06,0x05,0x00,0x04,0x00 };
6581 static const BYTE PKCSSignerWithHash[] = {
6582  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6583  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6584  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6585  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6586  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6587 static const BYTE PKCSSignerWithAuthAttr[] = {
6588 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6589 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6590 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6591 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6592 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6593 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6594 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6595 
6596 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6597 {
6598     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6599     BOOL ret;
6600     LPBYTE buf = NULL;
6601     DWORD size = 0;
6602     CMSG_SIGNER_INFO info = { 0 };
6603     char oid_common_name[] = szOID_COMMON_NAME;
6604     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6605      (LPBYTE)encodedCommonName };
6606     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6607 
6608     SetLastError(0xdeadbeef);
6609     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6610      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6611     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6612     {
6613         skip("no PKCS7_SIGNER_INFO encode support\n");
6614         return;
6615     }
6616     ok(!ret && (GetLastError() == E_INVALIDARG ||
6617      GetLastError() == OSS_LIMITED /* Win9x */),
6618      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6619     /* To be encoded, a signer must have an issuer at least, and the encoding
6620      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6621      * see decoding tests.)
6622      */
6623     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6624     info.Issuer.pbData = encodedCommonNameNoNull;
6625     SetLastError(0xdeadbeef);
6626     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6627      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6628     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6629         ok(!ret && GetLastError() == E_INVALIDARG,
6630          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6631     else
6632     {
6633         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6634          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6635         if (ret)
6636         {
6637             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6638             if (size == sizeof(minimalPKCSSigner))
6639                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6640             else
6641                 ok(0, "Unexpected value\n");
6642             LocalFree(buf);
6643         }
6644     }
6645     info.SerialNumber.cbData = sizeof(serialNum);
6646     info.SerialNumber.pbData = (BYTE *)serialNum;
6647     SetLastError(0xdeadbeef);
6648     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6649      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6650     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6651         ok(!ret && GetLastError() == E_INVALIDARG,
6652          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6653     else
6654     {
6655         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6656          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6657         if (ret)
6658         {
6659             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6660              size);
6661             if (size == sizeof(PKCSSignerWithSerial))
6662                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6663                  "Unexpected value\n");
6664             else
6665                 ok(0, "Unexpected value\n");
6666             LocalFree(buf);
6667         }
6668     }
6669     info.HashAlgorithm.pszObjId = oid1;
6670     SetLastError(0xdeadbeef);
6671     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6672      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6673     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6674         ok(!ret && GetLastError() == E_INVALIDARG,
6675          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6676     else
6677     {
6678         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6679          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6680         if (ret)
6681         {
6682             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6683              size);
6684             if (size == sizeof(PKCSSignerWithHashAlgo))
6685                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6686                  "Unexpected value\n");
6687             else
6688                 ok(0, "Unexpected value\n");
6689             LocalFree(buf);
6690         }
6691     }
6692     info.HashEncryptionAlgorithm.pszObjId = oid2;
6693     SetLastError(0xdeadbeef);
6694     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6695      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6696     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6697         ok(!ret && GetLastError() == E_INVALIDARG,
6698          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6699     else
6700     {
6701         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6702         if (ret)
6703         {
6704             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6705              "Unexpected size %d\n", size);
6706             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6707                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6708                  "Unexpected value\n");
6709             else
6710                 ok(0, "Unexpected value\n");
6711             LocalFree(buf);
6712         }
6713     }
6714     info.EncryptedHash.cbData = sizeof(hash);
6715     info.EncryptedHash.pbData = (BYTE *)hash;
6716     SetLastError(0xdeadbeef);
6717     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6718      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6719     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6720         ok(!ret && GetLastError() == E_INVALIDARG,
6721          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6722     else
6723     {
6724         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6725         if (ret)
6726         {
6727             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6728              size);
6729             if (size == sizeof(PKCSSignerWithHash))
6730                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6731                  "Unexpected value\n");
6732             else
6733                 ok(0, "Unexpected value\n");
6734             LocalFree(buf);
6735         }
6736     }
6737     info.AuthAttrs.cAttr = 1;
6738     info.AuthAttrs.rgAttr = &attr;
6739     SetLastError(0xdeadbeef);
6740     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6741      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6742     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6743         ok(!ret && GetLastError() == E_INVALIDARG,
6744          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6745     else
6746     {
6747         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6748         if (ret)
6749         {
6750             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6751              size);
6752             if (size == sizeof(PKCSSignerWithAuthAttr))
6753                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6754                  "Unexpected value\n");
6755             else
6756                 ok(0, "Unexpected value\n");
6757             LocalFree(buf);
6758         }
6759     }
6760 }
6761 
6762 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6763 {
6764     BOOL ret;
6765     LPBYTE buf = NULL;
6766     DWORD size = 0;
6767     CMSG_SIGNER_INFO *info;
6768 
6769     /* A PKCS signer can't be decoded without a serial number. */
6770     SetLastError(0xdeadbeef);
6771     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6772      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6773      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6774     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6775      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6776      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6777      GetLastError());
6778     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6779      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6780      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6781     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6782      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6783     if (ret)
6784     {
6785         info = (CMSG_SIGNER_INFO *)buf;
6786         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6787          info->dwVersion);
6788         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6789          "Unexpected size %d\n", info->Issuer.cbData);
6790         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6791          info->Issuer.cbData), "Unexpected value\n");
6792         ok(info->SerialNumber.cbData == sizeof(serialNum),
6793          "Unexpected size %d\n", info->SerialNumber.cbData);
6794         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6795          "Unexpected value\n");
6796         LocalFree(buf);
6797     }
6798     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6799      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6800      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6801     if (ret)
6802     {
6803         info = (CMSG_SIGNER_INFO *)buf;
6804         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6805          info->dwVersion);
6806         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6807          "Unexpected size %d\n", info->Issuer.cbData);
6808         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6809          info->Issuer.cbData), "Unexpected value\n");
6810         ok(info->SerialNumber.cbData == sizeof(serialNum),
6811          "Unexpected size %d\n", info->SerialNumber.cbData);
6812         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6813          "Unexpected value\n");
6814         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6815          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6816         LocalFree(buf);
6817     }
6818     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6819      PKCSSignerWithHashAndEncryptionAlgo,
6820      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6821      NULL, &buf, &size);
6822     if (ret)
6823     {
6824         info = (CMSG_SIGNER_INFO *)buf;
6825         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6826          info->dwVersion);
6827         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6828          "Unexpected size %d\n", info->Issuer.cbData);
6829         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6830          info->Issuer.cbData), "Unexpected value\n");
6831         ok(info->SerialNumber.cbData == sizeof(serialNum),
6832          "Unexpected size %d\n", info->SerialNumber.cbData);
6833         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6834          "Unexpected value\n");
6835         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6836          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6837         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6838          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6839         LocalFree(buf);
6840     }
6841     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6842      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6843      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6844     if (ret)
6845     {
6846         info = (CMSG_SIGNER_INFO *)buf;
6847         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6848          info->dwVersion);
6849         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6850          "Unexpected size %d\n", info->Issuer.cbData);
6851         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6852          info->Issuer.cbData), "Unexpected value\n");
6853         ok(info->SerialNumber.cbData == sizeof(serialNum),
6854          "Unexpected size %d\n", info->SerialNumber.cbData);
6855         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6856          "Unexpected value\n");
6857         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6858          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6859         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6860          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6861         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6862          info->EncryptedHash.cbData);
6863         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6864          "Unexpected value\n");
6865         LocalFree(buf);
6866     }
6867     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6868      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6869      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6870     if (ret)
6871     {
6872         info = (CMSG_SIGNER_INFO *)buf;
6873         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6874          info->AuthAttrs.cAttr);
6875         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6876          "Expected %s, got %s\n", szOID_COMMON_NAME,
6877          info->AuthAttrs.rgAttr[0].pszObjId);
6878         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6879          info->AuthAttrs.rgAttr[0].cValue);
6880         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6881          sizeof(encodedCommonName), "Unexpected size %d\n",
6882          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6883         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6884          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6885         LocalFree(buf);
6886     }
6887 }
6888 
6889 static const BYTE CMSSignerWithKeyId[] = {
6890 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6891 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6892 
6893 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6894 {
6895     BOOL ret;
6896     LPBYTE buf = NULL;
6897     DWORD size = 0;
6898     CMSG_CMS_SIGNER_INFO info = { 0 };
6899     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6900 
6901     SetLastError(0xdeadbeef);
6902     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6903      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6904     ok(!ret, "Expected failure, got %d\n", ret);
6905     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6906     {
6907         skip("no CMS_SIGNER_INFO encode support\n");
6908         return;
6909     }
6910     ok(GetLastError() == E_INVALIDARG,
6911        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6912     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6913     SetLastError(0xdeadbeef);
6914     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6915      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6916     ok(!ret, "Expected failure, got %d\n", ret);
6917     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6918     {
6919         skip("no CMS_SIGNER_INFO encode support\n");
6920         return;
6921     }
6922     ok(GetLastError() == E_INVALIDARG,
6923        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6924     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6925      * be a key id or an issuer serial number with at least the issuer set, and
6926      * the encoding must include PKCS_7_ASN_ENCODING.
6927      * (That isn't enough to be decoded, see decoding tests.)
6928      */
6929     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6930      sizeof(encodedCommonNameNoNull);
6931     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6932     SetLastError(0xdeadbeef);
6933     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6934      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6935     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6936         ok(!ret && GetLastError() == E_INVALIDARG,
6937          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6938     else
6939     {
6940         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6941         if (ret)
6942         {
6943             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6944             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6945             LocalFree(buf);
6946         }
6947     }
6948     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6949     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6950     SetLastError(0xdeadbeef);
6951     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6952      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6953     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6954         ok(!ret && GetLastError() == E_INVALIDARG,
6955          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6956     else
6957     {
6958         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6959         if (ret)
6960         {
6961             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6962              size);
6963             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6964             LocalFree(buf);
6965         }
6966     }
6967     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6968     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6969     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6970     SetLastError(0xdeadbeef);
6971     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6972      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6973     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6974         ok(!ret && GetLastError() == E_INVALIDARG,
6975          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6976     else
6977     {
6978         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6979         if (ret)
6980         {
6981             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6982              size);
6983             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6984             LocalFree(buf);
6985         }
6986     }
6987     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6988      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6989      * (see RFC 3852, section 5.3.)
6990      */
6991     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6992     U(info.SignerId).HashId.cbData = sizeof(hash);
6993     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6994     SetLastError(0xdeadbeef);
6995     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6996      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6997     ok(!ret && GetLastError() == E_INVALIDARG,
6998      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6999     /* Now with a hash algo */
7000     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
7001     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
7002      sizeof(encodedCommonNameNoNull);
7003     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
7004     info.HashAlgorithm.pszObjId = oid1;
7005     SetLastError(0xdeadbeef);
7006     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
7007      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7008     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
7009         ok(!ret && GetLastError() == E_INVALIDARG,
7010          "Expected E_INVALIDARG, got %08x\n", GetLastError());
7011     else
7012     {
7013         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
7014         if (ret)
7015         {
7016             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
7017              size);
7018             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
7019              "Unexpected value\n");
7020             LocalFree(buf);
7021         }
7022     }
7023     info.HashEncryptionAlgorithm.pszObjId = oid2;
7024     SetLastError(0xdeadbeef);
7025     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
7026      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7027     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
7028         ok(!ret && GetLastError() == E_INVALIDARG,
7029          "Expected E_INVALIDARG, got %08x\n", GetLastError());
7030     else
7031     {
7032         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
7033         if (ret)
7034         {
7035             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
7036              "Unexpected size %d\n", size);
7037             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
7038              "Unexpected value\n");
7039             LocalFree(buf);
7040         }
7041     }
7042     info.EncryptedHash.cbData = sizeof(hash);
7043     info.EncryptedHash.pbData = (BYTE *)hash;
7044     SetLastError(0xdeadbeef);
7045     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
7046      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7047     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
7048         ok(!ret && GetLastError() == E_INVALIDARG,
7049          "Expected E_INVALIDARG, got %08x\n", GetLastError());
7050     else
7051     {
7052         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
7053         if (ret)
7054         {
7055             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
7056              size);
7057             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
7058             LocalFree(buf);
7059         }
7060     }
7061 }
7062 
7063 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
7064 {
7065     BOOL ret;
7066     LPBYTE buf = NULL;
7067     DWORD size = 0;
7068     CMSG_CMS_SIGNER_INFO *info;
7069     static const char oid1[] = "1.2.3", oid2[] = "1.5.6";
7070 
7071     /* A CMS signer can't be decoded without a serial number. */
7072     SetLastError(0xdeadbeef);
7073     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7074      minimalPKCSSigner, sizeof(minimalPKCSSigner),
7075      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7076     ok(!ret, "expected failure\n");
7077     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7078     {
7079         skip("no CMS_SIGNER_INFO decode support\n");
7080         return;
7081     }
7082     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
7083      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
7084     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7085      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
7086      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7087     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7088     if (ret)
7089     {
7090         info = (CMSG_CMS_SIGNER_INFO *)buf;
7091         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7092          info->dwVersion);
7093         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7094          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7095          info->SignerId.dwIdChoice);
7096         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7097          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7098          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7099         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7100          encodedCommonNameNoNull,
7101          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7102          "Unexpected value\n");
7103         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7104          sizeof(serialNum), "Unexpected size %d\n",
7105          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7106         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7107          serialNum, sizeof(serialNum)), "Unexpected value\n");
7108         LocalFree(buf);
7109     }
7110     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7111      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
7112      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7113     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7114     if (ret)
7115     {
7116         info = (CMSG_CMS_SIGNER_INFO *)buf;
7117         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7118          info->dwVersion);
7119         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7120          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7121          info->SignerId.dwIdChoice);
7122         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7123          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7124          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7125         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7126          encodedCommonNameNoNull,
7127          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7128          "Unexpected value\n");
7129         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7130          sizeof(serialNum), "Unexpected size %d\n",
7131          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7132         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7133          serialNum, sizeof(serialNum)), "Unexpected value\n");
7134         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7135          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7136         LocalFree(buf);
7137     }
7138     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7139      PKCSSignerWithHashAndEncryptionAlgo,
7140      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
7141      NULL, &buf, &size);
7142     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7143     if (ret)
7144     {
7145         info = (CMSG_CMS_SIGNER_INFO *)buf;
7146         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7147          info->dwVersion);
7148         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7149          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7150          info->SignerId.dwIdChoice);
7151         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7152          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7153          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7154         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7155          encodedCommonNameNoNull,
7156          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7157          "Unexpected value\n");
7158         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7159          sizeof(serialNum), "Unexpected size %d\n",
7160          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7161         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7162          serialNum, sizeof(serialNum)), "Unexpected value\n");
7163         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7164          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7165         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7166          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7167         LocalFree(buf);
7168     }
7169     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7170      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
7171      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7172     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7173     if (ret)
7174     {
7175         info = (CMSG_CMS_SIGNER_INFO *)buf;
7176         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7177          info->dwVersion);
7178         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7179          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7180          info->SignerId.dwIdChoice);
7181         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7182          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7183          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7184         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7185          encodedCommonNameNoNull,
7186          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7187          "Unexpected value\n");
7188         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7189          sizeof(serialNum), "Unexpected size %d\n",
7190          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7191         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7192          serialNum, sizeof(serialNum)), "Unexpected value\n");
7193         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7194          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7195         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7196          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7197         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
7198          info->EncryptedHash.cbData);
7199         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
7200          "Unexpected value\n");
7201         LocalFree(buf);
7202     }
7203     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7204      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
7205      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7206     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7207     if (ret)
7208     {
7209         info = (CMSG_CMS_SIGNER_INFO *)buf;
7210         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7211          info->dwVersion);
7212         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
7213          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
7214          info->SignerId.dwIdChoice);
7215         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
7216          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
7217         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
7218          "Unexpected value\n");
7219         LocalFree(buf);
7220     }
7221 }
7222 
7223 static BYTE emptyDNSPermittedConstraints[] = {
7224 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7225 static BYTE emptyDNSExcludedConstraints[] = {
7226 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7227 static BYTE DNSExcludedConstraints[] = {
7228 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7229 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7230 static BYTE permittedAndExcludedConstraints[] = {
7231 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7232 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7233 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7234 static BYTE permittedAndExcludedWithMinConstraints[] = {
7235 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7236 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7237 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7238 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7239 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7240 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7241 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7242 
7243 static void test_encodeNameConstraints(DWORD dwEncoding)
7244 {
7245     BOOL ret;
7246     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7247     CERT_GENERAL_SUBTREE permitted = { { 0 } };
7248     CERT_GENERAL_SUBTREE excluded = { { 0 } };
7249     LPBYTE buf;
7250     DWORD size;
7251 
7252     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7253      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7254     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7255     {
7256         skip("no X509_NAME_CONSTRAINTS encode support\n");
7257         return;
7258     }
7259     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7260     if (ret)
7261     {
7262         ok(size == sizeof(emptySequence), "Unexpected size\n");
7263         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7264         LocalFree(buf);
7265     }
7266     constraints.cPermittedSubtree = 1;
7267     constraints.rgPermittedSubtree = &permitted;
7268     SetLastError(0xdeadbeef);
7269     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7270      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7271     ok(!ret && GetLastError() == E_INVALIDARG,
7272      "Expected E_INVALIDARG, got %08x\n", GetLastError());
7273     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7274     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7275      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7276     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7277     if (ret)
7278     {
7279         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7280         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7281          "Unexpected value\n");
7282         LocalFree(buf);
7283     }
7284     constraints.cPermittedSubtree = 0;
7285     constraints.cExcludedSubtree = 1;
7286     constraints.rgExcludedSubtree = &excluded;
7287     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7288     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7289      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7290     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7291     if (ret)
7292     {
7293         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7294         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7295          "Unexpected value\n");
7296         LocalFree(buf);
7297     }
7298     U(excluded.Base).pwszURL = (LPWSTR)url;
7299     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7300      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7301     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7302     if (ret)
7303     {
7304         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7305         ok(!memcmp(buf, DNSExcludedConstraints, size),
7306          "Unexpected value\n");
7307         LocalFree(buf);
7308     }
7309     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7310     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7311     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7312     constraints.cPermittedSubtree = 1;
7313     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7314      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7315     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7316     if (ret)
7317     {
7318         ok(size == sizeof(permittedAndExcludedConstraints),
7319          "Unexpected size\n");
7320         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7321          "Unexpected value\n");
7322         LocalFree(buf);
7323     }
7324     permitted.dwMinimum = 5;
7325     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7326      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7327     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7328     if (ret)
7329     {
7330         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7331          "Unexpected size\n");
7332         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7333          "Unexpected value\n");
7334         LocalFree(buf);
7335     }
7336     permitted.fMaximum = TRUE;
7337     permitted.dwMaximum = 3;
7338     SetLastError(0xdeadbeef);
7339     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7340      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7341     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7342     if (ret)
7343     {
7344         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7345          "Unexpected size\n");
7346         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7347          "Unexpected value\n");
7348         LocalFree(buf);
7349     }
7350 }
7351 
7352 struct EncodedNameConstraints
7353 {
7354     CRYPT_DATA_BLOB            encoded;
7355     CERT_NAME_CONSTRAINTS_INFO constraints;
7356 };
7357 
7358 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7359  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7360 static CERT_GENERAL_SUBTREE DNSSubtree = {
7361  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7362 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7363  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7364 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7365  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7366 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7367  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7368 
7369 static const struct EncodedNameConstraints encodedNameConstraints[] = {
7370  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7371  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7372    { 1, &emptyDNSSubtree, 0, NULL } },
7373  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7374    { 0, NULL, 1, &emptyDNSSubtree } },
7375  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7376    { 0, NULL, 1, &DNSSubtree } },
7377  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7378    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7379  { { sizeof(permittedAndExcludedWithMinConstraints),
7380      permittedAndExcludedWithMinConstraints },
7381    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7382  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7383      permittedAndExcludedWithMinMaxConstraints },
7384    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7385 };
7386 
7387 static void test_decodeNameConstraints(DWORD dwEncoding)
7388 {
7389     BOOL ret;
7390     DWORD i;
7391     CERT_NAME_CONSTRAINTS_INFO *constraints;
7392 
7393     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7394     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7395     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7396     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7397     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7398     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7399     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7400     for (i = 0;
7401      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7402      i++)
7403     {
7404         DWORD size;
7405 
7406         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7407          encodedNameConstraints[i].encoded.pbData,
7408          encodedNameConstraints[i].encoded.cbData,
7409          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7410         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7411         {
7412             skip("no X509_NAME_CONSTRAINTS decode support\n");
7413             return;
7414         }
7415         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7416         if (ret)
7417         {
7418             DWORD j;
7419 
7420             if (constraints->cPermittedSubtree !=
7421              encodedNameConstraints[i].constraints.cPermittedSubtree)
7422                 fprintf(stderr, "%d: expected %u permitted, got %u\n", i,
7423                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7424                  constraints->cPermittedSubtree);
7425             if (constraints->cPermittedSubtree ==
7426              encodedNameConstraints[i].constraints.cPermittedSubtree)
7427             {
7428                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7429                 {
7430                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7431                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7432                 }
7433             }
7434             if (constraints->cExcludedSubtree !=
7435              encodedNameConstraints[i].constraints.cExcludedSubtree)
7436                 fprintf(stderr, "%d: expected %u excluded, got %u\n", i,
7437                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7438                  constraints->cExcludedSubtree);
7439             if (constraints->cExcludedSubtree ==
7440              encodedNameConstraints[i].constraints.cExcludedSubtree)
7441             {
7442                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7443                 {
7444                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7445                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7446                 }
7447             }
7448             LocalFree(constraints);
7449         }
7450     }
7451 }
7452 
7453 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7454  'n','o','t','i','c','e',0 };
7455 static const BYTE noticeWithDisplayText[] = {
7456  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7457  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7458  0x00,0x69,0x00,0x63,0x00,0x65
7459 };
7460 static char org[] = "Wine";
7461 static int noticeNumbers[] = { 2,3 };
7462 static BYTE noticeWithReference[] = {
7463  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7464  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7465  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7466  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7467 };
7468 
7469 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7470 {
7471     BOOL ret;
7472     LPBYTE buf;
7473     DWORD size;
7474     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7475     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7476 
7477     memset(&notice, 0, sizeof(notice));
7478     ret = pCryptEncodeObjectEx(dwEncoding,
7479      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7480      NULL, &buf, &size);
7481     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7482     {
7483         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7484         return;
7485     }
7486     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7487     if (ret)
7488     {
7489         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7490         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7491         LocalFree(buf);
7492     }
7493     notice.pszDisplayText = noticeText;
7494     ret = pCryptEncodeObjectEx(dwEncoding,
7495      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7496      NULL, &buf, &size);
7497     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7498     if (ret)
7499     {
7500         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7501         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7502         LocalFree(buf);
7503     }
7504     reference.pszOrganization = org;
7505     reference.cNoticeNumbers = 2;
7506     reference.rgNoticeNumbers = noticeNumbers;
7507     notice.pNoticeReference = &reference;
7508     ret = pCryptEncodeObjectEx(dwEncoding,
7509      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7510      NULL, &buf, &size);
7511     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7512     if (ret)
7513     {
7514         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7515         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7516         LocalFree(buf);
7517     }
7518 }
7519 
7520 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7521 {
7522     BOOL ret;
7523     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7524     DWORD size;
7525 
7526     ret = pCryptDecodeObjectEx(dwEncoding,
7527      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7528      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7529      &notice, &size);
7530     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7531     {
7532         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7533         return;
7534     }
7535     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7536     if (ret)
7537     {
7538         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7539         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7540         LocalFree(notice);
7541     }
7542     ret = pCryptDecodeObjectEx(dwEncoding,
7543      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7544      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7545      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7546     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7547     if (ret)
7548     {
7549         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7550          "unexpected display text\n");
7551         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7552         LocalFree(notice);
7553     }
7554     ret = pCryptDecodeObjectEx(dwEncoding,
7555      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7556      noticeWithReference, sizeof(noticeWithReference),
7557      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7558     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7559     if (ret)
7560     {
7561         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7562          "unexpected display text\n");
7563         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7564         if (notice->pNoticeReference)
7565         {
7566             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7567              "unexpected organization %s\n",
7568              notice->pNoticeReference->pszOrganization);
7569             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7570              "expected 2 notice numbers, got %d\n",
7571              notice->pNoticeReference->cNoticeNumbers);
7572             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7573              "unexpected notice number %d\n",
7574              notice->pNoticeReference->rgNoticeNumbers[0]);
7575             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7576              "unexpected notice number %d\n",
7577              notice->pNoticeReference->rgNoticeNumbers[1]);
7578         }
7579         LocalFree(notice);
7580     }
7581 }
7582 
7583 static char oid_any_policy[] = "2.5.29.32.0";
7584 static const BYTE policiesWithAnyPolicy[] = {
7585  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7586 };
7587 static char oid1[] = "1.2.3";
7588 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7589 static const BYTE twoPolicies[] = {
7590  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7591  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7592  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7593  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7594  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7595  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7596 };
7597 
7598 static void test_encodeCertPolicies(DWORD dwEncoding)
7599 {
7600     BOOL ret;
7601     CERT_POLICIES_INFO info;
7602     CERT_POLICY_INFO policy[2];
7603     CERT_POLICY_QUALIFIER_INFO qualifier;
7604     LPBYTE buf;
7605     DWORD size;
7606 
7607     memset(&info, 0, sizeof(info));
7608     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7609      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7610     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7611     if (ret)
7612     {
7613         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7614         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7615         LocalFree(buf);
7616     }
7617     memset(policy, 0, sizeof(policy));
7618     info.cPolicyInfo = 1;
7619     info.rgPolicyInfo = policy;
7620     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7621      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7622     ok(!ret && (GetLastError() == E_INVALIDARG ||
7623      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7624      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7625     policy[0].pszPolicyIdentifier = oid_any_policy;
7626     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7627      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7628     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7629     if (ret)
7630     {
7631         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7632         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7633         LocalFree(buf);
7634     }
7635     policy[1].pszPolicyIdentifier = oid1;
7636     memset(&qualifier, 0, sizeof(qualifier));
7637     qualifier.pszPolicyQualifierId = oid_user_notice;
7638     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7639     qualifier.Qualifier.pbData = noticeWithReference;
7640     policy[1].cPolicyQualifier = 1;
7641     policy[1].rgPolicyQualifier = &qualifier;
7642     info.cPolicyInfo = 2;
7643     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7644      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7645     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7646     if (ret)
7647     {
7648         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7649         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7650         LocalFree(buf);
7651     }
7652 }
7653 
7654 static void test_decodeCertPolicies(DWORD dwEncoding)
7655 {
7656     BOOL ret;
7657     CERT_POLICIES_INFO *info;
7658     DWORD size;
7659 
7660     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7661      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7662      &info, &size);
7663     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7664     if (ret)
7665     {
7666         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7667          info->cPolicyInfo);
7668         LocalFree(info);
7669     }
7670     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7671      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7672      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7673     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7674     if (ret)
7675     {
7676         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7677          info->cPolicyInfo);
7678         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7679          "unexpected policy id %s\n",
7680          info->rgPolicyInfo[0].pszPolicyIdentifier);
7681         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7682          "unexpected policy qualifier count %d\n",
7683          info->rgPolicyInfo[0].cPolicyQualifier);
7684         LocalFree(info);
7685     }
7686     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7687      twoPolicies, sizeof(twoPolicies),
7688      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7689     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7690     if (ret)
7691     {
7692         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7693          info->cPolicyInfo);
7694         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7695          "unexpected policy id %s\n",
7696          info->rgPolicyInfo[0].pszPolicyIdentifier);
7697         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7698          "unexpected policy qualifier count %d\n",
7699          info->rgPolicyInfo[0].cPolicyQualifier);
7700         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7701          "unexpected policy id %s\n",
7702          info->rgPolicyInfo[1].pszPolicyIdentifier);
7703         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7704          "unexpected policy qualifier count %d\n",
7705          info->rgPolicyInfo[1].cPolicyQualifier);
7706         ok(!strcmp(
7707          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7708          oid_user_notice), "unexpected policy qualifier id %s\n",
7709          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7710         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7711          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7712          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7713         ok(!memcmp(
7714          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7715          noticeWithReference, sizeof(noticeWithReference)),
7716          "unexpected qualifier value\n");
7717         LocalFree(info);
7718     }
7719     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7720      twoPolicies, sizeof(twoPolicies), 0, NULL, NULL, &size);
7721     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7722     info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7723     if (info)
7724     {
7725         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7726          twoPolicies, sizeof(twoPolicies), 0, NULL, info, &size);
7727         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7728         HeapFree(GetProcessHeap(), 0, info);
7729     }
7730 }
7731 
7732 static const BYTE policyMappingWithOneMapping[] = {
7733 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7734 static const BYTE policyMappingWithTwoMappings[] = {
7735 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7736 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7737 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7738  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7739 
7740 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7741 {
7742     static char oid2[] = "2.3.4";
7743     static char oid3[] = "1.3.4";
7744     static char oid4[] = "2.5.6";
7745     BOOL ret;
7746     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7747     CERT_POLICY_MAPPING mapping[2];
7748     LPBYTE buf;
7749     DWORD size, i;
7750 
7751     /* Each of the mapping OIDs is equivalent, so check with all of them */
7752     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7753     {
7754         memset(&info, 0, sizeof(info));
7755         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7756          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7757         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7758          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7759         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7760         {
7761             win_skip("no policy mappings support\n");
7762             return;
7763         }
7764         if (ret)
7765         {
7766             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7767             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7768              "unexpected value\n");
7769             LocalFree(buf);
7770         }
7771         mapping[0].pszIssuerDomainPolicy = NULL;
7772         mapping[0].pszSubjectDomainPolicy = NULL;
7773         info.cPolicyMapping = 1;
7774         info.rgPolicyMapping = mapping;
7775         SetLastError(0xdeadbeef);
7776         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7777          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7778         ok(!ret && GetLastError() == E_INVALIDARG,
7779          "expected E_INVALIDARG, got %08x\n", GetLastError());
7780         mapping[0].pszIssuerDomainPolicy = oid1;
7781         mapping[0].pszSubjectDomainPolicy = oid2;
7782         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7783          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7784         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7785         if (ret)
7786         {
7787             ok(size == sizeof(policyMappingWithOneMapping),
7788              "unexpected size %d\n", size);
7789             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7790              "unexpected value\n");
7791             LocalFree(buf);
7792         }
7793         mapping[1].pszIssuerDomainPolicy = oid3;
7794         mapping[1].pszSubjectDomainPolicy = oid4;
7795         info.cPolicyMapping = 2;
7796         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7797          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7798         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7799         if (ret)
7800         {
7801             ok(size == sizeof(policyMappingWithTwoMappings),
7802              "unexpected size %d\n", size);
7803             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7804              "unexpected value\n");
7805             LocalFree(buf);
7806         }
7807     }
7808 }
7809 
7810 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7811 {
7812     DWORD size, i;
7813     CERT_POLICY_MAPPINGS_INFO *info;
7814     BOOL ret;
7815 
7816     /* Each of the mapping OIDs is equivalent, so check with all of them */
7817     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7818     {
7819         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7820          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7821          &info, &size);
7822         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7823          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7824         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7825         {
7826             win_skip("no policy mappings support\n");
7827             return;
7828         }
7829         if (ret)
7830         {
7831             ok(info->cPolicyMapping == 0,
7832              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7833             LocalFree(info);
7834         }
7835         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7836          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7837          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7838         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7839         if (ret)
7840         {
7841             ok(info->cPolicyMapping == 1,
7842              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7843             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7844              "unexpected issuer policy %s\n",
7845              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7846             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7847              "2.3.4"), "unexpected subject policy %s\n",
7848              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7849             LocalFree(info);
7850         }
7851         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7852          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7853          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7854         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7855         if (ret)
7856         {
7857             ok(info->cPolicyMapping == 2,
7858              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7859             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7860              "unexpected issuer policy %s\n",
7861              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7862             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7863              "2.3.4"), "unexpected subject policy %s\n",
7864              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7865             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7866              "unexpected issuer policy %s\n",
7867              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7868             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7869              "2.5.6"), "unexpected subject policy %s\n",
7870              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7871             LocalFree(info);
7872         }
7873         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7874          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7875          NULL, NULL, &size);
7876         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7877         info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7878         if (info)
7879         {
7880             ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7881              policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7882              NULL, info, &size);
7883             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7884             HeapFree(GetProcessHeap(), 0, info);
7885         }
7886     }
7887 }
7888 
7889 static const BYTE policyConstraintsWithRequireExplicit[] = {
7890 0x30,0x03,0x80,0x01,0x00 };
7891 static const BYTE policyConstraintsWithInhibitMapping[] = {
7892 0x30,0x03,0x81,0x01,0x01 };
7893 static const BYTE policyConstraintsWithBoth[] = {
7894 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7895 
7896 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7897 {
7898     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7899     LPBYTE buf;
7900     DWORD size;
7901     BOOL ret;
7902 
7903     /* Even though RFC 5280 explicitly states CAs must not issue empty
7904      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7905      */
7906     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7907      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7908     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7909      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7910     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7911     {
7912         win_skip("no policy constraints support\n");
7913         return;
7914     }
7915     if (ret)
7916     {
7917         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7918         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7919          "unexpected value\n");
7920         LocalFree(buf);
7921     }
7922     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7923      * is not, then a skip of 0 is encoded.
7924      */
7925     info.fRequireExplicitPolicy = TRUE;
7926     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7927      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7928     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7929     if (ret)
7930     {
7931         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7932          "unexpected size %d\n", size);
7933         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7934          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7935         LocalFree(buf);
7936     }
7937     /* With inhibit policy mapping */
7938     info.fRequireExplicitPolicy = FALSE;
7939     info.dwRequireExplicitPolicySkipCerts = 0;
7940     info.fInhibitPolicyMapping = TRUE;
7941     info.dwInhibitPolicyMappingSkipCerts = 1;
7942     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7943      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7944     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7945     if (ret)
7946     {
7947         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7948          "unexpected size %d\n", size);
7949         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7950          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7951         LocalFree(buf);
7952     }
7953     /* And with both */
7954     info.fRequireExplicitPolicy = TRUE;
7955     info.dwRequireExplicitPolicySkipCerts = 1;
7956     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7957      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7958     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7959     if (ret)
7960     {
7961         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7962          size);
7963         ok(!memcmp(buf, policyConstraintsWithBoth,
7964          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7965         LocalFree(buf);
7966     }
7967 }
7968 
7969 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7970 {
7971     CERT_POLICY_CONSTRAINTS_INFO *info;
7972     DWORD size;
7973     BOOL ret;
7974 
7975     /* Again, even though CAs must not issue such constraints, they can be
7976      * decoded.
7977      */
7978     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7979      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7980      &info, &size);
7981     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7982      "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7983     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7984     {
7985         win_skip("no policy mappings support\n");
7986         return;
7987     }
7988     if (ret)
7989     {
7990         ok(!info->fRequireExplicitPolicy,
7991          "expected require explicit = FALSE\n");
7992         ok(!info->fInhibitPolicyMapping,
7993          "expected implicit mapping = FALSE\n");
7994         LocalFree(info);
7995     }
7996     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7997      policyConstraintsWithRequireExplicit,
7998      sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7999      NULL, &info, &size);
8000     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
8001     if (ret)
8002     {
8003         ok(info->fRequireExplicitPolicy,
8004          "expected require explicit = TRUE\n");
8005         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
8006          info->dwRequireExplicitPolicySkipCerts);
8007         ok(!info->fInhibitPolicyMapping,
8008          "expected implicit mapping = FALSE\n");
8009         LocalFree(info);
8010     }
8011     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
8012      policyConstraintsWithInhibitMapping,
8013      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
8014      NULL, &info, &size);
8015     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
8016     if (ret)
8017     {
8018         ok(!info->fRequireExplicitPolicy,
8019          "expected require explicit = FALSE\n");
8020         ok(info->fInhibitPolicyMapping,
8021          "expected implicit mapping = TRUE\n");
8022         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
8023          info->dwInhibitPolicyMappingSkipCerts);
8024         LocalFree(info);
8025     }
8026     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
8027      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
8028      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
8029     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
8030     if (ret)
8031     {
8032         ok(info->fRequireExplicitPolicy,
8033          "expected require explicit = TRUE\n");
8034         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
8035          info->dwRequireExplicitPolicySkipCerts);
8036         ok(info->fInhibitPolicyMapping,
8037          "expected implicit mapping = TRUE\n");
8038         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
8039          info->dwInhibitPolicyMappingSkipCerts);
8040         LocalFree(info);
8041     }
8042 }
8043 
8044 static const BYTE rsaPrivKeyDer[] = {
8045 0x30,0x82,0x04,0xa5,0x02,0x01,0x00,0x02,0x82,0x01,0x01,0x00,
8046 0xae,0xba,0x3c,0x41,0xeb,0x25,0x41,0xb0,0x1c,0x41,0xd4,0x26,
8047 0xf9,0xf8,0x31,0x64,0x7e,0x97,0x65,0x54,0x9c,0x90,0xdf,0x34,
8048 0x07,0xfb,0xb0,0x69,0x99,0x3b,0x45,0x39,0x06,0xe4,0x3a,0x7a,
8049 0x01,0xe0,0xeb,0x3f,0xe1,0xd5,0x91,0xe0,0x16,0xe0,0xf2,0x35,
8050 0x59,0xdf,0x32,0x2d,0x69,0x3a,0x4a,0xbc,0xd1,0xba,0x1b,0x3b,
8051 0x7a,0x55,0x76,0xba,0x11,0xdd,0x2f,0xc7,0x58,0x66,0xf2,0x6c,
8052 0xd1,0x68,0x27,0x6c,0x85,0x74,0x0b,0xc9,0x7b,0x1a,0xde,0x3c,
8053 0x62,0x73,0xe2,0x9e,0x36,0x3a,0x29,0x3b,0x91,0x85,0x3d,0xd2,
8054 0xe1,0xe5,0x61,0x84,0x1e,0x28,0xfd,0xb7,0x97,0x68,0xc1,0xbb,
8055 0x0f,0x93,0x14,0xc2,0x03,0x60,0x41,0x11,0x7a,0xda,0x76,0x01,
8056 0x65,0x08,0xe6,0x0c,0xf6,0xfc,0x1d,0x64,0x12,0x7b,0x42,0xb0,
8057 0xb8,0xfe,0x61,0xe5,0xe2,0xe5,0x61,0x44,0xcc,0x94,0xe8,0xc0,
8058 0x4f,0x58,0x9a,0xea,0x99,0xaf,0x9c,0xa4,0xf2,0xd7,0x2b,0x31,
8059 0x90,0x3b,0x41,0x2e,0x4a,0x74,0x7c,0x1a,0xfc,0x42,0xa9,0x17,
8060 0xff,0x53,0x20,0x76,0xa7,0xf0,0x2c,0xb9,0xd5,0x1f,0xa9,0x8a,
8061 0x77,0xa8,0x09,0x5c,0x0e,0xd1,0x54,0xc5,0xf2,0x86,0xf1,0x2f,
8062 0x23,0xd6,0x63,0xba,0xe9,0x2b,0x73,0xf9,0xf0,0xdc,0xcb,0xf9,
8063 0xcb,0xe8,0x40,0x62,0x47,0x09,0x85,0xe1,0x9c,0xfd,0xcf,0x75,
8064 0x5a,0x65,0xfd,0x86,0x1c,0x50,0xfa,0x24,0x36,0x0f,0x54,0x5e,
8065 0x81,0xe7,0xf6,0x63,0x2d,0x87,0x0c,0x50,0x03,0x25,0x49,0xe7,
8066 0xc5,0x20,0xaa,0xbc,0x6c,0xf9,0xbe,0x49,0x8f,0x4f,0xb8,0x9a,
8067 0x73,0x9f,0x55,0x43,0x02,0x03,0x01,0x00,0x01,0x02,0x82,0x01,
8068 0x01,0x00,0x99,0x03,0xcd,0x5b,0x69,0x03,0x32,0x98,0x78,0xd6,
8069 0x89,0x65,0x2c,0xc9,0xd6,0xef,0x8c,0x11,0x27,0x93,0x46,0x9d,
8070 0x74,0x6a,0xcb,0x86,0xf6,0x02,0x34,0x47,0xfc,0xa2,0x29,0x4f,
8071 0xdb,0x8a,0x17,0x75,0x12,0x6f,0xda,0x65,0x3f,0x1f,0xc0,0xc9,
8072 0x74,0x33,0x96,0xa5,0xe8,0xfa,0x6d,0xc9,0xb7,0xc3,0xcd,0xe3,
8073 0x2e,0x90,0x12,0xdd,0x1f,0x61,0x69,0xdd,0x8b,0x47,0x07,0x3a,
8074 0xf8,0x98,0xa5,0x76,0x91,0xf7,0xee,0x93,0x26,0xf3,0x66,0x54,
8075 0xac,0x44,0xb3,0x6f,0x8b,0x09,0x44,0xb2,0x00,0x84,0x03,0x37,
8076 0x6d,0x61,0xed,0xa4,0x04,0x97,0x40,0x16,0x63,0xc2,0xd0,0xdc,
8077 0xd3,0xb3,0xee,0xba,0xbe,0x95,0xfd,0x80,0xe0,0xda,0xde,0xfc,
8078 0xcc,0x15,0x02,0x97,0x1d,0x68,0x43,0x2f,0x9c,0xc8,0x20,0x23,
8079 0xeb,0x00,0x4c,0x74,0x3d,0x27,0x20,0x14,0x23,0x95,0xfc,0x8c,
8080 0xb7,0x7e,0x7f,0xb0,0xdb,0xaf,0x8a,0x48,0x1b,0xfe,0x59,0xab,
8081 0x75,0xe2,0xbf,0x69,0xf2,0x73,0xe3,0xb9,0x92,0xa9,0x90,0x03,
8082 0xe5,0xd4,0x2d,0x86,0xff,0x12,0x54,0xb3,0xbb,0xe2,0xce,0x81,
8083 0x58,0x71,0xa4,0xde,0x45,0x05,0xf8,0x2d,0x45,0xf5,0xd8,0x5e,
8084 0x4c,0x5d,0x06,0x69,0x0c,0x86,0x9f,0x66,0x9f,0xb1,0x60,0xfd,
8085 0xf2,0x33,0x85,0x15,0xd5,0x18,0xf7,0xba,0x99,0x65,0x15,0x1d,
8086 0xfa,0xaa,0x76,0xdd,0x25,0xed,0xdf,0x90,0x6e,0xba,0x61,0x96,
8087 0x79,0xde,0xd2,0xda,0x66,0x03,0x74,0x3b,0x13,0x39,0x68,0xbc,
8088 0x94,0x01,0x00,0x2d,0xf8,0xf0,0x8c,0xbd,0x4c,0x9c,0x7e,0x87,
8089 0x9c,0x62,0x9f,0xb6,0x90,0x11,0x02,0x81,0x81,0x00,0xe3,0x5e,
8090 0xfe,0xdd,0xed,0x76,0xb6,0x4e,0xfc,0x5b,0xe0,0x20,0x99,0x7b,
8091 0x48,0x3b,0x1e,0x5f,0x7f,0x9f,0xa4,0x68,0xbe,0xc3,0x7f,0xb8,
8092 0x62,0x98,0xb0,0x95,0x8a,0xfa,0x0d,0xa3,0x79,0x63,0x39,0xf7,
8093 0xdb,0x76,0x3d,0x53,0x4a,0x0a,0x33,0xdf,0xe0,0x47,0x22,0xd5,
8094 0x96,0x80,0xc7,0xcd,0x24,0xef,0xac,0x49,0x46,0x37,0x6c,0x25,
8095 0xcf,0x6c,0x4d,0xe5,0x31,0xf8,0x2f,0xd2,0x59,0x74,0x00,0x38,
8096 0xdb,0xce,0xd1,0x72,0xc3,0xa8,0x30,0x70,0xd8,0x02,0x20,0xe7,
8097 0x56,0xe7,0xca,0xf0,0x3b,0x52,0x5d,0x11,0xbe,0x53,0x4e,0xd0,
8098 0xd9,0x2e,0xa6,0xb8,0xe2,0xd9,0xbf,0xb9,0x77,0xe7,0x3b,0xed,
8099 0x5e,0xd7,0x16,0x4a,0x3a,0xc5,0x86,0xd7,0x74,0x20,0xa7,0x8e,
8100 0xbf,0xb7,0x33,0xdb,0x51,0xe9,0x02,0x81,0x81,0x00,0xc4,0xba,
8101 0x57,0xf0,0x6e,0xcf,0xe8,0xce,0xce,0x9d,0x4a,0xe9,0x0f,0xe1,
8102 0xab,0x91,0x62,0xaa,0x66,0x5d,0x82,0x66,0x1c,0x72,0x18,0x6f,
8103 0x68,0x9c,0x7d,0x5e,0xfc,0xaf,0x4a,0xd6,0x8e,0xc6,0xae,0x40,
8104 0xf2,0x40,0x84,0x93,0xee,0x7c,0x87,0xa9,0xa6,0xcd,0x2b,0xc3,
8105 0xe6,0x29,0x3a,0xe2,0x4a,0xed,0xb0,0x4d,0x9f,0xc0,0xe9,0xd6,
8106 0xa3,0xca,0x97,0xee,0xac,0xab,0xa4,0x32,0x05,0x40,0x4d,0xf2,
8107 0x95,0x99,0xaf,0xa0,0xe1,0xe1,0xe7,0x3a,0x64,0xa4,0x70,0x6b,
8108 0x3d,0x1d,0x7b,0xf1,0x53,0xfa,0xb0,0xe0,0xe2,0x68,0x1a,0x61,
8109 0x2c,0x37,0xa5,0x39,0x7b,0xb2,0xcf,0xe6,0x5f,0x9b,0xc6,0x64,
8110 0xaf,0x48,0x86,0xfb,0xc1,0xf3,0x39,0x97,0x10,0x36,0xf5,0xa9,
8111 0x3d,0x08,0xa5,0x2f,0xe6,0x4b,0x02,0x81,0x81,0x00,0x86,0xe7,
8112 0x02,0x08,0xe2,0xaf,0xa0,0x93,0x54,0x9f,0x9e,0x67,0x39,0x29,
8113 0x30,0x3e,0x03,0x53,0x5e,0x01,0x76,0x26,0xbf,0xa8,0x76,0xcb,
8114 0x0b,0x94,0xd4,0x90,0xa5,0x98,0x9f,0x26,0xf3,0x0a,0xb0,0x86,
8115 0x22,0xac,0x10,0xce,0xae,0x0b,0x47,0xa3,0xf9,0x09,0xbb,0xdd,
8116 0x46,0x22,0xba,0x69,0x39,0x15,0x0a,0xff,0x9e,0xad,0x9b,0x79,
8117 0x03,0x8c,0x9a,0xda,0xf5,0xbe,0xef,0x80,0xba,0x9a,0x5c,0xd7,
8118 0x5f,0x73,0x62,0x49,0xd9,0x54,0x9d,0x09,0x16,0xe0,0x8c,0x6d,
8119 0x35,0xde,0xe9,0x45,0x87,0xac,0xe2,0x93,0x78,0x7d,0x2d,0x32,
8120 0x34,0xe9,0xbc,0xf9,0xcd,0x7e,0xac,0x86,0x7a,0x61,0xb3,0xe8,
8121 0xae,0x70,0xa7,0x44,0xfb,0x81,0xde,0xf3,0x4e,0x6f,0x61,0x7b,
8122 0x0c,0xbc,0xc2,0x03,0xca,0xa1,0x02,0x81,0x80,0x69,0x5b,0x4a,
8123 0xa1,0x4f,0x17,0x35,0x9d,0x1b,0xf6,0x0d,0x1a,0x48,0x11,0x19,
8124 0xab,0x20,0xe6,0x15,0x30,0x5b,0x17,0x88,0x80,0x6a,0x29,0xb0,
8125 0x22,0xae,0xd9,0xe2,0x05,0x96,0xd4,0xd5,0x5d,0xfe,0x10,0x76,
8126 0x2c,0xab,0x53,0xf6,0x52,0xe6,0xec,0xaa,0x92,0x12,0xb0,0x35,
8127 0x61,0x3b,0x51,0xd9,0xc2,0xf5,0xba,0x7c,0xa5,0xfa,0x15,0xa3,
8128 0x5e,0x6a,0x83,0xbe,0x21,0xa6,0x2b,0xcb,0xb8,0x26,0x86,0x96,
8129 0x2b,0xda,0x6d,0x14,0xcb,0xc0,0xe3,0xfa,0xe6,0x3d,0xf6,0x90,
8130 0xa2,0x6b,0xb0,0x50,0xc3,0x5f,0x5a,0xf0,0xa5,0xc4,0x0a,0xea,
8131 0x7d,0x5a,0x95,0x30,0x74,0x10,0xf7,0x55,0x98,0xbd,0x65,0x4a,
8132 0xa2,0x52,0xf8,0x1d,0x64,0xbf,0x20,0xf1,0xe4,0x1d,0x28,0x67,
8133 0xb1,0x6b,0x95,0xfd,0x85,0x02,0x81,0x81,0x00,0xda,0xb4,0x31,
8134 0x34,0xe1,0xec,0x9a,0x1e,0x07,0xd7,0xda,0x20,0x46,0xbf,0x6b,
8135 0xf0,0x45,0xbd,0x50,0xa2,0x0f,0x8a,0x14,0x51,0x52,0x83,0x7c,
8136 0x47,0xc8,0x9c,0x4e,0x68,0x6b,0xae,0x00,0x25,0x63,0xdd,0x13,
8137 0x2a,0x66,0x65,0xb6,0x74,0x91,0x5b,0xb6,0x47,0x3e,0x8e,0x46,
8138 0x62,0xcd,0x9d,0xc1,0xf7,0x14,0x14,0xbc,0x60,0xd6,0x3c,0x7c,
8139 0x3a,0xce,0xff,0x96,0x04,0x84,0xf6,0x44,0x1a,0xf8,0xdb,0x40,
8140 0x1c,0xf2,0xf1,0x4d,0xb2,0x68,0x3e,0xa3,0x0b,0xc6,0xb1,0xd0,
8141 0xa6,0x88,0x18,0x68,0xa1,0x05,0x2a,0xfc,0x2b,0x3a,0xa1,0xe6,
8142 0x31,0x4a,0x46,0x88,0x39,0x1e,0x44,0x11,0x6c,0xc5,0x8b,0xb6,
8143 0x8b,0xce,0x3d,0xd5,0xcb,0xbd,0xf0,0xd4,0xd9,0xfb,0x02,0x35,
8144 0x96,0x39,0x26,0x85,0xf9 };
8145 static const BYTE rsaPrivKeyModulus[] = {
8146 0x43,0x55,0x9f,0x73,0x9a,0xb8,0x4f,0x8f,0x49,0xbe,0xf9,0x6c,
8147 0xbc,0xaa,0x20,0xc5,0xe7,0x49,0x25,0x03,0x50,0x0c,0x87,0x2d,
8148 0x63,0xf6,0xe7,0x81,0x5e,0x54,0x0f,0x36,0x24,0xfa,0x50,0x1c,
8149 0x86,0xfd,0x65,0x5a,0x75,0xcf,0xfd,0x9c,0xe1,0x85,0x09,0x47,
8150 0x62,0x40,0xe8,0xcb,0xf9,0xcb,0xdc,0xf0,0xf9,0x73,0x2b,0xe9,
8151 0xba,0x63,0xd6,0x23,0x2f,0xf1,0x86,0xf2,0xc5,0x54,0xd1,0x0e,
8152 0x5c,0x09,0xa8,0x77,0x8a,0xa9,0x1f,0xd5,0xb9,0x2c,0xf0,0xa7,
8153 0x76,0x20,0x53,0xff,0x17,0xa9,0x42,0xfc,0x1a,0x7c,0x74,0x4a,
8154 0x2e,0x41,0x3b,0x90,0x31,0x2b,0xd7,0xf2,0xa4,0x9c,0xaf,0x99,
8155 0xea,0x9a,0x58,0x4f,0xc0,0xe8,0x94,0xcc,0x44,0x61,0xe5,0xe2,
8156 0xe5,0x61,0xfe,0xb8,0xb0,0x42,0x7b,0x12,0x64,0x1d,0xfc,0xf6,
8157 0x0c,0xe6,0x08,0x65,0x01,0x76,0xda,0x7a,0x11,0x41,0x60,0x03,
8158 0xc2,0x14,0x93,0x0f,0xbb,0xc1,0x68,0x97,0xb7,0xfd,0x28,0x1e,
8159 0x84,0x61,0xe5,0xe1,0xd2,0x3d,0x85,0x91,0x3b,0x29,0x3a,0x36,
8160 0x9e,0xe2,0x73,0x62,0x3c,0xde,0x1a,0x7b,0xc9,0x0b,0x74,0x85,
8161 0x6c,0x27,0x68,0xd1,0x6c,0xf2,0x66,0x58,0xc7,0x2f,0xdd,0x11,
8162 0xba,0x76,0x55,0x7a,0x3b,0x1b,0xba,0xd1,0xbc,0x4a,0x3a,0x69,
8163 0x2d,0x32,0xdf,0x59,0x35,0xf2,0xe0,0x16,0xe0,0x91,0xd5,0xe1,
8164 0x3f,0xeb,0xe0,0x01,0x7a,0x3a,0xe4,0x06,0x39,0x45,0x3b,0x99,
8165 0x69,0xb0,0xfb,0x07,0x34,0xdf,0x90,0x9c,0x54,0x65,0x97,0x7e,
8166 0x64,0x31,0xf8,0xf9,0x26,0xd4,0x41,0x1c,0xb0,0x41,0x25,0xeb,
8167 0x41,0x3c,0xba,0xae };
8168 static const BYTE rsaPrivKeyPrime1[] = {
8169 0xe9,0x51,0xdb,0x33,0xb7,0xbf,0x8e,0xa7,0x20,0x74,0xd7,0x86,
8170 0xc5,0x3a,0x4a,0x16,0xd7,0x5e,0xed,0x3b,0xe7,0x77,0xb9,0xbf,
8171 0xd9,0xe2,0xb8,0xa6,0x2e,0xd9,0xd0,0x4e,0x53,0xbe,0x11,0x5d,
8172 0x52,0x3b,0xf0,0xca,0xe7,0x56,0xe7,0x20,0x02,0xd8,0x70,0x30,
8173 0xa8,0xc3,0x72,0xd1,0xce,0xdb,0x38,0x00,0x74,0x59,0xd2,0x2f,
8174 0xf8,0x31,0xe5,0x4d,0x6c,0xcf,0x25,0x6c,0x37,0x46,0x49,0xac,
8175 0xef,0x24,0xcd,0xc7,0x80,0x96,0xd5,0x22,0x47,0xe0,0xdf,0x33,
8176 0x0a,0x4a,0x53,0x3d,0x76,0xdb,0xf7,0x39,0x63,0x79,0xa3,0x0d,
8177 0xfa,0x8a,0x95,0xb0,0x98,0x62,0xb8,0x7f,0xc3,0xbe,0x68,0xa4,
8178 0x9f,0x7f,0x5f,0x1e,0x3b,0x48,0x7b,0x99,0x20,0xe0,0x5b,0xfc,
8179 0x4e,0xb6,0x76,0xed,0xdd,0xfe,0x5e,0xe3 };
8180 static const BYTE rsaPrivKeyPrime2[] = {
8181 0x4b,0xe6,0x2f,0xa5,0x08,0x3d,0xa9,0xf5,0x36,0x10,0x97,0x39,
8182 0xf3,0xc1,0xfb,0x86,0x48,0xaf,0x64,0xc6,0x9b,0x5f,0xe6,0xcf,
8183 0xb2,0x7b,0x39,0xa5,0x37,0x2c,0x61,0x1a,0x68,0xe2,0xe0,0xb0,
8184 0xfa,0x53,0xf1,0x7b,0x1d,0x3d,0x6b,0x70,0xa4,0x64,0x3a,0xe7,
8185 0xe1,0xe1,0xa0,0xaf,0x99,0x95,0xf2,0x4d,0x40,0x05,0x32,0xa4,
8186 0xab,0xac,0xee,0x97,0xca,0xa3,0xd6,0xe9,0xc0,0x9f,0x4d,0xb0,
8187 0xed,0x4a,0xe2,0x3a,0x29,0xe6,0xc3,0x2b,0xcd,0xa6,0xa9,0x87,
8188 0x7c,0xee,0x93,0x84,0x40,0xf2,0x40,0xae,0xc6,0x8e,0xd6,0x4a,
8189 0xaf,0xfc,0x5e,0x7d,0x9c,0x68,0x6f,0x18,0x72,0x1c,0x66,0x82,
8190 0x5d,0x66,0xaa,0x62,0x91,0xab,0xe1,0x0f,0xe9,0x4a,0x9d,0xce,
8191 0xce,0xe8,0xcf,0x6e,0xf0,0x57,0xba,0xc4 };
8192 static const BYTE rsaPrivKeyExponent1[] = {
8193 0xa1,0xca,0x03,0xc2,0xbc,0x0c,0x7b,0x61,0x6f,0x4e,0xf3,0xde,
8194 0x81,0xfb,0x44,0xa7,0x70,0xae,0xe8,0xb3,0x61,0x7a,0x86,0xac,
8195 0x7e,0xcd,0xf9,0xbc,0xe9,0x34,0x32,0x2d,0x7d,0x78,0x93,0xe2,
8196 0xac,0x87,0x45,0xe9,0xde,0x35,0x6d,0x8c,0xe0,0x16,0x09,0x9d,
8197 0x54,0xd9,0x49,0x62,0x73,0x5f,0xd7,0x5c,0x9a,0xba,0x80,0xef,
8198 0xbe,0xf5,0xda,0x9a,0x8c,0x03,0x79,0x9b,0xad,0x9e,0xff,0x0a,
8199 0x15,0x39,0x69,0xba,0x22,0x46,0xdd,0xbb,0x09,0xf9,0xa3,0x47,
8200 0x0b,0xae,0xce,0x10,0xac,0x22,0x86,0xb0,0x0a,0xf3,0x26,0x9f,
8201 0x98,0xa5,0x90,0xd4,0x94,0x0b,0xcb,0x76,0xa8,0xbf,0x26,0x76,
8202 0x01,0x5e,0x53,0x03,0x3e,0x30,0x29,0x39,0x67,0x9e,0x9f,0x54,
8203 0x93,0xa0,0xaf,0xe2,0x08,0x02,0xe7,0x86 };
8204 static const BYTE rsaPrivKeyExponent2[] = {
8205 0x85,0xfd,0x95,0x6b,0xb1,0x67,0x28,0x1d,0xe4,0xf1,0x20,0xbf,
8206 0x64,0x1d,0xf8,0x52,0xa2,0x4a,0x65,0xbd,0x98,0x55,0xf7,0x10,
8207 0x74,0x30,0x95,0x5a,0x7d,0xea,0x0a,0xc4,0xa5,0xf0,0x5a,0x5f,
8208 0xc3,0x50,0xb0,0x6b,0xa2,0x90,0xf6,0x3d,0xe6,0xfa,0xe3,0xc0,
8209 0xcb,0x14,0x6d,0xda,0x2b,0x96,0x86,0x26,0xb8,0xcb,0x2b,0xa6,
8210 0x21,0xbe,0x83,0x6a,0x5e,0xa3,0x15,0xfa,0xa5,0x7c,0xba,0xf5,
8211 0xc2,0xd9,0x51,0x3b,0x61,0x35,0xb0,0x12,0x92,0xaa,0xec,0xe6,
8212 0x52,0xf6,0x53,0xab,0x2c,0x76,0x10,0xfe,0x5d,0xd5,0xd4,0x96,
8213 0x05,0xe2,0xd9,0xae,0x22,0xb0,0x29,0x6a,0x80,0x88,0x17,0x5b,
8214 0x30,0x15,0xe6,0x20,0xab,0x19,0x11,0x48,0x1a,0x0d,0xf6,0x1b,
8215 0x9d,0x35,0x17,0x4f,0xa1,0x4a,0x5b,0x69 };
8216 static const BYTE rsaPrivKeyCoefficient[] = {
8217 0xf9,0x85,0x26,0x39,0x96,0x35,0x02,0xfb,0xd9,0xd4,0xf0,0xbd,
8218 0xcb,0xd5,0x3d,0xce,0x8b,0xb6,0x8b,0xc5,0x6c,0x11,0x44,0x1e,
8219 0x39,0x88,0x46,0x4a,0x31,0xe6,0xa1,0x3a,0x2b,0xfc,0x2a,0x05,
8220 0xa1,0x68,0x18,0x88,0xa6,0xd0,0xb1,0xc6,0x0b,0xa3,0x3e,0x68,
8221 0xb2,0x4d,0xf1,0xf2,0x1c,0x40,0xdb,0xf8,0x1a,0x44,0xf6,0x84,
8222 0x04,0x96,0xff,0xce,0x3a,0x7c,0x3c,0xd6,0x60,0xbc,0x14,0x14,
8223 0xf7,0xc1,0x9d,0xcd,0x62,0x46,0x8e,0x3e,0x47,0xb6,0x5b,0x91,
8224 0x74,0xb6,0x65,0x66,0x2a,0x13,0xdd,0x63,0x25,0x00,0xae,0x6b,
8225 0x68,0x4e,0x9c,0xc8,0x47,0x7c,0x83,0x52,0x51,0x14,0x8a,0x0f,
8226 0xa2,0x50,0xbd,0x45,0xf0,0x6b,0xbf,0x46,0x20,0xda,0xd7,0x07,
8227 0x1e,0x9a,0xec,0xe1,0x34,0x31,0xb4,0xda };
8228 static const BYTE rsaPrivKeyPrivateExponent[] = {
8229 0x11,0x90,0xb6,0x9f,0x62,0x9c,0x87,0x7e,0x9c,0x4c,0xbd,0x8c,
8230 0xf0,0xf8,0x2d,0x00,0x01,0x94,0xbc,0x68,0x39,0x13,0x3b,0x74,
8231 0x03,0x66,0xda,0xd2,0xde,0x79,0x96,0x61,0xba,0x6e,0x90,0xdf,
8232 0xed,0x25,0xdd,0x76,0xaa,0xfa,0x1d,0x15,0x65,0x99,0xba,0xf7,
8233 0x18,0xd5,0x15,0x85,0x33,0xf2,0xfd,0x60,0xb1,0x9f,0x66,0x9f,
8234 0x86,0x0c,0x69,0x06,0x5d,0x4c,0x5e,0xd8,0xf5,0x45,0x2d,0xf8,
8235 0x05,0x45,0xde,0xa4,0x71,0x58,0x81,0xce,0xe2,0xbb,0xb3,0x54,
8236 0x12,0xff,0x86,0x2d,0xd4,0xe5,0x03,0x90,0xa9,0x92,0xb9,0xe3,
8237 0x73,0xf2,0x69,0xbf,0xe2,0x75,0xab,0x59,0xfe,0x1b,0x48,0x8a,
8238 0xaf,0xdb,0xb0,0x7f,0x7e,0xb7,0x8c,0xfc,0x95,0x23,0x14,0x20,
8239 0x27,0x3d,0x74,0x4c,0x00,0xeb,0x23,0x20,0xc8,0x9c,0x2f,0x43,
8240 0x68,0x1d,0x97,0x02,0x15,0xcc,0xfc,0xde,0xda,0xe0,0x80,0xfd,
8241 0x95,0xbe,0xba,0xee,0xb3,0xd3,0xdc,0xd0,0xc2,0x63,0x16,0x40,
8242 0x97,0x04,0xa4,0xed,0x61,0x6d,0x37,0x03,0x84,0x00,0xb2,0x44,
8243 0x09,0x8b,0x6f,0xb3,0x44,0xac,0x54,0x66,0xf3,0x26,0x93,0xee,
8244 0xf7,0x91,0x76,0xa5,0x98,0xf8,0x3a,0x07,0x47,0x8b,0xdd,0x69,
8245 0x61,0x1f,0xdd,0x12,0x90,0x2e,0xe3,0xcd,0xc3,0xb7,0xc9,0x6d,
8246 0xfa,0xe8,0xa5,0x96,0x33,0x74,0xc9,0xc0,0x1f,0x3f,0x65,0xda,
8247 0x6f,0x12,0x75,0x17,0x8a,0xdb,0x4f,0x29,0xa2,0xfc,0x47,0x34,
8248 0x02,0xf6,0x86,0xcb,0x6a,0x74,0x9d,0x46,0x93,0x27,0x11,0x8c,
8249 0xef,0xd6,0xc9,0x2c,0x65,0x89,0xd6,0x78,0x98,0x32,0x03,0x69,
8250 0x5b,0xcd,0x03,0x99 };
8251 
8252 static void test_decodeRsaPrivateKey(DWORD dwEncoding)
8253 {
8254     LPBYTE buf = NULL;
8255     DWORD bufSize = 0;
8256     BOOL ret;
8257 
8258     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
8259      rsaPrivKeyDer, sizeof(rsaPrivKeyDer)-10,
8260      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
8261     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD),
8262      "Expected CRYPT_E_ASN1_EOD, got %08x\n",
8263      GetLastError());
8264 
8265     buf = NULL;
8266     bufSize = 0;
8267     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
8268      rsaPrivKeyDer, sizeof(rsaPrivKeyDer),
8269      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
8270     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
8271 
8272     if (ret)
8273     {
8274         BLOBHEADER *hdr = (BLOBHEADER *)buf;
8275         RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
8276         static const int bitlen = 2048;
8277         BYTE *modulus = (BYTE*)(rsaPubKey + 1);
8278         BYTE *prime1 = modulus + bitlen/8;
8279         BYTE *prime2 = prime1 + bitlen/16;
8280         BYTE *exponent1 = prime2 + bitlen/16;
8281         BYTE *exponent2 = exponent1 + bitlen/16;
8282         BYTE *coefficient = exponent2 + bitlen/16;
8283         BYTE *privateExponent = coefficient + bitlen/16;
8284 
8285         ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
8286             (bitlen * 9 / 16),
8287          "Wrong size %d\n", bufSize);
8288 
8289         ok(hdr->bType == PRIVATEKEYBLOB,
8290          "Expected type PRIVATEKEYBLOB (%d), got %d\n", PRIVATEKEYBLOB,
8291          hdr->bType);
8292         ok(hdr->bVersion == CUR_BLOB_VERSION,
8293          "Expected version CUR_BLOB_VERSION (%d), got %d\n",
8294          CUR_BLOB_VERSION, hdr->bVersion);
8295         ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
8296          hdr->reserved);
8297         ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
8298          "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
8299 
8300         ok(rsaPubKey->magic == 0x32415352,
8301          "Expected magic 0x32415352, got 0x%x\n", rsaPubKey->magic);
8302         ok(rsaPubKey->bitlen == bitlen,
8303          "Expected bitlen %d, got %d\n", bitlen, rsaPubKey->bitlen);
8304         ok(rsaPubKey->pubexp == 65537,
8305          "Expected pubexp 65537, got %d\n", rsaPubKey->pubexp);
8306 
8307         ok(!memcmp(modulus, rsaPrivKeyModulus, bitlen/8),
8308          "unexpected modulus\n");
8309         ok(!memcmp(prime1, rsaPrivKeyPrime1, bitlen/16),
8310          "unexpected prime1\n");
8311         ok(!memcmp(prime2, rsaPrivKeyPrime2, bitlen/16),
8312          "unexpected prime2\n");
8313         ok(!memcmp(exponent1, rsaPrivKeyExponent1, bitlen/16),
8314          "unexpected exponent1\n");
8315         ok(!memcmp(exponent2, rsaPrivKeyExponent2, bitlen/16),
8316          "unexpected exponent2\n");
8317         ok(!memcmp(coefficient, rsaPrivKeyCoefficient, bitlen/16),
8318          "unexpected coefficient\n");
8319         ok(!memcmp(privateExponent, rsaPrivKeyPrivateExponent, bitlen/8),
8320          "unexpected privateExponent\n");
8321 
8322         LocalFree(buf);
8323     }
8324 }
8325 
8326 /* Free *pInfo with HeapFree */
8327 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
8328 {
8329     BOOL ret;
8330     DWORD size = 0;
8331     HCRYPTKEY key;
8332 
8333     /* This crashes
8334     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
8335      */
8336     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
8337     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8338      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8339     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
8340      &size);
8341     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8342      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8343     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
8344      NULL, &size);
8345     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8346      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8347     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
8348      0, NULL, NULL, &size);
8349     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8350      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8351     /* Test with no key */
8352     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
8353      0, NULL, NULL, &size);
8354     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
8355      GetLastError());
8356     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
8357     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
8358     if (ret)
8359     {
8360         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
8361          NULL, 0, NULL, NULL, &size);
8362         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
8363         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
8364         if (*pInfo)
8365         {
8366             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
8367              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
8368             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
8369              GetLastError());
8370             if (ret)
8371             {
8372                 /* By default (we passed NULL as the OID) the OID is
8373                  * szOID_RSA_RSA.
8374                  */
8375                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
8376                  "Expected %s, got %s\n", szOID_RSA_RSA,
8377                  (*pInfo)->Algorithm.pszObjId);
8378             }
8379         }
8380     }
8381     CryptDestroyKey(key);
8382 }
8383 
8384 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
8385  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
8386  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
8387  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
8388  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
8389  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
8390  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
8391  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
8392  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
8393  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
8394  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
8395  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
8396  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
8397  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
8398  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
8399  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
8400  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
8401  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
8402  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
8403  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
8404  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
8405  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
8406  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
8407  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
8408  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
8409 
8410 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
8411 {
8412     BOOL ret;
8413     HCRYPTKEY key;
8414     PCCERT_CONTEXT context;
8415     DWORD dwSize;
8416     ALG_ID ai;
8417 
8418     /* These crash
8419     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
8420     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
8421     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
8422     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
8423      NULL);
8424      */
8425     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
8426     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
8427      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
8428     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
8429     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
8430      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
8431     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
8432      &key);
8433     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8434      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8435 
8436     /* Export key with standard algorithm (CALG_RSA_KEYX) */
8437     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
8438      &key);
8439     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8440 
8441     dwSize = sizeof(ai);
8442     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8443     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8444     if(ret)
8445     {
8446       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8447       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
8448     }
8449 
8450     CryptDestroyKey(key);
8451 
8452     /* Repeat with forced algorithm */
8453     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
8454      &key);
8455     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8456 
8457     dwSize = sizeof(ai);
8458     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8459     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8460     if(ret)
8461     {
8462       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8463       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
8464     }
8465 
8466     CryptDestroyKey(key);
8467 
8468     /* Test importing a public key from a certificate context */
8469     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
8470      sizeof(expiredCert));
8471     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
8472      GetLastError());
8473     if (context)
8474     {
8475         ok(!strcmp(szOID_RSA_RSA,
8476          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
8477          "Expected %s, got %s\n", szOID_RSA_RSA,
8478          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
8479         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
8480          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
8481         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8482         CryptDestroyKey(key);
8483         CertFreeCertificateContext(context);
8484     }
8485 }
8486 
8487 static const char cspName[] = "WineCryptTemp";
8488 
8489 static void testPortPublicKeyInfo(void)
8490 {
8491     HCRYPTPROV csp;
8492     BOOL ret;
8493     PCERT_PUBLIC_KEY_INFO info = NULL;
8494 
8495     /* Just in case a previous run failed, delete this thing */
8496     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8497      CRYPT_DELETEKEYSET);
8498     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8499      CRYPT_NEWKEYSET);
8500     ok(ret,"CryptAcquireContextA failed\n");
8501 
8502     testExportPublicKey(csp, &info);
8503     testImportPublicKey(csp, info);
8504 
8505     HeapFree(GetProcessHeap(), 0, info);
8506     CryptReleaseContext(csp, 0);
8507     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8508      CRYPT_DELETEKEYSET);
8509     ok(ret,"CryptAcquireContextA failed\n");
8510 }
8511 
8512 static const BYTE eccCert[] = {
8513 0x30,0x82,0x01,0x46,0x30,0x81,0xec,0x02,0x09,0x00,0xe7,0x6b,
8514 0x26,0x86,0x0a,0x82,0xff,0xe9,0x30,0x0a,0x06,0x08,0x2a,0x86,
8515 0x48,0xce,0x3d,0x04,0x03,0x02,0x30,0x2b,0x31,0x0b,0x30,0x09,
8516 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x0d,0x30,
8517 0x0b,0x06,0x03,0x55,0x04,0x0a,0x0c,0x04,0x57,0x69,0x6e,0x65,
8518 0x31,0x0d,0x30,0x0b,0x06,0x03,0x55,0x04,0x03,0x0c,0x04,0x57,
8519 0x69,0x6e,0x65,0x30,0x1e,0x17,0x0d,0x31,0x37,0x30,0x39,0x32,
8520 0x37,0x31,0x33,0x34,0x31,0x30,0x34,0x5a,0x17,0x0d,0x32,0x37,
8521 0x30,0x39,0x32,0x35,0x31,0x33,0x34,0x31,0x30,0x34,0x5a,0x30,
8522 0x2b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
8523 0x44,0x45,0x31,0x0d,0x30,0x0b,0x06,0x03,0x55,0x04,0x0a,0x0c,
8524 0x04,0x54,0x65,0x73,0x74,0x31,0x0d,0x30,0x0b,0x06,0x03,0x55,
8525 0x04,0x03,0x0c,0x04,0x54,0x65,0x73,0x74,0x30,0x59,0x30,0x13,
8526 0x06,0x07,0x2a,0x86,0x48,0xce,0x3d,0x02,0x01,0x06,0x08,0x2a,
8527 0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xed,
8528 0xfc,0x77,0xd8,0xb9,0xe7,0xf3,0xf8,0xce,0x13,0xb8,0x7f,0x0f,
8529 0x78,0xea,0x73,0x87,0x29,0x10,0xe1,0x6d,0x10,0xce,0x57,0x60,
8530 0x3b,0x3e,0xb4,0x5f,0x0d,0x20,0xc1,0xeb,0x6d,0x74,0xe9,0x7b,
8531 0x11,0x51,0x9a,0x00,0xe8,0xe9,0x12,0x84,0xb9,0x07,0x7e,0x7b,
8532 0x62,0x67,0x12,0x67,0x08,0xe5,0x2e,0x27,0xce,0xa2,0x57,0x15,
8533 0xad,0xc5,0x1f,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,
8534 0x04,0x03,0x02,0x03,0x49,0x00,0x30,0x46,0x02,0x21,0x00,0xd7,
8535 0x29,0xce,0x5a,0xef,0x74,0x85,0xd1,0x18,0x5f,0x6e,0xf1,0xba,
8536 0x53,0xd4,0xcd,0xdd,0xe0,0x5d,0xf1,0x5e,0x48,0x51,0xea,0x63,
8537 0xc0,0xe8,0xe2,0xf6,0xfa,0x4c,0xaf,0x02,0x21,0x00,0xe3,0x94,
8538 0x15,0x3b,0x6c,0x71,0x6e,0x44,0x22,0xcb,0xa0,0x88,0xcd,0x0a,
8539 0x5a,0x50,0x29,0x7c,0x5c,0xd6,0x6c,0xd2,0xe0,0x7f,0xcd,0x02,
8540 0x92,0x21,0x4c,0x2c,0x92,0xee };
8541 static const BYTE ecdsaSig[] = {
8542 0x30,0x46,0x02,0x21,0x00,0xd7,0x29,0xce,0x5a,0xef,0x74,0x85,
8543 0xd1,0x18,0x5f,0x6e,0xf1,0xba,0x53,0xd4,0xcd,0xdd,0xe0,0x5d,
8544 0xf1,0x5e,0x48,0x51,0xea,0x63,0xc0,0xe8,0xe2,0xf6,0xfa,0x4c,
8545 0xaf,0x02,0x21,0x00,0xe3,0x94,0x15,0x3b,0x6c,0x71,0x6e,0x44,
8546 0x22,0xcb,0xa0,0x88,0xcd,0x0a,0x5a,0x50,0x29,0x7c,0x5c,0xd6,
8547 0x6c,0xd2,0xe0,0x7f,0xcd,0x02,0x92,0x21,0x4c,0x2c,0x92,0xee };
8548 static const BYTE eccPubKey[] = {
8549 0x30,0x59,0x30,0x13,0x06,0x07,0x2a,0x86,0x48,0xce,0x3d,0x02,
8550 0x01,0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03,
8551 0x42,0x00,0x04,0xed,0xfc,0x77,0xd8,0xb9,0xe7,0xf3,0xf8,0xce,
8552 0x13,0xb8,0x7f,0x0f,0x78,0xea,0x73,0x87,0x29,0x10,0xe1,0x6d,
8553 0x10,0xce,0x57,0x60,0x3b,0x3e,0xb4,0x5f,0x0d,0x20,0xc1,0xeb,
8554 0x6d,0x74,0xe9,0x7b,0x11,0x51,0x9a,0x00,0xe8,0xe9,0x12,0x84,
8555 0xb9,0x07,0x7e,0x7b,0x62,0x67,0x12,0x67,0x08,0xe5,0x2e,0x27,
8556 0xce,0xa2,0x57,0x15,0xad,0xc5,0x1f };
8557 
8558 static void testECDSACert(void)
8559 {
8560     DWORD decode_flags = CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG;
8561     CERT_SIGNED_CONTENT_INFO *info;
8562     CERT_PUBLIC_KEY_INFO *pubkey;
8563     CERT_ECC_SIGNATURE *ecc_sig;
8564     LPSTR *ecc_curve;
8565     DWORD size;
8566     BOOL ret;
8567     int i;
8568 
8569     info = NULL;
8570     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT, eccCert, sizeof(eccCert), decode_flags,
8571                                NULL, &info, &size);
8572     ok(ret, "CryptDecodeObjectEx failed with %d\n", GetLastError());
8573 
8574     ok(!strcmp(info->SignatureAlgorithm.pszObjId, szOID_ECDSA_SHA256),
8575        "Expected 1.2.840.10045.4.3.2, got %s\n", info->SignatureAlgorithm.pszObjId);
8576     ok(!info->SignatureAlgorithm.Parameters.cbData,
8577        "Expected no parameter data, got %d bytes\n", info->SignatureAlgorithm.Parameters.cbData);
8578     ok(!info->SignatureAlgorithm.Parameters.pbData,
8579        "Expected no parameter data, got %p pointer\n", info->SignatureAlgorithm.Parameters.pbData);
8580 
8581     ok(info->Signature.cbData == sizeof(ecdsaSig),
8582        "Expected %d bytes, got %d\n", (int)sizeof(ecdsaSig), info->Signature.cbData);
8583     ok(info->Signature.pbData != NULL, "Got NULL pointer\n");
8584     ok(!info->Signature.cUnusedBits, "Expected no unused bytes, got %d\n", info->Signature.cUnusedBits);
8585     for (i = 0; i < info->Signature.cbData; i++)
8586     {
8587         ok(ecdsaSig[i] == info->Signature.pbData[i], "Expected %02x, got %02x at offset %d\n",
8588            ecdsaSig[i], info->Signature.pbData[i], i);
8589     }
8590 
8591     ecc_sig = NULL;
8592     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_ECC_SIGNATURE, info->Signature.pbData,
8593                                info->Signature.cbData, decode_flags, NULL, &ecc_sig, &size);
8594     ok(ret, "CryptDecodeObjectEx failed with %d\n", GetLastError());
8595     if (ret)
8596     {
8597         ok(ecc_sig->r.cbData == 32, "Expected 32 bytes, got %d\n", ecc_sig->r.cbData);
8598         ok(ecc_sig->r.pbData != NULL, "Got NULL pointer\n");
8599         ok(ecc_sig->s.cbData == 32, "Expected 32 bytes, got %d\n", ecc_sig->s.cbData);
8600         ok(ecc_sig->s.pbData != NULL, "Got NULL pointer\n");
8601         for (i = 0; i < ecc_sig->r.cbData; i++)
8602         {
8603             ok(ecdsaSig[4+32-i] == ecc_sig->r.pbData[i], "Expected %02x, got %02x at offset %d\n",
8604                ecdsaSig[4+32-i], ecc_sig->r.pbData[i], i);
8605         }
8606         for (i = 0; i < ecc_sig->s.cbData; i++)
8607         {
8608             ok(ecdsaSig[4+35+32-i] == ecc_sig->s.pbData[i], "Expected %02x, got %02x at offset %d\n",
8609                ecdsaSig[4+35+32-i], ecc_sig->s.pbData[i], i);
8610         }
8611         LocalFree(ecc_sig);
8612     }
8613 
8614     LocalFree(info);
8615 
8616     info = NULL;
8617     decode_flags &= ~CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG;
8618     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT, eccCert, sizeof(eccCert), decode_flags,
8619                                NULL, &info, &size);
8620     ok(ret, "CryptDecodeObjectEx failed with %d\n", GetLastError());
8621 
8622     ok(info->Signature.cbData == sizeof(ecdsaSig),
8623        "Expected %d bytes, got %d\n", (int)sizeof(ecdsaSig), info->Signature.cbData);
8624     ok(info->Signature.pbData != NULL, "Got NULL pointer\n");
8625     ok(!info->Signature.cUnusedBits, "Expected no unused bytes, got %d\n", info->Signature.cUnusedBits);
8626     for (i = 0; i < info->Signature.cbData; i++)
8627     {
8628         ok(ecdsaSig[sizeof(ecdsaSig)-i-1] == info->Signature.pbData[i], "Expected %02x, got %02x at offset %d\n",
8629            ecdsaSig[sizeof(ecdsaSig)-i-1], info->Signature.pbData[i], i);
8630     }
8631 
8632     LocalFree(info);
8633 
8634     pubkey = NULL;
8635     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, eccPubKey, sizeof(eccPubKey),
8636                                decode_flags, NULL, &pubkey, &size);
8637     ok(ret, "CryptDecodeObjectEx failed with %d\n", GetLastError());
8638 
8639     ok(!strcmp(pubkey->Algorithm.pszObjId, szOID_ECC_PUBLIC_KEY),
8640        "Expected 1.2.840.10045.2.1, got %s\n", pubkey->Algorithm.pszObjId);
8641     ok(pubkey->Algorithm.Parameters.cbData == 10,
8642        "Expected 10 bytes parameters, got %d bytes\n", pubkey->Algorithm.Parameters.cbData);
8643     ok(pubkey->Algorithm.Parameters.pbData != NULL,
8644        "Expected pointer to parameters, got NULL\n");
8645 
8646     ecc_curve = NULL;
8647     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_OBJECT_IDENTIFIER, pubkey->Algorithm.Parameters.pbData,
8648                                pubkey->Algorithm.Parameters.cbData, decode_flags, NULL, &ecc_curve, &size);
8649     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND /* < Vista */),
8650        "CryptDecodeObjectEx failed with %d\n", GetLastError());
8651     if (ret)
8652     {
8653         ok(!strcmp(*ecc_curve, szOID_ECC_CURVE_P256), "Expected 1.2.840.10045.3.1.7, got %s\n", *ecc_curve);
8654         LocalFree(ecc_curve);
8655     }
8656 
8657     ecc_curve = NULL;
8658     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, szOID_ECC_PUBLIC_KEY, pubkey->Algorithm.Parameters.pbData,
8659                                pubkey->Algorithm.Parameters.cbData, decode_flags, NULL, &ecc_curve, &size);
8660     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND /* < Vista */),
8661        "CryptDecodeObjectEx failed with %d\n", GetLastError());
8662     if (ret)
8663     {
8664         ok(!strcmp(*ecc_curve, szOID_ECC_CURVE_P256), "Expected 1.2.840.10045.3.1.7, got %s\n", *ecc_curve);
8665         LocalFree(ecc_curve);
8666     }
8667 
8668     ok(pubkey->PublicKey.cbData == 65, "Expected 32 bytes parameters, got %d bytes\n", pubkey->PublicKey.cbData);
8669     ok(pubkey->PublicKey.pbData != NULL, "Expected pointer to parameters, got NULL\n");
8670     for (i = 0; i < pubkey->PublicKey.cbData; i++)
8671     {
8672         ok(eccPubKey[26+i] == pubkey->PublicKey.pbData[i], "Expected %02x, got %02x at offset %d\n",
8673            eccPubKey[26+i], pubkey->PublicKey.pbData[i], i);
8674     }
8675 
8676     LocalFree(pubkey);
8677 }
8678 
8679 START_TEST(encode)
8680 {
8681     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
8682      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
8683     HMODULE hCrypt32;
8684     DWORD i;
8685 
8686     hCrypt32 = GetModuleHandleA("crypt32.dll");
8687     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
8688     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
8689     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
8690     {
8691         win_skip("CryptDecodeObjectEx() is not available\n");
8692         return;
8693     }
8694 
8695     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
8696     {
8697         test_encodeInt(encodings[i]);
8698         test_decodeInt(encodings[i]);
8699         test_encodeEnumerated(encodings[i]);
8700         test_decodeEnumerated(encodings[i]);
8701         test_encodeFiletime(encodings[i]);
8702         test_decodeFiletime(encodings[i]);
8703         test_encodeName(encodings[i]);
8704         test_decodeName(encodings[i]);
8705         test_encodeUnicodeName(encodings[i]);
8706         test_decodeUnicodeName(encodings[i]);
8707         test_encodeNameValue(encodings[i]);
8708         test_decodeNameValue(encodings[i]);
8709         test_encodeUnicodeNameValue(encodings[i]);
8710         test_decodeUnicodeNameValue(encodings[i]);
8711         test_encodeAltName(encodings[i]);
8712         test_decodeAltName(encodings[i]);
8713         test_encodeOctets(encodings[i]);
8714         test_decodeOctets(encodings[i]);
8715         test_encodeBits(encodings[i]);
8716         test_decodeBits(encodings[i]);
8717         test_encodeBasicConstraints(encodings[i]);
8718         test_decodeBasicConstraints(encodings[i]);
8719         test_encodeRsaPublicKey(encodings[i]);
8720         test_decodeRsaPublicKey(encodings[i]);
8721         test_encodeSequenceOfAny(encodings[i]);
8722         test_decodeSequenceOfAny(encodings[i]);
8723         test_encodeExtensions(encodings[i]);
8724         test_decodeExtensions(encodings[i]);
8725         test_encodePublicKeyInfo(encodings[i]);
8726         test_decodePublicKeyInfo(encodings[i]);
8727         test_encodeCertToBeSigned(encodings[i]);
8728         test_decodeCertToBeSigned(encodings[i]);
8729         test_encodeCert(encodings[i]);
8730         test_decodeCert(encodings[i]);
8731         test_encodeCRLDistPoints(encodings[i]);
8732         test_decodeCRLDistPoints(encodings[i]);
8733         test_encodeCRLIssuingDistPoint(encodings[i]);
8734         test_decodeCRLIssuingDistPoint(encodings[i]);
8735         test_encodeCRLToBeSigned(encodings[i]);
8736         test_decodeCRLToBeSigned(encodings[i]);
8737         test_encodeEnhancedKeyUsage(encodings[i]);
8738         test_decodeEnhancedKeyUsage(encodings[i]);
8739         test_encodeAuthorityKeyId(encodings[i]);
8740         test_decodeAuthorityKeyId(encodings[i]);
8741         test_encodeAuthorityKeyId2(encodings[i]);
8742         test_decodeAuthorityKeyId2(encodings[i]);
8743         test_encodeAuthorityInfoAccess(encodings[i]);
8744         test_decodeAuthorityInfoAccess(encodings[i]);
8745         test_encodeCTL(encodings[i]);
8746         test_decodeCTL(encodings[i]);
8747         test_encodePKCSContentInfo(encodings[i]);
8748         test_decodePKCSContentInfo(encodings[i]);
8749         test_encodePKCSAttribute(encodings[i]);
8750         test_decodePKCSAttribute(encodings[i]);
8751         test_encodePKCSAttributes(encodings[i]);
8752         test_decodePKCSAttributes(encodings[i]);
8753         test_encodePKCSSMimeCapabilities(encodings[i]);
8754         test_decodePKCSSMimeCapabilities(encodings[i]);
8755         test_encodePKCSSignerInfo(encodings[i]);
8756         test_decodePKCSSignerInfo(encodings[i]);
8757         test_encodeCMSSignerInfo(encodings[i]);
8758         test_decodeCMSSignerInfo(encodings[i]);
8759         test_encodeNameConstraints(encodings[i]);
8760         test_decodeNameConstraints(encodings[i]);
8761         test_encodePolicyQualifierUserNotice(encodings[i]);
8762         test_decodePolicyQualifierUserNotice(encodings[i]);
8763         test_encodeCertPolicies(encodings[i]);
8764         test_decodeCertPolicies(encodings[i]);
8765         test_encodeCertPolicyMappings(encodings[i]);
8766         test_decodeCertPolicyMappings(encodings[i]);
8767         test_encodeCertPolicyConstraints(encodings[i]);
8768         test_decodeCertPolicyConstraints(encodings[i]);
8769         test_decodeRsaPrivateKey(encodings[i]);
8770     }
8771     testPortPublicKeyInfo();
8772     testECDSACert();
8773 }
8774