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 
21 #include "precomp.h"
22 
23 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
24 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
25 
26 struct encodedInt
27 {
28     int val;
29     const BYTE *encoded;
30 };
31 
32 static const BYTE bin1[] = {0x02,0x01,0x01};
33 static const BYTE bin2[] = {0x02,0x01,0x7f};
34 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
35 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
36 static const BYTE bin5[] = {0x02,0x01,0x80};
37 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
38 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
39 
40 static const struct encodedInt ints[] = {
41  { 1,          bin1 },
42  { 127,        bin2 },
43  { 128,        bin3 },
44  { 256,        bin4 },
45  { -128,       bin5 },
46  { -129,       bin6 },
47  { 0xbaddf00d, bin7 },
48 };
49 
50 struct encodedBigInt
51 {
52     const BYTE *val;
53     const BYTE *encoded;
54     const BYTE *decoded;
55 };
56 
57 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
58 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
59 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
60 
61 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
62 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
63 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
64 
65 static const struct encodedBigInt bigInts[] = {
66  { bin8, bin9, bin10 },
67  { bin11, bin12, bin13 },
68 };
69 
70 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
71 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
72 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
73 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
74 
75 /* Decoded is the same as original, so don't bother storing a separate copy */
76 static const struct encodedBigInt bigUInts[] = {
77  { bin14, bin15, NULL },
78  { bin16, bin17, NULL },
79 };
80 
81 static void test_encodeInt(DWORD dwEncoding)
82 {
83     DWORD bufSize = 0;
84     int i;
85     BOOL ret;
86     CRYPT_INTEGER_BLOB blob;
87     BYTE *buf = NULL;
88 
89     /* CryptEncodeObjectEx with NULL bufSize crashes..
90     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
91      NULL);
92      */
93     /* check bogus encoding */
94     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
95      &bufSize);
96     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
97      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
98     if (0)
99     {
100         /* check with NULL integer buffer.  Windows XP incorrectly returns an
101          * NTSTATUS (crashes on win9x).
102          */
103         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
104          &bufSize);
105         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
106          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
107     }
108     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
109     {
110         /* encode as normal integer */
111         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
112          NULL, NULL, &bufSize);
113         ok(ret, "Expected success, got %d\n", GetLastError());
114         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
115          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
116         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
117         if (ret)
118         {
119             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
120              buf[0]);
121             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
122              buf[1], ints[i].encoded[1]);
123             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
124              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
125             LocalFree(buf);
126         }
127         /* encode as multibyte integer */
128         blob.cbData = sizeof(ints[i].val);
129         blob.pbData = (BYTE *)&ints[i].val;
130         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
131          0, NULL, NULL, &bufSize);
132         ok(ret, "Expected success, got %d\n", GetLastError());
133         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
134          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
135         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
136         if (ret)
137         {
138             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
139              buf[0]);
140             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
141              buf[1], ints[i].encoded[1]);
142             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
143              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
144             LocalFree(buf);
145         }
146     }
147     /* encode a couple bigger ints, just to show it's little-endian and leading
148      * sign bytes are dropped
149      */
150     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
151     {
152         blob.cbData = strlen((const char*)bigInts[i].val);
153         blob.pbData = (BYTE *)bigInts[i].val;
154         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
155          0, NULL, NULL, &bufSize);
156         ok(ret, "Expected success, got %d\n", GetLastError());
157         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
158          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
159         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
160         if (ret)
161         {
162             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
163              buf[0]);
164             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
165              buf[1], bigInts[i].encoded[1]);
166             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
167              bigInts[i].encoded[1] + 1),
168              "Encoded value didn't match expected\n");
169             LocalFree(buf);
170         }
171     }
172     /* and, encode some uints */
173     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
174     {
175         blob.cbData = strlen((const char*)bigUInts[i].val);
176         blob.pbData = (BYTE*)bigUInts[i].val;
177         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
178          0, NULL, NULL, &bufSize);
179         ok(ret, "Expected success, got %d\n", GetLastError());
180         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
181          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
182         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
183         if (ret)
184         {
185             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
186              buf[0]);
187             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
188              buf[1], bigUInts[i].encoded[1]);
189             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
190              bigUInts[i].encoded[1] + 1),
191              "Encoded value didn't match expected\n");
192             LocalFree(buf);
193         }
194     }
195 }
196 
197 static void test_decodeInt(DWORD dwEncoding)
198 {
199     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
200     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
201     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
202     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
203     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
204     BYTE *buf = NULL;
205     DWORD bufSize = 0;
206     int i;
207     BOOL ret;
208 
209     /* CryptDecodeObjectEx with NULL bufSize crashes..
210     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
211      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
212      */
213     /* check bogus encoding */
214     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
215      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
216     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
217      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
218     /* check with NULL integer buffer */
219     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
220      &bufSize);
221     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
222      GetLastError() == OSS_BAD_ARG /* Win9x */),
223      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
224     /* check with a valid, but too large, integer */
225     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
226      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
227     ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
228      broken(ret) /* Win9x */,
229      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
230     /* check with a DER-encoded string */
231     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
232      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
233     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
234      GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
235      "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
236      GetLastError());
237     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
238     {
239         /* When the output buffer is NULL, this always succeeds */
240         SetLastError(0xdeadbeef);
241         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
243          &bufSize);
244         ok(ret && GetLastError() == NOERROR,
245          "Expected success and NOERROR, got %d\n", GetLastError());
246         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
247          ints[i].encoded, ints[i].encoded[1] + 2,
248          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
249         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
250         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
251         ok(buf != NULL, "Expected allocated buffer\n");
252         if (ret)
253         {
254             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
255              ints[i].val, *(int *)buf);
256             LocalFree(buf);
257         }
258     }
259     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
260     {
261         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
262          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
263          &bufSize);
264         ok(ret && GetLastError() == NOERROR,
265          "Expected success and NOERROR, got %d\n", GetLastError());
266         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
267          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
268          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
269         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
270         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
271         ok(buf != NULL, "Expected allocated buffer\n");
272         if (ret)
273         {
274             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
275 
276             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
277              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
278              blob->cbData);
279             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
280              "Unexpected value\n");
281             LocalFree(buf);
282         }
283     }
284     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
285     {
286         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
287          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
288          &bufSize);
289         ok(ret && GetLastError() == NOERROR,
290          "Expected success and NOERROR, got %d\n", GetLastError());
291         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
292          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
293          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
294         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
295         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
296         ok(buf != NULL, "Expected allocated buffer\n");
297         if (ret)
298         {
299             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
300 
301             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
302              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
303              blob->cbData);
304             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
305              "Unexpected value\n");
306             LocalFree(buf);
307         }
308     }
309     /* Decode the value 1 with long-form length */
310     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
311      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
312     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
313     if (ret)
314     {
315         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
316         LocalFree(buf);
317     }
318     /* check with extra bytes at the end */
319     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
320      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
321     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
322     if (ret)
323     {
324         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
325         LocalFree(buf);
326     }
327     /* Try to decode some bogus large items */
328     /* The buffer size is smaller than the encoded length, so this should fail
329      * with CRYPT_E_ASN1_EOD if it's being decoded.
330      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
331      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
332      * So this test unfortunately isn't useful.
333     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
334      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
335     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
336      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
337      */
338     /* This will try to decode the buffer and overflow it, check that it's
339      * caught.
340      */
341     if (0)
342     {
343     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
344     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
345      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
346     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
347      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
348     }
349 }
350 
351 static const BYTE bin18[] = {0x0a,0x01,0x01};
352 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
353 
354 /* These are always encoded unsigned, and aren't constrained to be any
355  * particular value
356  */
357 static const struct encodedInt enums[] = {
358  { 1,    bin18 },
359  { -128, bin19 },
360 };
361 
362 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
363  * X509_ENUMERATED.
364  */
365 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
366  szOID_CRL_REASON_CODE };
367 
368 static void test_encodeEnumerated(DWORD dwEncoding)
369 {
370     DWORD i, j;
371 
372     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
373     {
374         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
375         {
376             BOOL ret;
377             BYTE *buf = NULL;
378             DWORD bufSize = 0;
379 
380             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
381              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
382              &bufSize);
383             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
384             if (ret)
385             {
386                 ok(buf[0] == 0xa,
387                  "Got unexpected type %d for enumerated (expected 0xa)\n",
388                  buf[0]);
389                 ok(buf[1] == enums[j].encoded[1],
390                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
391                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
392                  enums[j].encoded[1] + 1),
393                  "Encoded value of 0x%08x didn't match expected\n",
394                  enums[j].val);
395                 LocalFree(buf);
396             }
397         }
398     }
399 }
400 
401 static void test_decodeEnumerated(DWORD dwEncoding)
402 {
403     DWORD i, j;
404 
405     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
406     {
407         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
408         {
409             BOOL ret;
410             DWORD bufSize = sizeof(int);
411             int val;
412 
413             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
414              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
415              &val, &bufSize);
416             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
417             ok(bufSize == sizeof(int),
418              "Got unexpected size %d for enumerated\n", bufSize);
419             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
420              val, enums[j].val);
421         }
422     }
423 }
424 
425 struct encodedFiletime
426 {
427     SYSTEMTIME sysTime;
428     const BYTE *encodedTime;
429 };
430 
431 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
432  const struct encodedFiletime *time)
433 {
434     FILETIME ft = { 0 };
435     BYTE *buf = NULL;
436     DWORD bufSize = 0;
437     BOOL ret;
438 
439     ret = SystemTimeToFileTime(&time->sysTime, &ft);
440     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
441     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
442      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
443     /* years other than 1950-2050 are not allowed for encodings other than
444      * X509_CHOICE_OF_TIME.
445      */
446     if (structType == X509_CHOICE_OF_TIME ||
447      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
448     {
449         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
450          GetLastError());
451         ok(buf != NULL, "Expected an allocated buffer\n");
452         if (ret)
453         {
454             ok(buf[0] == time->encodedTime[0],
455              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
456              buf[0]);
457             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
458              time->encodedTime[1], bufSize);
459             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
460              "Got unexpected value for time encoding\n");
461             LocalFree(buf);
462         }
463     }
464     else
465         ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
466          broken(GetLastError() == ERROR_SUCCESS),
467          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
468 }
469 
470 static const char *printSystemTime(const SYSTEMTIME *st)
471 {
472     static char buf[64];
473 
474     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
475      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
476     return buf;
477 }
478 
479 static const char *printFileTime(const FILETIME *ft)
480 {
481     static char buf[64];
482     SYSTEMTIME st;
483 
484     FileTimeToSystemTime(ft, &st);
485     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
486      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
487     return buf;
488 }
489 
490 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
491 {
492     SYSTEMTIME st;
493 
494     FileTimeToSystemTime(got, &st);
495     ok((expected->wYear == st.wYear &&
496      expected->wMonth == st.wMonth &&
497      expected->wDay == st.wDay &&
498      expected->wHour == st.wHour &&
499      expected->wMinute == st.wMinute &&
500      expected->wSecond == st.wSecond &&
501      abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
502      /* Some Windows systems only seem to be accurate in their time decoding to
503       * within about an hour.
504       */
505      broken(expected->wYear == st.wYear &&
506      expected->wMonth == st.wMonth &&
507      expected->wDay == st.wDay &&
508      abs(expected->wHour - st.wHour) <= 1),
509      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
510      printSystemTime(expected), printFileTime(got));
511 }
512 
513 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
514  const struct encodedFiletime *time)
515 {
516     FILETIME ft = { 0 };
517     DWORD size = sizeof(ft);
518     BOOL ret;
519 
520     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
521      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
522     /* years other than 1950-2050 are not allowed for encodings other than
523      * X509_CHOICE_OF_TIME.
524      */
525     if (structType == X509_CHOICE_OF_TIME ||
526      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
527     {
528         ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
529          "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
530          GetLastError());
531         if (ret)
532             compareTime(&time->sysTime, &ft);
533     }
534     else
535         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
536          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
537          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
538          GetLastError());
539 }
540 
541 static const BYTE bin20[] = {
542     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
543 static const BYTE bin21[] = {
544     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
545 static const BYTE bin22[] = {
546     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
547 
548 static const struct encodedFiletime times[] = {
549  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
550  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
551  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
552 };
553 
554 static void test_encodeFiletime(DWORD dwEncoding)
555 {
556     DWORD i;
557 
558     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
559     {
560         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
561         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
562         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
563     }
564 }
565 
566 static const BYTE bin23[] = {
567     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
568 static const BYTE bin24[] = {
569     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
570 static const BYTE bin25[] = {
571     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
572 static const BYTE bin26[] = {
573     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
574 static const BYTE bin27[] = {
575     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
576 static const BYTE bin28[] = {
577     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
578 static const BYTE bin29[] = {
579     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
580 static const BYTE bin30[] = {
581     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
582 static const BYTE bin31[] = {
583     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
584 static const BYTE bin32[] = {
585     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
586 static const BYTE bin33[] = {
587     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
588 static const BYTE bin34[] = {
589     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
590 static const BYTE bin35[] = {
591     0x17,0x08, '4','5','0','6','0','6','1','6'};
592 static const BYTE bin36[] = {
593     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
594 static const BYTE bin37[] = {
595     0x18,0x04, '2','1','4','5'};
596 static const BYTE bin38[] = {
597     0x18,0x08, '2','1','4','5','0','6','0','6'};
598 
599 static void test_decodeFiletime(DWORD dwEncoding)
600 {
601     static const struct encodedFiletime otherTimes[] = {
602      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
603      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
604      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
605      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
606      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
607      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
608      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
609      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
610      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
611      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
612      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
613      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
614     };
615     /* An oddball case that succeeds in Windows, but doesn't seem correct
616      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
617      */
618     static const unsigned char *bogusTimes[] = {
619      /* oddly, this succeeds on Windows, with year 2765
620      "\x18" "\x0f" "21r50606161000Z",
621       */
622      bin35,
623      bin36,
624      bin37,
625      bin38,
626     };
627     DWORD i, size;
628     FILETIME ft1 = { 0 }, ft2 = { 0 };
629     BOOL ret;
630 
631     /* Check bogus length with non-NULL buffer */
632     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
633     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
634     size = 1;
635     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
636      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
637     ok(!ret && GetLastError() == ERROR_MORE_DATA,
638      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
639     /* Normal tests */
640     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
641     {
642         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
643         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
644         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
645     }
646     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
647     {
648         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
649         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
650         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
651     }
652     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
653     {
654         size = sizeof(ft1);
655         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
656          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
657         ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
658                      GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
659            broken(ret), /* Win9x and NT4 for bin38 */
660          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
661          GetLastError());
662     }
663 }
664 
665 static const char commonName[] = "Juan Lang";
666 static const char surName[] = "Lang";
667 
668 static const BYTE emptySequence[] = { 0x30, 0 };
669 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
670 static const BYTE twoRDNs[] = {
671     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
672     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
673     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
674 static const BYTE encodedTwoRDNs[] = {
675 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
676 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
677 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
678 0x6e,0x67,0x00,
679 };
680 
681 static const BYTE us[] = { 0x55, 0x53 };
682 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
683  0x74, 0x61 };
684 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
685  0x6f, 0x6c, 0x69, 0x73 };
686 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
687  0x76, 0x65, 0x72, 0x73 };
688 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
689  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
690 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
691  0x73, 0x74 };
692 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
693  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
694 
695 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
696 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
697 
698 static CHAR oid_us[]            = "2.5.4.6",
699             oid_minnesota[]     = "2.5.4.8",
700             oid_minneapolis[]   = "2.5.4.7",
701             oid_codeweavers[]   = "2.5.4.10",
702             oid_wine[]          = "2.5.4.11",
703             oid_localhostAttr[] = "2.5.4.3",
704             oid_aric[]          = "1.2.840.113549.1.9.1";
705 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
706                                     { RDNA(minnesota) },
707                                     { RDNA(minneapolis) },
708                                     { RDNA(codeweavers) },
709                                     { RDNA(wine) },
710                                     { RDNA(localhostAttr) },
711                                     { RDNIA5(aric) } };
712 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
713                                            { RDNA(localhostAttr) },
714                                            { RDNA(minnesota) },
715                                            { RDNA(minneapolis) },
716                                            { RDNA(codeweavers) },
717                                            { RDNA(wine) },
718                                            { RDNIA5(aric) } };
719 
720 #undef RDNIA5
721 #undef RDNA
722 
723 static const BYTE encodedRDNAttrs[] = {
724 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
725 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
726 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
727 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
728 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
729 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
730 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
731 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
732 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
733 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
734 };
735 
736 static void test_encodeName(DWORD dwEncoding)
737 {
738     CERT_RDN_ATTR attrs[2];
739     CERT_RDN rdn;
740     CERT_NAME_INFO info;
741     static CHAR oid_common_name[] = szOID_COMMON_NAME,
742                 oid_sur_name[]    = szOID_SUR_NAME;
743     BYTE *buf = NULL;
744     DWORD size = 0;
745     BOOL ret;
746 
747     if (0)
748     {
749         /* Test with NULL pvStructInfo (crashes on win9x) */
750         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
751          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
752         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
753          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
754     }
755     /* Test with empty CERT_NAME_INFO */
756     info.cRDN = 0;
757     info.rgRDN = NULL;
758     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
759      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
760     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
761     if (ret)
762     {
763         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
764          "Got unexpected encoding for empty name\n");
765         LocalFree(buf);
766     }
767     if (0)
768     {
769         /* Test with bogus CERT_RDN (crashes on win9x) */
770         info.cRDN = 1;
771         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
772          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
773         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
774          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
775     }
776     /* Test with empty CERT_RDN */
777     rdn.cRDNAttr = 0;
778     rdn.rgRDNAttr = NULL;
779     info.cRDN = 1;
780     info.rgRDN = &rdn;
781     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
782      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
783     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
784     if (ret)
785     {
786         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
787          "Got unexpected encoding for empty RDN array\n");
788         LocalFree(buf);
789     }
790     if (0)
791     {
792         /* Test with bogus attr array (crashes on win9x) */
793         rdn.cRDNAttr = 1;
794         rdn.rgRDNAttr = NULL;
795         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
796          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
797         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
798          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
799     }
800     /* oddly, a bogus OID is accepted by Windows XP; not testing.
801     attrs[0].pszObjId = "bogus";
802     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
803     attrs[0].Value.cbData = sizeof(commonName);
804     attrs[0].Value.pbData = commonName;
805     rdn.cRDNAttr = 1;
806     rdn.rgRDNAttr = attrs;
807     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
808      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
809     ok(!ret, "Expected failure, got success\n");
810      */
811     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
812      * the encoded attributes to be swapped.
813      */
814     attrs[0].pszObjId = oid_common_name;
815     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
816     attrs[0].Value.cbData = sizeof(commonName);
817     attrs[0].Value.pbData = (BYTE *)commonName;
818     attrs[1].pszObjId = oid_sur_name;
819     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
820     attrs[1].Value.cbData = sizeof(surName);
821     attrs[1].Value.pbData = (BYTE *)surName;
822     rdn.cRDNAttr = 2;
823     rdn.rgRDNAttr = attrs;
824     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
825      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
826     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
827     if (ret)
828     {
829         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
830          "Got unexpected encoding for two RDN array\n");
831         LocalFree(buf);
832     }
833     /* A name can be "encoded" with previously encoded RDN attrs. */
834     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
835     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
836     attrs[0].Value.cbData = sizeof(twoRDNs);
837     rdn.cRDNAttr = 1;
838     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
839      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
840     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
841     if (ret)
842     {
843         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
844         ok(!memcmp(buf, encodedTwoRDNs, size),
845          "Unexpected value for re-encoded two RDN array\n");
846         LocalFree(buf);
847     }
848     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
849     rdn.cRDNAttr = 1;
850     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
851     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
852      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
853     ok(!ret && GetLastError() == E_INVALIDARG,
854      "Expected E_INVALIDARG, got %08x\n", GetLastError());
855     /* Test a more complex name */
856     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
857     rdn.rgRDNAttr = rdnAttrs;
858     info.cRDN = 1;
859     info.rgRDN = &rdn;
860     buf = NULL;
861     size = 0;
862     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
863      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
864     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
865     if (ret)
866     {
867         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
868         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
869         LocalFree(buf);
870     }
871 }
872 
873 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
874 static WCHAR surNameW[] = { 'L','a','n','g',0 };
875 
876 static const BYTE twoRDNsNoNull[] = {
877  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
878  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
879  0x20,0x4c,0x61,0x6e,0x67 };
880 static const BYTE anyType[] = {
881  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
882  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
883  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
884  0x61,0x4c,0x67,0x6e };
885 
886 static void test_encodeUnicodeName(DWORD dwEncoding)
887 {
888     CERT_RDN_ATTR attrs[2];
889     CERT_RDN rdn;
890     CERT_NAME_INFO info;
891     static CHAR oid_common_name[] = szOID_COMMON_NAME,
892                 oid_sur_name[]    = szOID_SUR_NAME;
893     BYTE *buf = NULL;
894     DWORD size = 0;
895     BOOL ret;
896 
897     if (0)
898     {
899         /* Test with NULL pvStructInfo (crashes on win9x) */
900         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
901          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
902         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
903          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
904     }
905     /* Test with empty CERT_NAME_INFO */
906     info.cRDN = 0;
907     info.rgRDN = NULL;
908     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
909      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
910     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
911     if (ret)
912     {
913         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
914          "Got unexpected encoding for empty name\n");
915         LocalFree(buf);
916     }
917     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
918      * encoding (the NULL).
919      */
920     attrs[0].pszObjId = oid_common_name;
921     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
922     attrs[0].Value.cbData = sizeof(commonNameW);
923     attrs[0].Value.pbData = (BYTE *)commonNameW;
924     rdn.cRDNAttr = 1;
925     rdn.rgRDNAttr = attrs;
926     info.cRDN = 1;
927     info.rgRDN = &rdn;
928     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
929      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
930     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
931      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
932     ok(size == 9, "Unexpected error index %08x\n", size);
933     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
934      * forces the order of the encoded attributes to be swapped.
935      */
936     attrs[0].pszObjId = oid_common_name;
937     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
938     attrs[0].Value.cbData = 0;
939     attrs[0].Value.pbData = (BYTE *)commonNameW;
940     attrs[1].pszObjId = oid_sur_name;
941     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
942     attrs[1].Value.cbData = 0;
943     attrs[1].Value.pbData = (BYTE *)surNameW;
944     rdn.cRDNAttr = 2;
945     rdn.rgRDNAttr = attrs;
946     info.cRDN = 1;
947     info.rgRDN = &rdn;
948     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
949      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
950     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
951     if (ret)
952     {
953         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
954          "Got unexpected encoding for two RDN array\n");
955         LocalFree(buf);
956     }
957     /* A name can be "encoded" with previously encoded RDN attrs. */
958     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
959     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
960     attrs[0].Value.cbData = sizeof(twoRDNs);
961     rdn.cRDNAttr = 1;
962     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
963      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
964     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
965     if (ret)
966     {
967         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
968         ok(!memcmp(buf, encodedTwoRDNs, size),
969          "Unexpected value for re-encoded two RDN array\n");
970         LocalFree(buf);
971     }
972     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
973     rdn.cRDNAttr = 1;
974     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
975     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
976      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
977     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
978     if (ret)
979     {
980         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
981         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
982         LocalFree(buf);
983     }
984 }
985 
986 static void compareNameValues(const CERT_NAME_VALUE *expected,
987  const CERT_NAME_VALUE *got)
988 {
989     if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
990         got->dwValueType == CERT_RDN_ENCODED_BLOB)
991     {
992         win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
993         return;
994     }
995 
996     ok(got->dwValueType == expected->dwValueType,
997      "Expected string type %d, got %d\n", expected->dwValueType,
998      got->dwValueType);
999     ok(got->Value.cbData == expected->Value.cbData ||
1000      got->Value.cbData == expected->Value.cbData - sizeof(WCHAR) /* Win8 */,
1001      "String type %d: unexpected data size, got %d, expected %d\n",
1002      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1003     if (got->Value.cbData && got->Value.pbData)
1004         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1005          min(got->Value.cbData, expected->Value.cbData)),
1006          "String type %d: unexpected value\n", expected->dwValueType);
1007 }
1008 
1009 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1010  const CERT_RDN_ATTR *got)
1011 {
1012     if (expected->pszObjId && strlen(expected->pszObjId))
1013     {
1014         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1015          expected->pszObjId);
1016         if (got->pszObjId)
1017         {
1018             ok(!strcmp(got->pszObjId, expected->pszObjId),
1019              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1020              expected->pszObjId);
1021         }
1022     }
1023     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1024      (const CERT_NAME_VALUE *)&got->dwValueType);
1025 }
1026 
1027 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1028 {
1029     ok(got->cRDNAttr == expected->cRDNAttr,
1030      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1031     if (got->cRDNAttr)
1032     {
1033         DWORD i;
1034 
1035         for (i = 0; i < got->cRDNAttr; i++)
1036             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1037     }
1038 }
1039 
1040 static void compareNames(const CERT_NAME_INFO *expected,
1041  const CERT_NAME_INFO *got)
1042 {
1043     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1044      expected->cRDN, got->cRDN);
1045     if (got->cRDN)
1046     {
1047         DWORD i;
1048 
1049         for (i = 0; i < got->cRDN; i++)
1050             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1051     }
1052 }
1053 
1054 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1055 static const BYTE twoRDNsExtraBytes[] = {
1056     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1057     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1058     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1059 
1060 static void test_decodeName(DWORD dwEncoding)
1061 {
1062     BYTE *buf = NULL;
1063     DWORD bufSize = 0;
1064     BOOL ret;
1065     CERT_RDN rdn;
1066     CERT_NAME_INFO info = { 1, &rdn };
1067 
1068     /* test empty name */
1069     bufSize = 0;
1070     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1071      emptySequence[1] + 2,
1072      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1073      &buf, &bufSize);
1074     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1075     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1076      * decoder works the same way, so only test the count.
1077      */
1078     if (ret)
1079     {
1080         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1081         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1082          "Expected 0 RDNs in empty info, got %d\n",
1083          ((CERT_NAME_INFO *)buf)->cRDN);
1084         LocalFree(buf);
1085     }
1086     /* test empty name with indefinite-length encoding */
1087     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1088      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1089      &buf, &bufSize);
1090     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1091     if (ret)
1092     {
1093         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1094         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1095          "Expected 0 RDNs in empty info, got %d\n",
1096          ((CERT_NAME_INFO *)buf)->cRDN);
1097         LocalFree(buf);
1098     }
1099     /* test empty RDN */
1100     bufSize = 0;
1101     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1102      emptyRDNs[1] + 2,
1103      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1104      &buf, &bufSize);
1105     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1106     if (ret)
1107     {
1108         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1109 
1110         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1111          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1112          "Got unexpected value for empty RDN\n");
1113         LocalFree(buf);
1114     }
1115     /* test two RDN attrs */
1116     bufSize = 0;
1117     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1118      twoRDNs[1] + 2,
1119      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1120      &buf, &bufSize);
1121     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1122     if (ret)
1123     {
1124         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1125                     oid_common_name[] = szOID_COMMON_NAME;
1126 
1127         CERT_RDN_ATTR attrs[] = {
1128          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1129           (BYTE *)surName } },
1130          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1131           (BYTE *)commonName } },
1132         };
1133 
1134         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1135         rdn.rgRDNAttr = attrs;
1136         compareNames(&info, (CERT_NAME_INFO *)buf);
1137         LocalFree(buf);
1138     }
1139     /* test that two RDN attrs with extra bytes succeeds */
1140     bufSize = 0;
1141     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1142      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1143     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1144     /* And, a slightly more complicated name */
1145     buf = NULL;
1146     bufSize = 0;
1147     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1148      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1149     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1150     if (ret)
1151     {
1152         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1153         rdn.rgRDNAttr = decodedRdnAttrs;
1154         compareNames(&info, (CERT_NAME_INFO *)buf);
1155         LocalFree(buf);
1156     }
1157 }
1158 
1159 static void test_decodeUnicodeName(DWORD dwEncoding)
1160 {
1161     BYTE *buf = NULL;
1162     DWORD bufSize = 0;
1163     BOOL ret;
1164     CERT_RDN rdn;
1165     CERT_NAME_INFO info = { 1, &rdn };
1166 
1167     /* test empty name */
1168     bufSize = 0;
1169     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1170      emptySequence[1] + 2,
1171      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1172      &buf, &bufSize);
1173     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1174     if (ret)
1175     {
1176         ok(bufSize == sizeof(CERT_NAME_INFO),
1177          "Got wrong bufSize %d\n", bufSize);
1178         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1179          "Expected 0 RDNs in empty info, got %d\n",
1180          ((CERT_NAME_INFO *)buf)->cRDN);
1181         LocalFree(buf);
1182     }
1183     /* test empty RDN */
1184     bufSize = 0;
1185     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1186      emptyRDNs[1] + 2,
1187      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1188      &buf, &bufSize);
1189     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1190     if (ret)
1191     {
1192         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1193 
1194         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1195          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1196          "Got unexpected value for empty RDN\n");
1197         LocalFree(buf);
1198     }
1199     /* test two RDN attrs */
1200     bufSize = 0;
1201     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1202      sizeof(twoRDNsNoNull),
1203      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1204      &buf, &bufSize);
1205     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1206     if (ret)
1207     {
1208         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1209                     oid_common_name[] = szOID_COMMON_NAME;
1210 
1211         CERT_RDN_ATTR attrs[] = {
1212          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1213          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1214          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1215          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1216         };
1217 
1218         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1219         rdn.rgRDNAttr = attrs;
1220         compareNames(&info, (CERT_NAME_INFO *)buf);
1221         LocalFree(buf);
1222     }
1223 }
1224 
1225 struct EncodedNameValue
1226 {
1227     CERT_NAME_VALUE value;
1228     const BYTE *encoded;
1229     DWORD encodedSize;
1230 };
1231 
1232 static const char bogusIA5[] = "\x80";
1233 static const char bogusPrintable[] = "~";
1234 static const char bogusNumeric[] = "A";
1235 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1236 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1237 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1238 static BYTE octetCommonNameValue[] = {
1239  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1240 static BYTE numericCommonNameValue[] = {
1241  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1242 static BYTE printableCommonNameValue[] = {
1243  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1244 static BYTE t61CommonNameValue[] = {
1245  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE videotexCommonNameValue[] = {
1247  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE ia5CommonNameValue[] = {
1249  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE graphicCommonNameValue[] = {
1251  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE visibleCommonNameValue[] = {
1253  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE generalCommonNameValue[] = {
1255  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1256 static BYTE bmpCommonNameValue[] = {
1257  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1258  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1259 static BYTE utf8CommonNameValue[] = {
1260  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1261 static char embedded_null[] = "foo\0com";
1262 static BYTE ia5EmbeddedNull[] = {
1263  0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1264 
1265 static struct EncodedNameValue nameValues[] = {
1266  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1267      octetCommonNameValue, sizeof(octetCommonNameValue) },
1268  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1269      numericCommonNameValue, sizeof(numericCommonNameValue) },
1270  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1271      printableCommonNameValue, sizeof(printableCommonNameValue) },
1272  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1273      t61CommonNameValue, sizeof(t61CommonNameValue) },
1274  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1275      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1276  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1277      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1278  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1279      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1280  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1281      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1282  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1283      generalCommonNameValue, sizeof(generalCommonNameValue) },
1284  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1285      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1286  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1287      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1288  /* The following tests succeed under Windows, but really should fail,
1289   * they contain characters that are illegal for the encoding.  I'm
1290   * including them to justify my lazy encoding.
1291   */
1292  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1293      sizeof(bin42) },
1294  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1295      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1296  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1297      bin44, sizeof(bin44) },
1298 };
1299 /* This is kept separate, because the decoding doesn't return to the original
1300  * value.
1301  */
1302 static struct EncodedNameValue embeddedNullNameValue = {
1303  { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1304    ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1305 
1306 static void test_encodeNameValue(DWORD dwEncoding)
1307 {
1308     BYTE *buf = NULL;
1309     DWORD size = 0, i;
1310     BOOL ret;
1311     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1312 
1313     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1314     value.Value.pbData = printableCommonNameValue;
1315     value.Value.cbData = sizeof(printableCommonNameValue);
1316     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1317      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1318     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1319     if (ret)
1320     {
1321         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1322          size);
1323         ok(!memcmp(buf, printableCommonNameValue, size),
1324          "Unexpected encoding\n");
1325         LocalFree(buf);
1326     }
1327     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1328     {
1329         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1330          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1331         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1332          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1333          nameValues[i].value.dwValueType, GetLastError());
1334         if (ret)
1335         {
1336             ok(size == nameValues[i].encodedSize,
1337              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1338             ok(!memcmp(buf, nameValues[i].encoded, size),
1339              "Got unexpected encoding\n");
1340             LocalFree(buf);
1341         }
1342     }
1343     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1344      &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1345     ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1346      "Type %d: CryptEncodeObjectEx failed: %08x\n",
1347      embeddedNullNameValue.value.dwValueType, GetLastError());
1348     if (ret)
1349     {
1350         ok(size == embeddedNullNameValue.encodedSize,
1351          "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1352         ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1353          "Got unexpected encoding\n");
1354         LocalFree(buf);
1355     }
1356 }
1357 
1358 static void test_decodeNameValue(DWORD dwEncoding)
1359 {
1360     int i;
1361     BYTE *buf = NULL;
1362     DWORD bufSize = 0;
1363     BOOL ret;
1364 
1365     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1366     {
1367         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1368          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1369          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1370          &buf, &bufSize);
1371         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1372          nameValues[i].value.dwValueType, GetLastError());
1373         if (ret)
1374         {
1375             compareNameValues(&nameValues[i].value,
1376              (const CERT_NAME_VALUE *)buf);
1377             LocalFree(buf);
1378         }
1379     }
1380     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1381      embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1382      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1383      &buf, &bufSize);
1384     /* Some Windows versions disallow name values with embedded NULLs, so
1385      * either success or failure is acceptable.
1386      */
1387     if (ret)
1388     {
1389         CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1390          { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1391         CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1392          { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1393         const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1394          *expected = NULL;
1395 
1396         /* Some Windows versions decode name values with embedded NULLs,
1397          * others leave them encoded, even with the same version of crypt32.
1398          * Accept either.
1399          */
1400         ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1401          got->dwValueType == CERT_RDN_IA5_STRING,
1402          "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1403          got->dwValueType);
1404         if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1405             expected = &rdnEncodedValue;
1406         else if (got->dwValueType == CERT_RDN_IA5_STRING)
1407             expected = &embeddedNullValue;
1408         if (expected)
1409         {
1410             ok(got->Value.cbData == expected->Value.cbData,
1411              "String type %d: unexpected data size, got %d, expected %d\n",
1412              got->dwValueType, got->Value.cbData, expected->Value.cbData);
1413             if (got->Value.cbData && got->Value.pbData)
1414                 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1415                  min(got->Value.cbData, expected->Value.cbData)),
1416                  "String type %d: unexpected value\n", expected->dwValueType);
1417         }
1418         LocalFree(buf);
1419     }
1420 }
1421 
1422 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1423 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1424 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1425  'h','q','.','o','r','g',0 };
1426 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1427  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1428  0x6f, 0x72, 0x67 };
1429 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1430  0x575b, 0 };
1431 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1432 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1433  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1434 static const BYTE localhost[] = { 127, 0, 0, 1 };
1435 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1436  0x01 };
1437 static const unsigned char encodedCommonName[] = {
1438     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1439 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1440 static const BYTE encodedDirectoryName[] = {
1441 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1442 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1443 
1444 static void test_encodeAltName(DWORD dwEncoding)
1445 {
1446     CERT_ALT_NAME_INFO info = { 0 };
1447     CERT_ALT_NAME_ENTRY entry = { 0 };
1448     BYTE *buf = NULL;
1449     DWORD size = 0;
1450     BOOL ret;
1451     char oid[] = "1.2.3";
1452 
1453     /* Test with empty info */
1454     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1455      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1456     if (ret)
1457     {
1458         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1459         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1460         LocalFree(buf);
1461     }
1462     /* Test with an empty entry */
1463     info.cAltEntry = 1;
1464     info.rgAltEntry = &entry;
1465     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1466      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1467     ok(!ret && GetLastError() == E_INVALIDARG,
1468      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1469     /* Test with an empty pointer */
1470     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1471     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1472      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1473     if (ret)
1474     {
1475         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1476         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1477         LocalFree(buf);
1478     }
1479     /* Test with a real URL */
1480     U(entry).pwszURL = (LPWSTR)url;
1481     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1482      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1483     if (ret)
1484     {
1485         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1486         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1487         LocalFree(buf);
1488     }
1489     /* Now with the URL containing an invalid IA5 char */
1490     U(entry).pwszURL = (LPWSTR)nihongoURL;
1491     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1492      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1493     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1494      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1495     /* The first invalid character is at index 7 */
1496     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1497      "Expected invalid char at index 7, got %d\n",
1498      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1499     /* Now with the URL missing a scheme */
1500     U(entry).pwszURL = (LPWSTR)dnsName;
1501     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1502      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1503     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1504     if (ret)
1505     {
1506         /* This succeeds, but it shouldn't, so don't worry about conforming */
1507         LocalFree(buf);
1508     }
1509     /* Now with a DNS name */
1510     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1511     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1512      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1513     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1514     if (ret)
1515     {
1516         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1517         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1518         LocalFree(buf);
1519     }
1520     /* Test with an IP address */
1521     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1522     U(entry).IPAddress.cbData = sizeof(localhost);
1523     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1524     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1525      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1526     if (ret)
1527     {
1528         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1529         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1530         LocalFree(buf);
1531     }
1532     /* Test with OID */
1533     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1534     U(entry).pszRegisteredID = oid;
1535     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1536      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1537     if (ret)
1538     {
1539         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1540         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1541         LocalFree(buf);
1542     }
1543     /* Test with directory name */
1544     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1545     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1546     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1547     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1548      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1549     if (ret)
1550     {
1551         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1552         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1553         LocalFree(buf);
1554     }
1555 }
1556 
1557 static void test_decodeAltName(DWORD dwEncoding)
1558 {
1559     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1560      0x00, 0x00, 0x01 };
1561     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1562      0x01 };
1563     static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1564      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1565     static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1566      0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1567     static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1568      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1569     BOOL ret;
1570     BYTE *buf = NULL;
1571     DWORD bufSize = 0;
1572     CERT_ALT_NAME_INFO *info;
1573 
1574     /* Test some bogus ones first */
1575     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1576      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1577      NULL, &buf, &bufSize);
1578     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1579      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1580      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1581      GetLastError());
1582     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1583      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1584      &bufSize);
1585     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1586      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1587      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1588      GetLastError());
1589     /* Now expected cases */
1590     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1591      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1592     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1593     if (ret)
1594     {
1595         info = (CERT_ALT_NAME_INFO *)buf;
1596 
1597         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1598          info->cAltEntry);
1599         LocalFree(buf);
1600     }
1601     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1602      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1603     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1604     if (ret)
1605     {
1606         info = (CERT_ALT_NAME_INFO *)buf;
1607 
1608         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1609          info->cAltEntry);
1610         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1611          "Expected CERT_ALT_NAME_URL, got %d\n",
1612          info->rgAltEntry[0].dwAltNameChoice);
1613         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1614          "Expected empty URL\n");
1615         LocalFree(buf);
1616     }
1617     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1618      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1619     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1620     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1621      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1622     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1623     if (ret)
1624     {
1625         info = (CERT_ALT_NAME_INFO *)buf;
1626 
1627         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1628          info->cAltEntry);
1629         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1630          "Expected CERT_ALT_NAME_URL, got %d\n",
1631          info->rgAltEntry[0].dwAltNameChoice);
1632         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1633         LocalFree(buf);
1634     }
1635     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1636      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1637     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1638     if (ret)
1639     {
1640         info = (CERT_ALT_NAME_INFO *)buf;
1641 
1642         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1643          info->cAltEntry);
1644         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1645          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1646          info->rgAltEntry[0].dwAltNameChoice);
1647         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1648          "Unexpected DNS name\n");
1649         LocalFree(buf);
1650     }
1651     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1652      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1653     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1654     if (ret)
1655     {
1656         info = (CERT_ALT_NAME_INFO *)buf;
1657 
1658         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1659          info->cAltEntry);
1660         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1661          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1662          info->rgAltEntry[0].dwAltNameChoice);
1663         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1664          "Unexpected IP address length %d\n",
1665           U(info->rgAltEntry[0]).IPAddress.cbData);
1666         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1667          sizeof(localhost)), "Unexpected IP address value\n");
1668         LocalFree(buf);
1669     }
1670     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1671      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1672     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1673     if (ret)
1674     {
1675         info = (CERT_ALT_NAME_INFO *)buf;
1676 
1677         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1678          info->cAltEntry);
1679         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1680          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1681          info->rgAltEntry[0].dwAltNameChoice);
1682         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1683            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1684         LocalFree(buf);
1685     }
1686     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1687      encodedDirectoryName, sizeof(encodedDirectoryName),
1688      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1689     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1690     if (ret)
1691     {
1692         info = (CERT_ALT_NAME_INFO *)buf;
1693 
1694         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1695          info->cAltEntry);
1696         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1697          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1698          info->rgAltEntry[0].dwAltNameChoice);
1699         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1700          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1701           U(info->rgAltEntry[0]).DirectoryName.cbData);
1702         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1703          encodedCommonName, sizeof(encodedCommonName)),
1704          "Unexpected directory name value\n");
1705         LocalFree(buf);
1706     }
1707     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1708      dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1709      NULL, &buf, &bufSize);
1710     /* Fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned about the
1711      * particular failure, just that it doesn't decode.
1712      * It succeeds on (broken) Windows versions that haven't addressed
1713      * embedded NULLs in alternate names.
1714      */
1715     ok(!ret || broken(ret), "expected failure\n");
1716     /* An embedded bell character is allowed, however. */
1717     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1718      dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1719      NULL, &buf, &bufSize);
1720     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1721     if (ret)
1722     {
1723         info = (CERT_ALT_NAME_INFO *)buf;
1724 
1725         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1726          info->cAltEntry);
1727         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1728          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1729          info->rgAltEntry[0].dwAltNameChoice);
1730         LocalFree(buf);
1731     }
1732     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1733      url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1734      NULL, &buf, &bufSize);
1735     /* Again, fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned
1736      * about the particular failure, just that it doesn't decode.
1737      * It succeeds on (broken) Windows versions that haven't addressed
1738      * embedded NULLs in alternate names.
1739      */
1740     ok(!ret || broken(ret), "expected failure\n");
1741 }
1742 
1743 struct UnicodeExpectedError
1744 {
1745     DWORD   valueType;
1746     LPCWSTR str;
1747     DWORD   errorIndex;
1748     DWORD   error;
1749 };
1750 
1751 static const WCHAR oneW[] = { '1',0 };
1752 static const WCHAR aW[] = { 'a',0 };
1753 static const WCHAR quoteW[] = { '"', 0 };
1754 
1755 static struct UnicodeExpectedError unicodeErrors[] = {
1756  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1757  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1758  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1759  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1760  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1761  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1762 };
1763 
1764 struct UnicodeExpectedResult
1765 {
1766     DWORD           valueType;
1767     LPCWSTR         str;
1768     CRYPT_DATA_BLOB encoded;
1769 };
1770 
1771 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1772 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1773 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1774 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1775 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1776 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1777 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1778 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1779 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1780 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1781 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1782 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1783  0x5b };
1784 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1785  0x6f,0x5b };
1786 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1787  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1788 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1789  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1790 
1791 static struct UnicodeExpectedResult unicodeResults[] = {
1792  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1793  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1794  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1795  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1796  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1797  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1798  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1799  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1800  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1801  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1802  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1803  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1804  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1805 };
1806 
1807 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1808  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1809  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1810 };
1811 
1812 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1813 {
1814     BYTE *buf = NULL;
1815     DWORD size = 0, i;
1816     BOOL ret;
1817     CERT_NAME_VALUE value;
1818 
1819     if (0)
1820     {
1821         /* Crashes on win9x */
1822         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1823          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1824         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1825          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1826     }
1827     /* Have to have a string of some sort */
1828     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1829     value.Value.pbData = NULL;
1830     value.Value.cbData = 0;
1831     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1832      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1833     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1834      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1835     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1836     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1837      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1838     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1839      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1840     value.dwValueType = CERT_RDN_ANY_TYPE;
1841     value.Value.pbData = (LPBYTE)oneW;
1842     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1843      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1844     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1845      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1846     value.Value.cbData = sizeof(oneW);
1847     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1848      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1849     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1850      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1851     /* An encoded string with specified length isn't good enough either */
1852     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1853     value.Value.pbData = oneUniversal;
1854     value.Value.cbData = sizeof(oneUniversal);
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     /* More failure checking */
1860     value.Value.cbData = 0;
1861     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1862     {
1863         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1864         value.dwValueType = unicodeErrors[i].valueType;
1865         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1866          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1867         ok(!ret && GetLastError() == unicodeErrors[i].error,
1868          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1869          unicodeErrors[i].error, GetLastError());
1870         ok(size == unicodeErrors[i].errorIndex,
1871          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1872          size);
1873     }
1874     /* cbData can be zero if the string is NULL-terminated */
1875     value.Value.cbData = 0;
1876     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1877     {
1878         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1879         value.dwValueType = unicodeResults[i].valueType;
1880         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1881          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1882         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1883          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1884         if (ret)
1885         {
1886             ok(size == unicodeResults[i].encoded.cbData,
1887              "Value type %d: expected size %d, got %d\n",
1888              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1889             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1890              "Value type %d: unexpected value\n", value.dwValueType);
1891             LocalFree(buf);
1892         }
1893     }
1894     /* These "encode," but they do so by truncating each unicode character
1895      * rather than properly encoding it.  Kept separate from the proper results,
1896      * because the encoded forms won't decode to their original strings.
1897      */
1898     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1899     {
1900         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1901         value.dwValueType = unicodeWeirdness[i].valueType;
1902         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1903          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1904         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1905         if (ret)
1906         {
1907             ok(size == unicodeWeirdness[i].encoded.cbData,
1908              "Value type %d: expected size %d, got %d\n",
1909              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1910             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1911              "Value type %d: unexpected value\n", value.dwValueType);
1912             LocalFree(buf);
1913         }
1914     }
1915 }
1916 
1917 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1918 {
1919     if (n <= 0) return 0;
1920     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1921     return *str1 - *str2;
1922 }
1923 
1924 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1925 {
1926     DWORD i;
1927 
1928     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1929     {
1930         BYTE *buf = NULL;
1931         BOOL ret;
1932         DWORD size = 0;
1933 
1934         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1935          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1936          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1937         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1938          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1939         if (ret && buf)
1940         {
1941             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1942 
1943             ok(value->dwValueType == unicodeResults[i].valueType,
1944              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1945              value->dwValueType);
1946             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1947              value->Value.cbData / sizeof(WCHAR)),
1948              "Unexpected decoded value for index %d (value type %d)\n", i,
1949              unicodeResults[i].valueType);
1950             LocalFree(buf);
1951         }
1952     }
1953 }
1954 
1955 struct encodedOctets
1956 {
1957     const BYTE *val;
1958     const BYTE *encoded;
1959 };
1960 
1961 static const unsigned char bin46[] = { 'h','i',0 };
1962 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1963 static const unsigned char bin48[] = {
1964      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1965 static const unsigned char bin49[] = {
1966      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1967 static const unsigned char bin50[] = { 0 };
1968 static const unsigned char bin51[] = { 0x04,0x00,0 };
1969 
1970 static const struct encodedOctets octets[] = {
1971     { bin46, bin47 },
1972     { bin48, bin49 },
1973     { bin50, bin51 },
1974 };
1975 
1976 static void test_encodeOctets(DWORD dwEncoding)
1977 {
1978     CRYPT_DATA_BLOB blob;
1979     DWORD i;
1980 
1981     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1982     {
1983         BYTE *buf = NULL;
1984         BOOL ret;
1985         DWORD bufSize = 0;
1986 
1987         blob.cbData = strlen((const char*)octets[i].val);
1988         blob.pbData = (BYTE*)octets[i].val;
1989         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1990          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1991         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1992         if (ret)
1993         {
1994             ok(buf[0] == 4,
1995              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1996             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1997              buf[1], octets[i].encoded[1]);
1998             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1999              octets[i].encoded[1] + 1), "Got unexpected value\n");
2000             LocalFree(buf);
2001         }
2002     }
2003 }
2004 
2005 static void test_decodeOctets(DWORD dwEncoding)
2006 {
2007     DWORD i;
2008 
2009     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
2010     {
2011         BYTE *buf = NULL;
2012         BOOL ret;
2013         DWORD bufSize = 0;
2014 
2015         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2016          octets[i].encoded, octets[i].encoded[1] + 2,
2017          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2018         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2019         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
2020          "Expected size >= %d, got %d\n",
2021            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2022         ok(buf != NULL, "Expected allocated buffer\n");
2023         if (ret)
2024         {
2025             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2026 
2027             if (blob->cbData)
2028                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2029                  "Unexpected value\n");
2030             LocalFree(buf);
2031         }
2032     }
2033 }
2034 
2035 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2036 
2037 struct encodedBits
2038 {
2039     DWORD cUnusedBits;
2040     const BYTE *encoded;
2041     DWORD cbDecoded;
2042     const BYTE *decoded;
2043 };
2044 
2045 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2046 static const unsigned char bin53[] = { 0xff,0xff };
2047 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2048 static const unsigned char bin55[] = { 0xff,0xfe };
2049 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2050 static const unsigned char bin57[] = { 0xfe };
2051 
2052 static const struct encodedBits bits[] = {
2053     /* normal test cases */
2054     { 0, bin52, 2, bin53 },
2055     { 1, bin54, 2, bin55 },
2056     /* strange test case, showing cUnusedBits >= 8 is allowed */
2057     { 9, bin56, 1, bin57 },
2058 };
2059 
2060 static void test_encodeBits(DWORD dwEncoding)
2061 {
2062     DWORD i;
2063 
2064     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2065     {
2066         CRYPT_BIT_BLOB blob;
2067         BOOL ret;
2068         BYTE *buf = NULL;
2069         DWORD bufSize = 0;
2070 
2071         blob.cbData = sizeof(bytesToEncode);
2072         blob.pbData = (BYTE *)bytesToEncode;
2073         blob.cUnusedBits = bits[i].cUnusedBits;
2074         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2075          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2076         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2077         if (ret)
2078         {
2079             ok(bufSize == bits[i].encoded[1] + 2,
2080              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2081              bits[i].encoded[1] + 2);
2082             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2083              "%d: Unexpected value\n", i);
2084             LocalFree(buf);
2085         }
2086     }
2087 }
2088 
2089 static void test_decodeBits(DWORD dwEncoding)
2090 {
2091     static const BYTE ber[] = "\x03\x02\x01\xff";
2092     static const BYTE berDecoded = 0xfe;
2093     DWORD i;
2094     BOOL ret;
2095     BYTE *buf = NULL;
2096     DWORD bufSize = 0;
2097 
2098     /* normal cases */
2099     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2100     {
2101         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2102          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2103          &bufSize);
2104         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2105         if (ret)
2106         {
2107             CRYPT_BIT_BLOB *blob;
2108 
2109             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2110                "Got unexpected size %d\n", bufSize);
2111             blob = (CRYPT_BIT_BLOB *)buf;
2112             ok(blob->cbData == bits[i].cbDecoded,
2113              "Got unexpected length %d, expected %d\n", blob->cbData,
2114              bits[i].cbDecoded);
2115             if (blob->cbData && bits[i].cbDecoded)
2116                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2117                  "Unexpected value\n");
2118             LocalFree(buf);
2119         }
2120     }
2121     /* special case: check that something that's valid in BER but not in DER
2122      * decodes successfully
2123      */
2124     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2125      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2126     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2127     if (ret)
2128     {
2129         CRYPT_BIT_BLOB *blob;
2130 
2131         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2132            "Got unexpected size %d\n", bufSize);
2133         blob = (CRYPT_BIT_BLOB *)buf;
2134         ok(blob->cbData == sizeof(berDecoded),
2135            "Got unexpected length %d\n", blob->cbData);
2136         if (blob->cbData)
2137             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2138         LocalFree(buf);
2139     }
2140 }
2141 
2142 struct Constraints2
2143 {
2144     CERT_BASIC_CONSTRAINTS2_INFO info;
2145     const BYTE *encoded;
2146 };
2147 
2148 static const unsigned char bin59[] = { 0x30,0x00 };
2149 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2150 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2151 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2152 static const struct Constraints2 constraints2[] = {
2153  /* empty constraints */
2154  { { FALSE, FALSE, 0}, bin59 },
2155  /* can be a CA */
2156  { { TRUE,  FALSE, 0}, bin60 },
2157  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2158   * but that's not the case
2159   */
2160  { { FALSE, TRUE,  0}, bin61 },
2161  /* can be a CA and has path length constraints set */
2162  { { TRUE,  TRUE,  1}, bin62 },
2163 };
2164 
2165 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2166 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2167  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2168  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2169  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2170 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2171  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2172  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2173  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2174  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2175 
2176 static void test_encodeBasicConstraints(DWORD dwEncoding)
2177 {
2178     DWORD i, bufSize = 0;
2179     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2180     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2181      (LPBYTE)encodedDomainName };
2182     BOOL ret;
2183     BYTE *buf = NULL;
2184 
2185     /* First test with the simpler info2 */
2186     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2187     {
2188         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2189          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2190          &bufSize);
2191         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2192         if (ret)
2193         {
2194             ok(bufSize == constraints2[i].encoded[1] + 2,
2195              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2196              bufSize);
2197             ok(!memcmp(buf, constraints2[i].encoded,
2198              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2199             LocalFree(buf);
2200         }
2201     }
2202     /* Now test with more complex basic constraints */
2203     info.SubjectType.cbData = 0;
2204     info.fPathLenConstraint = FALSE;
2205     info.cSubtreesConstraint = 0;
2206     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2207      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2208     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2209      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2210     if (ret)
2211     {
2212         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2213         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2214          "Unexpected value\n");
2215         LocalFree(buf);
2216     }
2217     /* None of the certs I examined had any subtree constraint, but I test one
2218      * anyway just in case.
2219      */
2220     info.cSubtreesConstraint = 1;
2221     info.rgSubtreesConstraint = &nameBlob;
2222     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2223      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2224     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2225      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2226     if (ret)
2227     {
2228         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2229         ok(!memcmp(buf, constraintWithDomainName,
2230          sizeof(constraintWithDomainName)), "Unexpected value\n");
2231         LocalFree(buf);
2232     }
2233     /* FIXME: test encoding with subject type. */
2234 }
2235 
2236 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2237 
2238 static void test_decodeBasicConstraints(DWORD dwEncoding)
2239 {
2240     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2241      0xff };
2242     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2243     DWORD i;
2244     BOOL ret;
2245     BYTE *buf = NULL;
2246     DWORD bufSize = 0;
2247 
2248     /* First test with simpler info2 */
2249     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2250     {
2251         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2252          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2253          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2254         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2255          GetLastError());
2256         if (ret)
2257         {
2258             CERT_BASIC_CONSTRAINTS2_INFO *info =
2259              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2260 
2261             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2262              "Unexpected value for item %d\n", i);
2263             LocalFree(buf);
2264         }
2265     }
2266     /* Check with the order of encoded elements inverted */
2267     buf = (PBYTE)1;
2268     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2269      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2270      &bufSize);
2271     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2272      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2273      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2274      GetLastError());
2275     ok(!buf, "Expected buf to be set to NULL\n");
2276     /* Check with a non-DER bool */
2277     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2278      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2279      &buf, &bufSize);
2280     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2281     if (ret)
2282     {
2283         CERT_BASIC_CONSTRAINTS2_INFO *info =
2284          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2285 
2286         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2287         LocalFree(buf);
2288     }
2289     /* Check with a non-basic constraints value */
2290     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2291      encodedCommonName, encodedCommonName[1] + 2,
2292      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2293     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2294      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2295      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2296      GetLastError());
2297     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2298     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2299      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2300      &buf, &bufSize);
2301     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2302     if (ret)
2303     {
2304         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2305 
2306         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2307         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2308         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2309         LocalFree(buf);
2310     }
2311     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2312      constraintWithDomainName, sizeof(constraintWithDomainName),
2313      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2314     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2315     if (ret)
2316     {
2317         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2318 
2319         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2320         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2321         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2322         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2323         {
2324             ok(info->rgSubtreesConstraint[0].cbData ==
2325              sizeof(encodedDomainName), "Wrong size %d\n",
2326              info->rgSubtreesConstraint[0].cbData);
2327             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2328              sizeof(encodedDomainName)), "Unexpected value\n");
2329         }
2330         LocalFree(buf);
2331     }
2332 }
2333 
2334 /* These are terrible public keys of course, I'm just testing encoding */
2335 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2336 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2337 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2338 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2339 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2340 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2341 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2342 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2343 
2344 struct EncodedRSAPubKey
2345 {
2346     const BYTE *modulus;
2347     size_t modulusLen;
2348     const BYTE *encoded;
2349     size_t decodedModulusLen;
2350 };
2351 
2352 static const struct EncodedRSAPubKey rsaPubKeys[] = {
2353     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2354     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2355     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2356     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2357 };
2358 
2359 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2360 {
2361     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2362     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2363     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2364     BOOL ret;
2365     BYTE *buf = NULL;
2366     DWORD bufSize = 0, i;
2367 
2368     /* Try with a bogus blob type */
2369     hdr->bType = 2;
2370     hdr->bVersion = CUR_BLOB_VERSION;
2371     hdr->reserved = 0;
2372     hdr->aiKeyAlg = CALG_RSA_KEYX;
2373     rsaPubKey->magic = 0x31415352;
2374     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2375     rsaPubKey->pubexp = 65537;
2376     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2377      sizeof(modulus1));
2378 
2379     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2380      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2381     ok(!ret && GetLastError() == E_INVALIDARG,
2382      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2383     /* Now with a bogus reserved field */
2384     hdr->bType = PUBLICKEYBLOB;
2385     hdr->reserved = 1;
2386     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2387      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388     if (ret)
2389     {
2390         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2391          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2392         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2393         LocalFree(buf);
2394     }
2395     /* Now with a bogus blob version */
2396     hdr->reserved = 0;
2397     hdr->bVersion = 0;
2398     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2399      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2400     if (ret)
2401     {
2402         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2403          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2404         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2405         LocalFree(buf);
2406     }
2407     /* And with a bogus alg ID */
2408     hdr->bVersion = CUR_BLOB_VERSION;
2409     hdr->aiKeyAlg = CALG_DES;
2410     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2411      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2412     if (ret)
2413     {
2414         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2415          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2416         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2417         LocalFree(buf);
2418     }
2419     /* Check a couple of RSA-related OIDs */
2420     hdr->aiKeyAlg = CALG_RSA_KEYX;
2421     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2422      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2423     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2424      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2425     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2426      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2427     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2428      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2429     /* Finally, all valid */
2430     hdr->aiKeyAlg = CALG_RSA_KEYX;
2431     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2432     {
2433         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2434          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2435         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2436          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2437         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2438         if (ret)
2439         {
2440             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2441              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2442              bufSize);
2443             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2444              "Unexpected value\n");
2445             LocalFree(buf);
2446         }
2447     }
2448 }
2449 
2450 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2451 {
2452     DWORD i;
2453     LPBYTE buf = NULL;
2454     DWORD bufSize = 0;
2455     BOOL ret;
2456 
2457     /* Try with a bad length */
2458     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2459      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2460      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2461     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2462      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2463      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2464      GetLastError());
2465     /* Try with a couple of RSA-related OIDs */
2466     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2467      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2468      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2469     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2470      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2471     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2472      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2473      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2474     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2475      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2476     /* Now try success cases */
2477     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2478     {
2479         bufSize = 0;
2480         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2481          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2482          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2483         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2484         if (ret)
2485         {
2486             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2487             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2488 
2489             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2490              rsaPubKeys[i].decodedModulusLen,
2491              "Wrong size %d\n", bufSize);
2492             ok(hdr->bType == PUBLICKEYBLOB,
2493              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2494              hdr->bType);
2495             ok(hdr->bVersion == CUR_BLOB_VERSION,
2496              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2497              CUR_BLOB_VERSION, hdr->bVersion);
2498             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2499              hdr->reserved);
2500             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2501              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2502             ok(rsaPubKey->magic == 0x31415352,
2503              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2504             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2505              "Wrong bit len %d\n", rsaPubKey->bitlen);
2506             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2507              rsaPubKey->pubexp);
2508             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2509              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2510              "Unexpected modulus\n");
2511             LocalFree(buf);
2512         }
2513     }
2514 }
2515 
2516 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2517  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2518  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2519 
2520 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2521  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2522  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2523  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2524 
2525 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2526 {
2527     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2528     CRYPT_SEQUENCE_OF_ANY seq;
2529     DWORD i;
2530     BOOL ret;
2531     BYTE *buf = NULL;
2532     DWORD bufSize = 0;
2533 
2534     /* Encode a homogeneous sequence */
2535     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2536     {
2537         blobs[i].cbData = ints[i].encoded[1] + 2;
2538         blobs[i].pbData = (BYTE *)ints[i].encoded;
2539     }
2540     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2541     seq.rgValue = blobs;
2542 
2543     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2544      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2545     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2546     if (ret)
2547     {
2548         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2549         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2550         LocalFree(buf);
2551     }
2552     /* Change the type of the first element in the sequence, and give it
2553      * another go
2554      */
2555     blobs[0].cbData = times[0].encodedTime[1] + 2;
2556     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2557     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2558      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2559     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2560     if (ret)
2561     {
2562         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2563         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2564          "Unexpected value\n");
2565         LocalFree(buf);
2566     }
2567 }
2568 
2569 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2570 {
2571     BOOL ret;
2572     BYTE *buf = NULL;
2573     DWORD bufSize = 0;
2574 
2575     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2576      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2577     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2578     if (ret)
2579     {
2580         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2581         DWORD i;
2582 
2583         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2584          "Wrong elements %d\n", seq->cValue);
2585         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2586         {
2587             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2588              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2589              seq->rgValue[i].cbData);
2590             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2591              ints[i].encoded[1] + 2), "Unexpected value\n");
2592         }
2593         LocalFree(buf);
2594     }
2595     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2596      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2597      &bufSize);
2598     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2599     if (ret)
2600     {
2601         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2602 
2603         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2604          "Wrong elements %d\n", seq->cValue);
2605         /* Just check the first element since it's all that changed */
2606         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2607          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2608          seq->rgValue[0].cbData);
2609         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2610          times[0].encodedTime[1] + 2), "Unexpected value\n");
2611         LocalFree(buf);
2612     }
2613 }
2614 
2615 struct encodedExtensions
2616 {
2617     CERT_EXTENSIONS exts;
2618     const BYTE *encoded;
2619 };
2620 
2621 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2622 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2623 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2624 static CERT_EXTENSION criticalExt =
2625  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2626 static CERT_EXTENSION nonCriticalExt =
2627  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2628 static CHAR oid_short[] = "1.1";
2629 static CERT_EXTENSION extWithShortOid =
2630  { oid_short, FALSE, { 0, NULL } };
2631 
2632 static const BYTE ext0[] = { 0x30,0x00 };
2633 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2634                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2635 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2636                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2637 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2638 
2639 static const struct encodedExtensions exts[] = {
2640  { { 0, NULL }, ext0 },
2641  { { 1, &criticalExt }, ext1 },
2642  { { 1, &nonCriticalExt }, ext2 },
2643  { { 1, &extWithShortOid }, ext3 }
2644 };
2645 
2646 static void test_encodeExtensions(DWORD dwEncoding)
2647 {
2648     DWORD i;
2649 
2650     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2651     {
2652         BOOL ret;
2653         BYTE *buf = NULL;
2654         DWORD bufSize = 0;
2655 
2656         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2657          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2658         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2659         if (ret)
2660         {
2661             ok(bufSize == exts[i].encoded[1] + 2,
2662              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2663             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2664              "Unexpected value\n");
2665             LocalFree(buf);
2666         }
2667     }
2668 }
2669 
2670 static void test_decodeExtensions(DWORD dwEncoding)
2671 {
2672     DWORD i;
2673 
2674     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2675     {
2676         BOOL ret;
2677         BYTE *buf = NULL;
2678         DWORD bufSize = 0;
2679 
2680         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2681          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2682          NULL, &buf, &bufSize);
2683         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2684         if (ret)
2685         {
2686             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2687             DWORD j;
2688 
2689             ok(ext->cExtension == exts[i].exts.cExtension,
2690              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2691              ext->cExtension);
2692             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2693             {
2694                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2695                  exts[i].exts.rgExtension[j].pszObjId),
2696                  "Expected OID %s, got %s\n",
2697                  exts[i].exts.rgExtension[j].pszObjId,
2698                  ext->rgExtension[j].pszObjId);
2699                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2700                  exts[i].exts.rgExtension[j].Value.pbData,
2701                  exts[i].exts.rgExtension[j].Value.cbData),
2702                  "Unexpected value\n");
2703             }
2704             LocalFree(buf);
2705         }
2706         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2707          exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
2708         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2709         buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);
2710         if (buf)
2711         {
2712             ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2713              exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, buf, &bufSize);
2714             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2715             HeapFree(GetProcessHeap(), 0, buf);
2716         }
2717     }
2718 }
2719 
2720 /* MS encodes public key info with a NULL if the algorithm identifier's
2721  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2722  * it encodes them by omitting the algorithm parameters.  It accepts either
2723  * form for decoding.
2724  */
2725 struct encodedPublicKey
2726 {
2727     CERT_PUBLIC_KEY_INFO info;
2728     const BYTE *encoded;
2729     const BYTE *encodedNoNull;
2730     CERT_PUBLIC_KEY_INFO decoded;
2731 };
2732 
2733 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2734  0xe, 0xf };
2735 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2736 
2737 static const unsigned char bin64[] = {
2738     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2739 static const unsigned char bin65[] = {
2740     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2741 static const unsigned char bin66[] = {
2742     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2743 static const unsigned char bin67[] = {
2744     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2745 static const unsigned char bin68[] = {
2746     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2747     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2748 static const unsigned char bin69[] = {
2749     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2750     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2751 static const unsigned char bin70[] = {
2752     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2753     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2754     0x0f};
2755 static const unsigned char bin71[] = {
2756     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2757     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2758     0x0f};
2759 static unsigned char bin72[] = { 0x05,0x00};
2760 
2761 static CHAR oid_bogus[] = "1.2.3",
2762             oid_rsa[]   = szOID_RSA;
2763 
2764 static const struct encodedPublicKey pubKeys[] = {
2765  /* with a bogus OID */
2766  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2767   bin64, bin65,
2768   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2769  /* some normal keys */
2770  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2771   bin66, bin67,
2772   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2773  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2774   bin68, bin69,
2775   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2776  /* with add'l parameters--note they must be DER-encoded */
2777  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2778   (BYTE *)aKey, 0 } },
2779   bin70, bin71,
2780   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2781   (BYTE *)aKey, 0 } } },
2782 };
2783 
2784 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2785 {
2786     DWORD i;
2787 
2788     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2789     {
2790         BOOL ret;
2791         BYTE *buf = NULL;
2792         DWORD bufSize = 0;
2793 
2794         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2795          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2796          &bufSize);
2797         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2798          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2799         if (ret)
2800         {
2801             ok(bufSize == pubKeys[i].encoded[1] + 2,
2802              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2803             if (bufSize == pubKeys[i].encoded[1] + 2)
2804                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2805                  "Unexpected value\n");
2806             LocalFree(buf);
2807         }
2808     }
2809 }
2810 
2811 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2812  const CERT_PUBLIC_KEY_INFO *got)
2813 {
2814     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2815      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2816      got->Algorithm.pszObjId);
2817     ok(expected->Algorithm.Parameters.cbData ==
2818      got->Algorithm.Parameters.cbData,
2819      "Expected parameters of %d bytes, got %d\n",
2820      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2821     if (expected->Algorithm.Parameters.cbData)
2822         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2823          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2824          "Unexpected algorithm parameters\n");
2825     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2826      "Expected public key of %d bytes, got %d\n",
2827      expected->PublicKey.cbData, got->PublicKey.cbData);
2828     if (expected->PublicKey.cbData)
2829         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2830          got->PublicKey.cbData), "Unexpected public key value\n");
2831 }
2832 
2833 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2834 {
2835     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2836      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2837      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2838      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2839     DWORD i;
2840     BOOL ret;
2841     BYTE *buf = NULL;
2842     DWORD bufSize = 0;
2843 
2844     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2845     {
2846         /* The NULL form decodes to the decoded member */
2847         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2848          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2849          NULL, &buf, &bufSize);
2850         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2851         if (ret)
2852         {
2853             comparePublicKeyInfo(&pubKeys[i].decoded,
2854              (CERT_PUBLIC_KEY_INFO *)buf);
2855             LocalFree(buf);
2856         }
2857         /* The non-NULL form decodes to the original */
2858         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2859          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2860          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2861         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2862         if (ret)
2863         {
2864             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2865             LocalFree(buf);
2866         }
2867     }
2868     /* Test with bogus (not valid DER) parameters */
2869     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2870      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2871      NULL, &buf, &bufSize);
2872     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2873      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2874      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2875      GetLastError());
2876 }
2877 
2878 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2879  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2880  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2881  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2882  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2883 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2884  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2885  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2886  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2887  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2888 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2889  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2890  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2891  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2892  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2893 static const BYTE v4Cert[] = {
2894 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2895 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2896 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2897 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2898 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2899  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2900  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2901  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2902  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2903  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2904  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2905 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2906  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2907  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2908  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2909  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2910  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2911  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2912 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2913  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2914  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2915  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2916  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2917  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2918  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2919  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2920  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2921  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2922 static const BYTE v1CertWithPubKey[] = {
2923 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2924 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2925 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2926 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2927 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2928 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2929 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2930 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2931 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2932 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2933 0x01,0x01 };
2934 static const BYTE v1CertWithPubKeyNoNull[] = {
2935 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2936 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2937 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2938 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2939 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2940 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2941 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2942 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2943 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2944 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2945 static const BYTE v1CertWithSubjectKeyId[] = {
2946 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2947 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2948 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2949 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2950 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2951 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2952 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2953 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2954 0x4c,0x61,0x6e,0x67,0x00 };
2955 static const BYTE v1CertWithIssuerUniqueId[] = {
2956 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2957 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2958 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2959 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2960 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2961 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2962 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2963 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2964 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2965 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2966 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2967 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2968 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2969 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2970 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2971 0x01,0x01,0xff,0x02,0x01,0x01 };
2972 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2973 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2974 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2975 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2976 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2977 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2978 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2979 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2980 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2981 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2982 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2983 0xff,0x02,0x01,0x01 };
2984 
2985 static const BYTE serialNum[] = { 0x01 };
2986 
2987 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2988 {
2989     BOOL ret;
2990     BYTE *buf = NULL;
2991     DWORD size = 0;
2992     CERT_INFO info = { 0 };
2993     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2994     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2995     CERT_EXTENSION ext;
2996 
2997     if (0)
2998     {
2999         /* Test with NULL pvStructInfo (crashes on win9x) */
3000         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
3001          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3002         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3003          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3004     }
3005     /* Test with a V1 cert */
3006     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3007      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3008     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3009      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3010     if (ret)
3011     {
3012         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3013          v1Cert[1] + 2, size);
3014         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3015         LocalFree(buf);
3016     }
3017     /* Test v2 cert */
3018     info.dwVersion = CERT_V2;
3019     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3020      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3021     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3022      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3023     if (ret)
3024     {
3025         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3026         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3027         LocalFree(buf);
3028     }
3029     /* Test v3 cert */
3030     info.dwVersion = CERT_V3;
3031     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3032      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3033     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3034      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3035     if (ret)
3036     {
3037         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3038         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3039         LocalFree(buf);
3040     }
3041     /* A v4 cert? */
3042     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3043     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3044      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3045     if (ret)
3046     {
3047         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3048         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3049         LocalFree(buf);
3050     }
3051     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3052      * API doesn't prevent it)
3053      */
3054     info.dwVersion = CERT_V1;
3055     info.cExtension = 1;
3056     info.rgExtension = &criticalExt;
3057     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3058      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3059     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3060      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3061     if (ret)
3062     {
3063         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3064         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3065         LocalFree(buf);
3066     }
3067     /* test v1 cert with a serial number */
3068     info.SerialNumber.cbData = sizeof(serialNum);
3069     info.SerialNumber.pbData = (BYTE *)serialNum;
3070     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3071      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3072     if (ret)
3073     {
3074         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3075         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3076         LocalFree(buf);
3077     }
3078     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3079     info.dwVersion = CERT_V1;
3080     info.cExtension = 0;
3081     info.IssuerUniqueId.cbData = sizeof(serialNum);
3082     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3083     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3084      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3085     ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3086      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3087     if (ret)
3088     {
3089         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3090         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3091          "Got unexpected value\n");
3092         LocalFree(buf);
3093     }
3094     /* Test v1 cert with an issuer name, a subject name, and a serial number */
3095     info.IssuerUniqueId.cbData = 0;
3096     info.IssuerUniqueId.pbData = NULL;
3097     info.cExtension = 1;
3098     info.rgExtension = &criticalExt;
3099     info.Issuer.cbData = sizeof(encodedCommonName);
3100     info.Issuer.pbData = (BYTE *)encodedCommonName;
3101     info.Subject.cbData = sizeof(encodedCommonName);
3102     info.Subject.pbData = (BYTE *)encodedCommonName;
3103     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3104      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3105     if (ret)
3106     {
3107         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3108         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3109         LocalFree(buf);
3110     }
3111     /* Add a public key */
3112     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3113     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3114     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3115     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3116      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3117     if (ret)
3118     {
3119         ok(size == sizeof(v1CertWithPubKey) ||
3120          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3121         if (size == sizeof(v1CertWithPubKey))
3122             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3123         else if (size == sizeof(v1CertWithPubKeyNoNull))
3124             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3125              "Got unexpected value\n");
3126         LocalFree(buf);
3127     }
3128     /* Again add an issuer unique id */
3129     info.IssuerUniqueId.cbData = sizeof(serialNum);
3130     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3131     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3132      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3133     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3134     if (ret)
3135     {
3136         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3137          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3138          "Wrong size %d\n", size);
3139         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3140             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3141              size), "unexpected value\n");
3142         else if (size ==
3143          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3144             ok(!memcmp(buf,
3145              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3146              "unexpected value\n");
3147         LocalFree(buf);
3148     }
3149     /* Remove the public key, and add a subject key identifier extension */
3150     info.IssuerUniqueId.cbData = 0;
3151     info.IssuerUniqueId.pbData = NULL;
3152     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3153     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3154     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3155     ext.pszObjId = oid_subject_key_identifier;
3156     ext.fCritical = FALSE;
3157     ext.Value.cbData = sizeof(octetCommonNameValue);
3158     ext.Value.pbData = octetCommonNameValue;
3159     info.cExtension = 1;
3160     info.rgExtension = &ext;
3161     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3162      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3163     if (ret)
3164     {
3165         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3166         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3167         LocalFree(buf);
3168     }
3169 }
3170 
3171 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3172 {
3173     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3174      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3175     BOOL ret;
3176     BYTE *buf = NULL;
3177     DWORD size = 0, i;
3178 
3179     /* Test with NULL pbEncoded */
3180     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3181      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3182     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3183      GetLastError() == OSS_BAD_ARG /* Win9x */),
3184      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3185     if (0)
3186     {
3187         /* Crashes on win9x */
3188         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3189          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3190         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3191          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3192     }
3193     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3194      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3195      * serial number, an issuer, a subject, and a public key.
3196      */
3197     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3198     {
3199         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3200          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3201          &buf, &size);
3202         ok(!ret, "Expected failure\n");
3203     }
3204     /* The following succeeds, even though v1 certs are not allowed to have
3205      * extensions.
3206      */
3207     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3208      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3209      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3210     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3211     if (ret)
3212     {
3213         CERT_INFO *info = (CERT_INFO *)buf;
3214 
3215         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3216         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3217          info->dwVersion);
3218         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3219          info->cExtension);
3220         LocalFree(buf);
3221     }
3222     /* The following also succeeds, even though V1 certs are not allowed to
3223      * have issuer unique ids.
3224      */
3225     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3226      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3227      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3228      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3229     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3230     if (ret)
3231     {
3232         CERT_INFO *info = (CERT_INFO *)buf;
3233 
3234         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3235         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3236          info->dwVersion);
3237         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3238          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3239         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3240          "unexpected issuer unique id value\n");
3241         LocalFree(buf);
3242     }
3243     /* Now check with serial number, subject and issuer specified */
3244     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3245      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3246     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3247     if (ret)
3248     {
3249         CERT_INFO *info = (CERT_INFO *)buf;
3250 
3251         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3252         ok(info->SerialNumber.cbData == 1,
3253          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3254         ok(*info->SerialNumber.pbData == *serialNum,
3255          "Expected serial number %d, got %d\n", *serialNum,
3256          *info->SerialNumber.pbData);
3257         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3258          "Wrong size %d\n", info->Issuer.cbData);
3259         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3260          "Unexpected issuer\n");
3261         ok(info->Subject.cbData == sizeof(encodedCommonName),
3262          "Wrong size %d\n", info->Subject.cbData);
3263         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3264          info->Subject.cbData), "Unexpected subject\n");
3265         LocalFree(buf);
3266     }
3267     /* Check again with pub key specified */
3268     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3269      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3270      &buf, &size);
3271     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3272     if (ret)
3273     {
3274         CERT_INFO *info = (CERT_INFO *)buf;
3275 
3276         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3277         ok(info->SerialNumber.cbData == 1,
3278          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3279         ok(*info->SerialNumber.pbData == *serialNum,
3280          "Expected serial number %d, got %d\n", *serialNum,
3281          *info->SerialNumber.pbData);
3282         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3283          "Wrong size %d\n", info->Issuer.cbData);
3284         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3285          "Unexpected issuer\n");
3286         ok(info->Subject.cbData == sizeof(encodedCommonName),
3287          "Wrong size %d\n", info->Subject.cbData);
3288         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3289          info->Subject.cbData), "Unexpected subject\n");
3290         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3291          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3292          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3293         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3294          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3295         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3296          sizeof(aKey)), "Unexpected public key\n");
3297         LocalFree(buf);
3298     }
3299 }
3300 
3301 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3302  0xe, 0xf };
3303 
3304 static const BYTE signedBigCert[] = {
3305  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3306  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3307  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3308  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3309  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3310  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3311  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3312  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3313  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3314  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3315  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3316  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3317 
3318 static void test_encodeCert(DWORD dwEncoding)
3319 {
3320     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3321      * also that bigCert is a NULL-terminated string, so don't count its
3322      * last byte (otherwise the signed cert won't decode.)
3323      */
3324     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3325      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3326     BOOL ret;
3327     BYTE *buf = NULL;
3328     DWORD bufSize = 0;
3329 
3330     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3331      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3332     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3333     if (ret)
3334     {
3335         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3336         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3337         LocalFree(buf);
3338     }
3339 }
3340 
3341 static void test_decodeCert(DWORD dwEncoding)
3342 {
3343     BOOL ret;
3344     BYTE *buf = NULL;
3345     DWORD size = 0;
3346 
3347     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3348      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3349     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3350     if (ret)
3351     {
3352         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3353 
3354         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3355          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3356         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3357          "Unexpected cert\n");
3358         ok(info->Signature.cbData == sizeof(hash),
3359          "Wrong signature size %d\n", info->Signature.cbData);
3360         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3361          "Unexpected signature\n");
3362         LocalFree(buf);
3363     }
3364     /* A signed cert decodes as a CERT_INFO too */
3365     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3366      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3367     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3368     if (ret)
3369     {
3370         CERT_INFO *info = (CERT_INFO *)buf;
3371 
3372         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3373         ok(info->SerialNumber.cbData == 1,
3374          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3375         ok(*info->SerialNumber.pbData == *serialNum,
3376          "Expected serial number %d, got %d\n", *serialNum,
3377          *info->SerialNumber.pbData);
3378         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3379          "Wrong size %d\n", info->Issuer.cbData);
3380         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3381          "Unexpected issuer\n");
3382         ok(info->Subject.cbData == sizeof(encodedCommonName),
3383          "Wrong size %d\n", info->Subject.cbData);
3384         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3385          info->Subject.cbData), "Unexpected subject\n");
3386         LocalFree(buf);
3387     }
3388 }
3389 
3390 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3391 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3392  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3393  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3394 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3395  0x00, 0x03 };
3396 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3397  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3398  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3399 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3400  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3401  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3402  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3403  0x2e, 0x6f, 0x72, 0x67 };
3404 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3405  CRL_REASON_AFFILIATION_CHANGED;
3406 
3407 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3408 {
3409     CRL_DIST_POINTS_INFO info = { 0 };
3410     CRL_DIST_POINT point = { { 0 } };
3411     CERT_ALT_NAME_ENTRY entry = { 0 };
3412     BOOL ret;
3413     BYTE *buf = NULL;
3414     DWORD size = 0;
3415 
3416     /* Test with an empty info */
3417     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3418      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3419     ok(!ret && GetLastError() == E_INVALIDARG,
3420      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3421     /* Test with one empty dist point */
3422     info.cDistPoint = 1;
3423     info.rgDistPoint = &point;
3424     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3425      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3426     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3427     if (ret)
3428     {
3429         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3430         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3431         LocalFree(buf);
3432     }
3433     /* A dist point with an invalid name */
3434     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3435     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3436     U(entry).pwszURL = (LPWSTR)nihongoURL;
3437     U(point.DistPointName).FullName.cAltEntry = 1;
3438     U(point.DistPointName).FullName.rgAltEntry = &entry;
3439     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3440      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3441     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3442      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3443     /* The first invalid character is at index 7 */
3444     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3445      "Expected invalid char at index 7, got %d\n",
3446      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3447     /* A dist point with (just) a valid name */
3448     U(entry).pwszURL = (LPWSTR)url;
3449     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3450      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3451     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3452     if (ret)
3453     {
3454         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3455         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3456         LocalFree(buf);
3457     }
3458     /* A dist point with (just) reason flags */
3459     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3460     point.ReasonFlags.cbData = sizeof(crlReason);
3461     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3462     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3463      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3464     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3465     if (ret)
3466     {
3467         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3468         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3469         LocalFree(buf);
3470     }
3471     /* A dist point with just an issuer */
3472     point.ReasonFlags.cbData = 0;
3473     point.CRLIssuer.cAltEntry = 1;
3474     point.CRLIssuer.rgAltEntry = &entry;
3475     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3476      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3477     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3478     if (ret)
3479     {
3480         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3481         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3482         LocalFree(buf);
3483     }
3484     /* A dist point with both a name and an issuer */
3485     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3486     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3487      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3488     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3489     if (ret)
3490     {
3491         ok(size == sizeof(distPointWithUrlAndIssuer),
3492          "Wrong size %d\n", size);
3493         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3494         LocalFree(buf);
3495     }
3496 }
3497 
3498 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3499 {
3500     BOOL ret;
3501     BYTE *buf = NULL;
3502     DWORD size = 0;
3503     PCRL_DIST_POINTS_INFO info;
3504     PCRL_DIST_POINT point;
3505     PCERT_ALT_NAME_ENTRY entry;
3506 
3507     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3508      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3509      &buf, &size);
3510     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3511     if (ret)
3512     {
3513         info = (PCRL_DIST_POINTS_INFO)buf;
3514         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3515          "Wrong size %d\n", size);
3516         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3517          info->cDistPoint);
3518         point = info->rgDistPoint;
3519         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3520          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3521          point->DistPointName.dwDistPointNameChoice);
3522         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3523         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3524         LocalFree(buf);
3525     }
3526     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3527      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3528      &buf, &size);
3529     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3530     if (ret)
3531     {
3532         info = (PCRL_DIST_POINTS_INFO)buf;
3533         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3534          "Wrong size %d\n", size);
3535         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3536          info->cDistPoint);
3537         point = info->rgDistPoint;
3538         ok(point->DistPointName.dwDistPointNameChoice ==
3539          CRL_DIST_POINT_FULL_NAME,
3540          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3541          point->DistPointName.dwDistPointNameChoice);
3542         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3543          "Expected 1 name entry, got %d\n",
3544          U(point->DistPointName).FullName.cAltEntry);
3545         entry = U(point->DistPointName).FullName.rgAltEntry;
3546         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3547          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3548         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3549         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3550         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3551         LocalFree(buf);
3552     }
3553     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3554      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3555      NULL, &buf, &size);
3556     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3557     if (ret)
3558     {
3559         info = (PCRL_DIST_POINTS_INFO)buf;
3560         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3561          "Wrong size %d\n", size);
3562         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3563          info->cDistPoint);
3564         point = info->rgDistPoint;
3565         ok(point->DistPointName.dwDistPointNameChoice ==
3566          CRL_DIST_POINT_NO_NAME,
3567          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3568          point->DistPointName.dwDistPointNameChoice);
3569         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3570          "Expected reason length\n");
3571         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3572          "Unexpected reason\n");
3573         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3574         LocalFree(buf);
3575     }
3576     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3577      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3578      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3579     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3580     if (ret)
3581     {
3582         info = (PCRL_DIST_POINTS_INFO)buf;
3583         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3584          "Wrong size %d\n", size);
3585         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3586          info->cDistPoint);
3587         point = info->rgDistPoint;
3588         ok(point->DistPointName.dwDistPointNameChoice ==
3589          CRL_DIST_POINT_FULL_NAME,
3590          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3591          point->DistPointName.dwDistPointNameChoice);
3592         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3593          "Expected 1 name entry, got %d\n",
3594          U(point->DistPointName).FullName.cAltEntry);
3595         entry = U(point->DistPointName).FullName.rgAltEntry;
3596         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3597          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3598         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3599         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3600         ok(point->CRLIssuer.cAltEntry == 1,
3601          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3602         entry = point->CRLIssuer.rgAltEntry;
3603         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3604          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3605         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3606         LocalFree(buf);
3607     }
3608     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3609      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3610      NULL, NULL, &size);
3611     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3612     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3613     if (buf)
3614     {
3615         ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3616          distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3617          NULL, buf, &size);
3618         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3619         HeapFree(GetProcessHeap(), 0, buf);
3620     }
3621 }
3622 
3623 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3624 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3625 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3626  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3627  0x67 };
3628 
3629 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3630 {
3631     BOOL ret;
3632     BYTE *buf = NULL;
3633     DWORD size = 0;
3634     CRL_ISSUING_DIST_POINT point = { { 0 } };
3635     CERT_ALT_NAME_ENTRY entry;
3636 
3637     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3638      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3639     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3640     {
3641         skip("no X509_ISSUING_DIST_POINT encode support\n");
3642         return;
3643     }
3644     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3645      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3646     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3647      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3648     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3649     if (ret)
3650     {
3651         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3652         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3653         LocalFree(buf);
3654     }
3655     /* nonsensical flags */
3656     point.fOnlyContainsUserCerts = TRUE;
3657     point.fOnlyContainsCACerts = TRUE;
3658     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3659      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3660     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3661     if (ret)
3662     {
3663         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3664         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3665         LocalFree(buf);
3666     }
3667     /* unimplemented name type */
3668     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3669     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3670     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3671      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3672     ok(!ret && GetLastError() == E_INVALIDARG,
3673      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3674     /* empty name */
3675     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3676     U(point.DistPointName).FullName.cAltEntry = 0;
3677     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3678      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3679     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3680     if (ret)
3681     {
3682         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3683         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3684         LocalFree(buf);
3685     }
3686     /* name with URL entry */
3687     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3688     U(entry).pwszURL = (LPWSTR)url;
3689     U(point.DistPointName).FullName.cAltEntry = 1;
3690     U(point.DistPointName).FullName.rgAltEntry = &entry;
3691     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3692      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3693     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3694     if (ret)
3695     {
3696         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3697         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3698         LocalFree(buf);
3699     }
3700 }
3701 
3702 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3703  const CERT_ALT_NAME_ENTRY *got)
3704 {
3705     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3706      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3707      got->dwAltNameChoice);
3708     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3709     {
3710         switch (got->dwAltNameChoice)
3711         {
3712         case CERT_ALT_NAME_RFC822_NAME:
3713         case CERT_ALT_NAME_DNS_NAME:
3714         case CERT_ALT_NAME_EDI_PARTY_NAME:
3715         case CERT_ALT_NAME_URL:
3716         case CERT_ALT_NAME_REGISTERED_ID:
3717             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3718              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3719              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3720              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3721              "Unexpected name\n");
3722             break;
3723         case CERT_ALT_NAME_X400_ADDRESS:
3724         case CERT_ALT_NAME_DIRECTORY_NAME:
3725         case CERT_ALT_NAME_IP_ADDRESS:
3726             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3727                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3728             ok(!memcmp(U(*got).IPAddress.pbData, U(*expected).IPAddress.pbData,
3729                        U(*got).IPAddress.cbData), "Unexpected value\n");
3730             break;
3731         }
3732     }
3733 }
3734 
3735 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3736  const CERT_ALT_NAME_INFO *got)
3737 {
3738     DWORD i;
3739 
3740     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3741      expected->cAltEntry, got->cAltEntry);
3742     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3743         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3744 }
3745 
3746 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3747  const CRL_DIST_POINT_NAME *got)
3748 {
3749     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3750      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3751     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3752         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3753 }
3754 
3755 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3756  const CRL_ISSUING_DIST_POINT *got)
3757 {
3758     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3759     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3760      "Unexpected fOnlyContainsUserCerts\n");
3761     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3762      "Unexpected fOnlyContainsCACerts\n");
3763     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3764      "Unexpected reason flags\n");
3765     ok(got->fIndirectCRL == expected->fIndirectCRL,
3766      "Unexpected fIndirectCRL\n");
3767 }
3768 
3769 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3770 {
3771     BOOL ret;
3772     BYTE *buf = NULL;
3773     DWORD size = 0;
3774     CRL_ISSUING_DIST_POINT point = { { 0 } };
3775 
3776     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3777      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3778      &buf, &size);
3779     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3780     {
3781         skip("no X509_ISSUING_DIST_POINT decode support\n");
3782         return;
3783     }
3784     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3785     if (ret)
3786     {
3787         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3788         LocalFree(buf);
3789     }
3790     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3791      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3792      &buf, &size);
3793     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3794     if (ret)
3795     {
3796         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3797         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3798         LocalFree(buf);
3799     }
3800     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3801      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3802      &buf, &size);
3803     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3804     if (ret)
3805     {
3806         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3807         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3808         U(point.DistPointName).FullName.cAltEntry = 0;
3809         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3810         LocalFree(buf);
3811     }
3812     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3813      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3814     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3815     if (ret)
3816     {
3817         CERT_ALT_NAME_ENTRY entry;
3818 
3819         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3820         U(entry).pwszURL = (LPWSTR)url;
3821         U(point.DistPointName).FullName.cAltEntry = 1;
3822         U(point.DistPointName).FullName.rgAltEntry = &entry;
3823         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3824         LocalFree(buf);
3825     }
3826 }
3827 
3828 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3829  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3830  0x30, 0x5a };
3831 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3832  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3833  0x30, 0x30, 0x30, 0x30, 0x5a };
3834 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3835  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3836  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3837  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3838  0x5a };
3839 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3840  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3841  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3842  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3843  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3844  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3845 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3846  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3847  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3848  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3849  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3850  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3851 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3852  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3853  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3854  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3855  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3856  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3857  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3858 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3859  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3860  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3861  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3862  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3863  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3864  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3865 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3866  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3867  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3868  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3869  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3870  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3871  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3872 
3873 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3874 {
3875     BOOL ret;
3876     BYTE *buf = NULL;
3877     DWORD size = 0;
3878     CRL_INFO info = { 0 };
3879     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3880 
3881     /* Test with a V1 CRL */
3882     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3883      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3884     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3885      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3886     if (ret)
3887     {
3888         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3889         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3890         LocalFree(buf);
3891     }
3892     /* Test v2 CRL */
3893     info.dwVersion = CRL_V2;
3894     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3895      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3896     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3897      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3898     if (ret)
3899     {
3900         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3901          v2CRL[1] + 2, size);
3902         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3903         LocalFree(buf);
3904     }
3905     /* v1 CRL with a name */
3906     info.dwVersion = CRL_V1;
3907     info.Issuer.cbData = sizeof(encodedCommonName);
3908     info.Issuer.pbData = (BYTE *)encodedCommonName;
3909     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3910      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3911     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3912     if (ret)
3913     {
3914         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3915         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3916         LocalFree(buf);
3917     }
3918     if (0)
3919     {
3920         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3921         info.cCRLEntry = 1;
3922         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3923          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3924         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3925          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3926     }
3927     /* now set an empty entry */
3928     info.cCRLEntry = 1;
3929     info.rgCRLEntry = &entry;
3930     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3931      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3932     if (ret)
3933     {
3934         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3935          "Wrong size %d\n", size);
3936         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3937          "Got unexpected value\n");
3938         LocalFree(buf);
3939     }
3940     /* an entry with a serial number */
3941     entry.SerialNumber.cbData = sizeof(serialNum);
3942     entry.SerialNumber.pbData = (BYTE *)serialNum;
3943     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3944      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3945     if (ret)
3946     {
3947         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3948          "Wrong size %d\n", size);
3949         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3950          "Got unexpected value\n");
3951         LocalFree(buf);
3952     }
3953     /* an entry with an extension */
3954     entry.cExtension = 1;
3955     entry.rgExtension = &criticalExt;
3956     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3957      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3958     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3959     if (ret)
3960     {
3961         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3962         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3963         LocalFree(buf);
3964     }
3965     /* a CRL with an extension */
3966     entry.cExtension = 0;
3967     info.cExtension = 1;
3968     info.rgExtension = &criticalExt;
3969     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3970      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3971     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3972     if (ret)
3973     {
3974         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3975         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3976         LocalFree(buf);
3977     }
3978     /* a v2 CRL with an extension, this time non-critical */
3979     info.dwVersion = CRL_V2;
3980     info.rgExtension = &nonCriticalExt;
3981     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3982      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3983     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3984     if (ret)
3985     {
3986         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3987         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3988         LocalFree(buf);
3989     }
3990 }
3991 
3992 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3993  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3994  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3995  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3996  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3997  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3998  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3999  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
4000  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
4001  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
4002  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
4003  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
4004  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
4005  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
4006  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
4007  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
4008  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
4009  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
4010  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
4011  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
4012  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
4013  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
4014  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
4015  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
4016  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4017  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4018  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4019  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4020  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4021  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4022  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4023  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4024  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4025  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4026  0xcd };
4027 static const BYTE verisignCRLWithLotsOfEntries[] = {
4028 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4029 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4030 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4031 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4032 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4033 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4034 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4035 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4036 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4037 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4038 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4039 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4040 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4041 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4042 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4043 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4044 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4045 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4046 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4047 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4048 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4049 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4050 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4051 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4052 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4053 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4054 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4055 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4056 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4057 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4058 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4059 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4060 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4061 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4062 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4063 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4064 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4065 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4066 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4067 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4068 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4069 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4070 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4071 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4072 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4073 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4074 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4075 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4076 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4077 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4078 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4079 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4080 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4081 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4082 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4083 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4084 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4085 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4086 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4087 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4088 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4089 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4090 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4091 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4092 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4093 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4094 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4095 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4096 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4097 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4098 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4099 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4100 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4101 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4102 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4103 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4104 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4105 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4106 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4107 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4108 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4109 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4110 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4111 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4112 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4113 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4114 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4115 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4116 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4117 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4118 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4119 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4120 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4121 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4122 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4123 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4124 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4125 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4126 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4127 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4128 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4129 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4130 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4131 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4132 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4133 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4134 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4135 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4136 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4137 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4138 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4139 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4140 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4141 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4142 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4143 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4144 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4145 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4146 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4147 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4148 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4149 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4150 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4151 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4152 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4153 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4154 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4155 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4156 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4157 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4158 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4159 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4160 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4161 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4162 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4163 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4164 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4165 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4166 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4167 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4168 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4169 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4170 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4171 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4172 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4173 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4174 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4175 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4176 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4177 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4178 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4179 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4180 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4181 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4182 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4183 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4184 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4185 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4186 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4187 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4188 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4189 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4190 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4191 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4192 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4193 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4194 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4195 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4196 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4197 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4198 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4199 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4200 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4201 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4202 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4203 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4204 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4205 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4206 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4207 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4208 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4209 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4210 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4211 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4212 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4213 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4214 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4215 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4216 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4217 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4218 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4219 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4220 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4221 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4222 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4223 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4224 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4225 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4226 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4227 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4228 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4229 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4230 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4231 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4232 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4233 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4234 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4235 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4236 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4237 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4238 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4239 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4240 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4241 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4242 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4243 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4244 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4245 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4246 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4247 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4248 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4249 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4250 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4251 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4252 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4253 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4254 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4255 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4256 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4257 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4258 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4259 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4260 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4261 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4262 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4263 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4264 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4265 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4266 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4267 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4268 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4269 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4270 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4271 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4272 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4273 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4274 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4275 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4276 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4277 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4278 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4279 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4280 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4281 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4282 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4283 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4284 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4285 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4286 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4287 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4288 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4289 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4290 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4291 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4292 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4293 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4294 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4295 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4296 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4297 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4298 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4299 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4300 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4301 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4302 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4303 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4304 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4305 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4306 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4307 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4308 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4309 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4310 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4311 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4312 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4313 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4314 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4315 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4316 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4317 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4318 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4319 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4320 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4321 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4322 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4323 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4324 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4325 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4326 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4327 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4328 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4329 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4330 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4331 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4332 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4333 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4334 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4335 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4336 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4337 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4338 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4339 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4340 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4341 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4342 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4343 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4344 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4345 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4346 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4347 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4348 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4349 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4350 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4351 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4352 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4353 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4354 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4355 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4356 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4357 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4358 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4359 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4360 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4361 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4362 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4363 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4364 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4365 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4366 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4367 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4368 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4369 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4370 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4371 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4372 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4373 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4374 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4375 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4376 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4377 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4378 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4379 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4380 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4381 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4382 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4383 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4384 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4385 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4386 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4387 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4388 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4389 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4390 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4391 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4392 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4393 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4394 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4395 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4396 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4397 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4398 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4399 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4400 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4401 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4402 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4403 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4404 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4405 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4406 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4407 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4408 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4409 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4410 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4411 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4412 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4413 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4414 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4415 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4416 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4417 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4418 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4419 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4420 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4421 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4422 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4423 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4424 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4425 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4426 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4427 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4428 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4429 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4430 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4431 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4432 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4433 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4434 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4435 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4436 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4437 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4438 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4439 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4440 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4441 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4442 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4443 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4444 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4445 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4446 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4447 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4448 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4449 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4450 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4451 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4452 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4453 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4454 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4455 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4456 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4457 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4458 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4459 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4460 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4461 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4462 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4463 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4464 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4465 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4466 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4467 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4468 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4469 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4470 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4471 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4472 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4473 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4474 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4475 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4476 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4477 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4478 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4479 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4480 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4481 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4482 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4483 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4484 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4485 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4486 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4487 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4488 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4489 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4490 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4491 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4492 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4493 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4494 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4495 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4496 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4497 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4498 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4499 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4500 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4501 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4502 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4503 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4504 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4505 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4506 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4507 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4508 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4509 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4510 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4511 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4512 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4513 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4514 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4515 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4516 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4517 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4518 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4519 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4520 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4521 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4522 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4523 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4524 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4525 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4526 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4527 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4528 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4529 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4530 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4531 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4532 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4533 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4534 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4535 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4536 
4537 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4538 {
4539     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4540     BOOL ret;
4541     BYTE *buf = NULL;
4542     DWORD size = 0, i;
4543 
4544     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4545     {
4546         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4547          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4548          &buf, &size);
4549         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4550          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4551          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4552          GetLastError());
4553     }
4554     /* at a minimum, a CRL must contain an issuer: */
4555     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4556      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4557      &buf, &size);
4558     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4559     if (ret)
4560     {
4561         CRL_INFO *info = (CRL_INFO *)buf;
4562 
4563         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4564         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4565          info->cCRLEntry);
4566         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4567          "Wrong issuer size %d\n", info->Issuer.cbData);
4568         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4569          "Unexpected issuer\n");
4570         LocalFree(buf);
4571     }
4572     /* check decoding with an empty CRL entry */
4573     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4574      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4575      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4576     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4577      GetLastError() == OSS_DATA_ERROR /* Win9x */ ||
4578      GetLastError() == CRYPT_E_BAD_ENCODE /* Win8 */),
4579      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4580      GetLastError());
4581     /* with a real CRL entry */
4582     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4583      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4584      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4585     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4586     if (ret)
4587     {
4588         CRL_INFO *info = (CRL_INFO *)buf;
4589         CRL_ENTRY *entry;
4590 
4591         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4592         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4593          info->cCRLEntry);
4594         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4595         entry = info->rgCRLEntry;
4596         ok(entry->SerialNumber.cbData == 1,
4597          "Expected serial number size 1, got %d\n",
4598          entry->SerialNumber.cbData);
4599         ok(*entry->SerialNumber.pbData == *serialNum,
4600          "Expected serial number %d, got %d\n", *serialNum,
4601          *entry->SerialNumber.pbData);
4602         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4603          "Wrong issuer size %d\n", info->Issuer.cbData);
4604         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4605          "Unexpected issuer\n");
4606         LocalFree(buf);
4607     }
4608     /* a real CRL from verisign that has extensions */
4609     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4610      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4611      NULL, &buf, &size);
4612     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4613     if (ret)
4614     {
4615         CRL_INFO *info = (CRL_INFO *)buf;
4616 
4617         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4618         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4619          info->cCRLEntry);
4620         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4621         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4622          info->cExtension);
4623         LocalFree(buf);
4624     }
4625     /* another real CRL from verisign that has lots of entries */
4626     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4627      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4628      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4629     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4630     if (ret)
4631     {
4632         CRL_INFO *info = (CRL_INFO *)buf;
4633 
4634         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4635         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4636          info->cCRLEntry);
4637         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4638          info->cExtension);
4639         LocalFree(buf);
4640     }
4641     /* and finally, with an extension */
4642     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4643      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4644      NULL, &buf, &size);
4645     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4646     if (ret)
4647     {
4648         CRL_INFO *info = (CRL_INFO *)buf;
4649         CRL_ENTRY *entry;
4650 
4651         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4652         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4653          info->cCRLEntry);
4654         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4655         entry = info->rgCRLEntry;
4656         ok(entry->SerialNumber.cbData == 1,
4657          "Expected serial number size 1, got %d\n",
4658          entry->SerialNumber.cbData);
4659         ok(*entry->SerialNumber.pbData == *serialNum,
4660          "Expected serial number %d, got %d\n", *serialNum,
4661          *entry->SerialNumber.pbData);
4662         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4663          "Wrong issuer size %d\n", info->Issuer.cbData);
4664         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4665          "Unexpected issuer\n");
4666         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4667          info->cExtension);
4668         LocalFree(buf);
4669     }
4670     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4671      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4672      NULL, &buf, &size);
4673     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4674     if (ret)
4675     {
4676         CRL_INFO *info = (CRL_INFO *)buf;
4677 
4678         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4679          info->cExtension);
4680         LocalFree(buf);
4681     }
4682 }
4683 
4684 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4685  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4686 static const BYTE encodedUsage[] = {
4687  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4688  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4689  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4690 
4691 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4692 {
4693     BOOL ret;
4694     BYTE *buf = NULL;
4695     DWORD size = 0;
4696     CERT_ENHKEY_USAGE usage;
4697 
4698     /* Test with empty usage */
4699     usage.cUsageIdentifier = 0;
4700     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4701      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4702     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4703     if (ret)
4704     {
4705         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4706         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4707         LocalFree(buf);
4708     }
4709     /* Test with a few usages */
4710     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4711     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4712     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4713      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4714     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4715     if (ret)
4716     {
4717         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4718         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4719         LocalFree(buf);
4720     }
4721 }
4722 
4723 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4724 {
4725     BOOL ret;
4726     LPBYTE buf = NULL;
4727     DWORD size = 0;
4728 
4729     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4730      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4731      &buf, &size);
4732     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4733     if (ret)
4734     {
4735         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4736 
4737         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4738          "Wrong size %d\n", size);
4739         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4740          usage->cUsageIdentifier);
4741         LocalFree(buf);
4742     }
4743     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4744      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4745      &buf, &size);
4746     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4747     if (ret)
4748     {
4749         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4750         DWORD i;
4751 
4752         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4753          "Wrong size %d\n", size);
4754         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4755          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4756         for (i = 0; i < usage->cUsageIdentifier; i++)
4757             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4758              "Expected OID %s, got %s\n", keyUsages[i],
4759              usage->rgpszUsageIdentifier[i]);
4760         LocalFree(buf);
4761     }
4762     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4763      encodedUsage, sizeof(encodedUsage), 0, NULL, NULL, &size);
4764     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4765     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4766     if (buf)
4767     {
4768         ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4769          encodedUsage, sizeof(encodedUsage), 0, NULL, buf, &size);
4770         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4771         HeapFree(GetProcessHeap(), 0, buf);
4772     }
4773 }
4774 
4775 static BYTE keyId[] = { 1,2,3,4 };
4776 static const BYTE authorityKeyIdWithId[] = {
4777  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4778 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4779  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4780  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4781 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4782 
4783 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4784 {
4785     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4786     BOOL ret;
4787     BYTE *buf = NULL;
4788     DWORD size = 0;
4789 
4790     /* Test with empty id */
4791     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4792      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4793     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4794     if (ret)
4795     {
4796         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4797         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4798         LocalFree(buf);
4799     }
4800     /* With just a key id */
4801     info.KeyId.cbData = sizeof(keyId);
4802     info.KeyId.pbData = keyId;
4803     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4804      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4805     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4806     if (ret)
4807     {
4808         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4809         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4810         LocalFree(buf);
4811     }
4812     /* With just an issuer */
4813     info.KeyId.cbData = 0;
4814     info.CertIssuer.cbData = sizeof(encodedCommonName);
4815     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4816     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4817      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4818     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4819     if (ret)
4820     {
4821         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4822          size);
4823         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4824         LocalFree(buf);
4825     }
4826     /* With just a serial number */
4827     info.CertIssuer.cbData = 0;
4828     info.CertSerialNumber.cbData = sizeof(serialNum);
4829     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4830     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4831      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4832     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4833     if (ret)
4834     {
4835         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4836          size);
4837         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4838         LocalFree(buf);
4839     }
4840 }
4841 
4842 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4843 {
4844     BOOL ret;
4845     LPBYTE buf = NULL;
4846     DWORD size = 0;
4847 
4848     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4849      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4850      &buf, &size);
4851     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4852     if (ret)
4853     {
4854         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4855 
4856         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4857          size);
4858         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4859         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4860         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4861         LocalFree(buf);
4862     }
4863     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4864      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4865      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4866     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4867     if (ret)
4868     {
4869         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4870 
4871         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4872          size);
4873         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4874         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4875          "Unexpected key id\n");
4876         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4877         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4878         LocalFree(buf);
4879     }
4880     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4881      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4882      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4883     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4884     if (ret)
4885     {
4886         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4887 
4888         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4889          size);
4890         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4891         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4892          "Unexpected issuer len\n");
4893         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4894          sizeof(encodedCommonName)), "Unexpected issuer\n");
4895         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4896         LocalFree(buf);
4897     }
4898     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4899      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4900      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4901     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4902     if (ret)
4903     {
4904         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4905 
4906         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4907          size);
4908         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4909         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4910         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4911          "Unexpected serial number len\n");
4912         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4913          "Unexpected serial number\n");
4914         LocalFree(buf);
4915     }
4916 }
4917 
4918 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4919  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4920  0x6f,0x72,0x67 };
4921 
4922 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4923 {
4924     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4925     CERT_ALT_NAME_ENTRY entry = { 0 };
4926     BOOL ret;
4927     BYTE *buf = NULL;
4928     DWORD size = 0;
4929 
4930     /* Test with empty id */
4931     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4932      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4933     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4934     if (ret)
4935     {
4936         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4937         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4938         LocalFree(buf);
4939     }
4940     /* With just a key id */
4941     info.KeyId.cbData = sizeof(keyId);
4942     info.KeyId.pbData = keyId;
4943     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4944      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4945     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4946     if (ret)
4947     {
4948         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4949          size);
4950         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4951         LocalFree(buf);
4952     }
4953     /* With a bogus issuer name */
4954     info.KeyId.cbData = 0;
4955     info.AuthorityCertIssuer.cAltEntry = 1;
4956     info.AuthorityCertIssuer.rgAltEntry = &entry;
4957     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4958      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4959     ok(!ret && GetLastError() == E_INVALIDARG,
4960      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4961     /* With an issuer name */
4962     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4963     U(entry).pwszURL = (LPWSTR)url;
4964     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4965      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4966     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4967     if (ret)
4968     {
4969         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4970          size);
4971         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4972          "Unexpected value\n");
4973         LocalFree(buf);
4974     }
4975     /* With just a serial number */
4976     info.AuthorityCertIssuer.cAltEntry = 0;
4977     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4978     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4979     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4980      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4981     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4982     if (ret)
4983     {
4984         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4985          size);
4986         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4987         LocalFree(buf);
4988     }
4989 }
4990 
4991 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4992 {
4993     BOOL ret;
4994     LPBYTE buf = NULL;
4995     DWORD size = 0;
4996 
4997     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4998      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4999      &buf, &size);
5000     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5001     if (ret)
5002     {
5003         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5004 
5005         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5006          size);
5007         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5008         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5009          "Expected no issuer name entries\n");
5010         ok(info->AuthorityCertSerialNumber.cbData == 0,
5011          "Expected no serial number\n");
5012         LocalFree(buf);
5013     }
5014     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5015      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5016      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5017     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5018     if (ret)
5019     {
5020         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5021 
5022         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5023          size);
5024         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5025         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5026          "Unexpected key id\n");
5027         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5028          "Expected no issuer name entries\n");
5029         ok(info->AuthorityCertSerialNumber.cbData == 0,
5030          "Expected no serial number\n");
5031         LocalFree(buf);
5032     }
5033     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5034      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5035      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5036     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5037     if (ret)
5038     {
5039         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5040 
5041         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5042          size);
5043         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5044         ok(info->AuthorityCertIssuer.cAltEntry == 1,
5045          "Expected 1 issuer entry, got %d\n",
5046          info->AuthorityCertIssuer.cAltEntry);
5047         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5048          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5049          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5050         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5051          url), "Unexpected URL\n");
5052         ok(info->AuthorityCertSerialNumber.cbData == 0,
5053          "Expected no serial number\n");
5054         LocalFree(buf);
5055     }
5056     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5057      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5058      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5059     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5060     if (ret)
5061     {
5062         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5063 
5064         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5065          size);
5066         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5067         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5068          "Expected no issuer name entries\n");
5069         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5070          "Unexpected serial number len\n");
5071         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5072          sizeof(serialNum)), "Unexpected serial number\n");
5073         LocalFree(buf);
5074     }
5075 }
5076 
5077 static const BYTE authorityInfoAccessWithUrl[] = {
5078 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5079 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5080 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5081 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5082 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5083 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5084 
5085 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5086 {
5087     static char oid1[] = "1.2.3";
5088     static char oid2[] = "1.5.6";
5089     BOOL ret;
5090     BYTE *buf = NULL;
5091     DWORD size = 0;
5092     CERT_ACCESS_DESCRIPTION accessDescription[2];
5093     CERT_AUTHORITY_INFO_ACCESS aia;
5094 
5095     memset(accessDescription, 0, sizeof(accessDescription));
5096     aia.cAccDescr = 0;
5097     aia.rgAccDescr = NULL;
5098     /* Having no access descriptions is allowed */
5099     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5100      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5101     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5102     if (ret)
5103     {
5104         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5105         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5106         LocalFree(buf);
5107         buf = NULL;
5108     }
5109     /* It can't have an empty access method */
5110     aia.cAccDescr = 1;
5111     aia.rgAccDescr = accessDescription;
5112     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5113      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5114     ok(!ret && (GetLastError() == E_INVALIDARG ||
5115      GetLastError() == OSS_LIMITED /* Win9x */),
5116      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5117     /* It can't have an empty location */
5118     accessDescription[0].pszAccessMethod = oid1;
5119     SetLastError(0xdeadbeef);
5120     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5121      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5122     ok(!ret && GetLastError() == E_INVALIDARG,
5123      "expected E_INVALIDARG, got %08x\n", GetLastError());
5124     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5125     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5126     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5127      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5128     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5129     if (ret)
5130     {
5131         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5132          size);
5133         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5134          "unexpected value\n");
5135         LocalFree(buf);
5136         buf = NULL;
5137     }
5138     accessDescription[1].pszAccessMethod = oid2;
5139     accessDescription[1].AccessLocation.dwAltNameChoice =
5140      CERT_ALT_NAME_IP_ADDRESS;
5141     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5142      sizeof(encodedIPAddr);
5143     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5144      (LPBYTE)encodedIPAddr;
5145     aia.cAccDescr = 2;
5146     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5147      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5148     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5149     if (ret)
5150     {
5151         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5152          "unexpected size %d\n", size);
5153         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5154          "unexpected value\n");
5155         LocalFree(buf);
5156         buf = NULL;
5157     }
5158 }
5159 
5160 static void compareAuthorityInfoAccess(LPCSTR header,
5161  const CERT_AUTHORITY_INFO_ACCESS *expected,
5162  const CERT_AUTHORITY_INFO_ACCESS *got)
5163 {
5164     DWORD i;
5165 
5166     ok(expected->cAccDescr == got->cAccDescr,
5167      "%s: expected %d access descriptions, got %d\n", header,
5168      expected->cAccDescr, got->cAccDescr);
5169     for (i = 0; i < expected->cAccDescr; i++)
5170     {
5171         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5172          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5173          header, i, expected->rgAccDescr[i].pszAccessMethod,
5174          got->rgAccDescr[i].pszAccessMethod);
5175         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5176          &got->rgAccDescr[i].AccessLocation);
5177     }
5178 }
5179 
5180 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5181 {
5182     static char oid1[] = "1.2.3";
5183     static char oid2[] = "1.5.6";
5184     BOOL ret;
5185     LPBYTE buf = NULL;
5186     DWORD size = 0;
5187 
5188     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5189      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5190      &buf, &size);
5191     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5192     if (ret)
5193     {
5194         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5195 
5196         compareAuthorityInfoAccess("empty AIA", &aia,
5197          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5198         LocalFree(buf);
5199         buf = NULL;
5200     }
5201     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5202      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5203      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5204     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5205     if (ret)
5206     {
5207         CERT_ACCESS_DESCRIPTION accessDescription;
5208         CERT_AUTHORITY_INFO_ACCESS aia;
5209 
5210         accessDescription.pszAccessMethod = oid1;
5211         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5212         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5213         aia.cAccDescr = 1;
5214         aia.rgAccDescr = &accessDescription;
5215         compareAuthorityInfoAccess("AIA with URL", &aia,
5216          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5217         LocalFree(buf);
5218         buf = NULL;
5219     }
5220     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5221      authorityInfoAccessWithUrlAndIPAddr,
5222      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5223      NULL, &buf, &size);
5224     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5225     if (ret)
5226     {
5227         CERT_ACCESS_DESCRIPTION accessDescription[2];
5228         CERT_AUTHORITY_INFO_ACCESS aia;
5229 
5230         accessDescription[0].pszAccessMethod = oid1;
5231         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5232         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5233         accessDescription[1].pszAccessMethod = oid2;
5234         accessDescription[1].AccessLocation.dwAltNameChoice =
5235          CERT_ALT_NAME_IP_ADDRESS;
5236         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5237          sizeof(encodedIPAddr);
5238         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5239          (LPBYTE)encodedIPAddr;
5240         aia.cAccDescr = 2;
5241         aia.rgAccDescr = accessDescription;
5242         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5243          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5244         LocalFree(buf);
5245         buf = NULL;
5246     }
5247     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5248      authorityInfoAccessWithUrlAndIPAddr,
5249      sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, NULL, &size);
5250     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5251     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
5252     if (buf)
5253     {
5254         ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5255          authorityInfoAccessWithUrlAndIPAddr,
5256          sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, buf, &size);
5257         ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5258         HeapFree(GetProcessHeap(), 0, buf);
5259     }
5260 }
5261 
5262 static const BYTE emptyCTL[] = {
5263 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5264 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5265 static const BYTE emptyCTLWithVersion1[] = {
5266 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5267 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5268 static const BYTE ctlWithUsageIdentifier[] = {
5269 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5270 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5271 static const BYTE ctlWithListIdentifier[] = {
5272 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5273 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5274 static const BYTE ctlWithSequenceNumber[] = {
5275 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5276 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5277 static const BYTE ctlWithThisUpdate[] = {
5278 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5279 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5280 static const BYTE ctlWithThisAndNextUpdate[] = {
5281 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5282 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5283 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5284 static const BYTE ctlWithAlgId[] = {
5285 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5286 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5287 static const BYTE ctlWithBogusEntry[] = {
5288 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5289 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5290 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5291 static const BYTE ctlWithOneEntry[] = {
5292 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5293 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5294 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5295 static const BYTE ctlWithTwoEntries[] = {
5296 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5297 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5298 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5299 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5300 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5301 
5302 static void test_encodeCTL(DWORD dwEncoding)
5303 {
5304     static char oid1[] = "1.2.3";
5305     static char oid2[] = "1.5.6";
5306     char *pOid1 = oid1;
5307     BOOL ret;
5308     BYTE *buf = NULL;
5309     DWORD size = 0;
5310     CTL_INFO info;
5311     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5312     CTL_ENTRY ctlEntry[2];
5313     CRYPT_ATTRIBUTE attr1, attr2;
5314     CRYPT_ATTR_BLOB value1, value2;
5315 
5316     memset(&info, 0, sizeof(info));
5317     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5318      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5319     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5320     if (ret)
5321     {
5322         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5323         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5324         LocalFree(buf);
5325         buf = NULL;
5326     }
5327     info.dwVersion = 1;
5328     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5329      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5330     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5331     if (ret)
5332     {
5333         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5334         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5335         LocalFree(buf);
5336         buf = NULL;
5337     }
5338     info.dwVersion = 0;
5339     info.SubjectUsage.cUsageIdentifier = 1;
5340     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5341     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5342      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5343     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5344     if (ret)
5345     {
5346         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5347          size);
5348         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5349         LocalFree(buf);
5350         buf = NULL;
5351     }
5352     info.SubjectUsage.cUsageIdentifier = 0;
5353     info.ListIdentifier.cbData = sizeof(serialNum);
5354     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5355     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5356      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5357     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5358     if (ret)
5359     {
5360         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5361         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5362         LocalFree(buf);
5363         buf = NULL;
5364     }
5365     info.ListIdentifier.cbData = 0;
5366     info.SequenceNumber.cbData = sizeof(serialNum);
5367     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5368     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5369      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5370     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5371     if (ret)
5372     {
5373         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5374          size);
5375         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5376         LocalFree(buf);
5377         buf = NULL;
5378     }
5379     info.SequenceNumber.cbData = 0;
5380     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5381     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5382      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5383     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5384     if (ret)
5385     {
5386         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5387         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5388         LocalFree(buf);
5389         buf = NULL;
5390     }
5391     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5392     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5393      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5394     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5395     if (ret)
5396     {
5397         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5398          size);
5399         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5400         LocalFree(buf);
5401         buf = NULL;
5402     }
5403     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5404     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5405     info.SubjectAlgorithm.pszObjId = oid2;
5406     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5407      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5408     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5409     if (ret)
5410     {
5411         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5412         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5413         LocalFree(buf);
5414         buf = NULL;
5415     }
5416     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5417      * (see tests below) but it'll encode fine.
5418      */
5419     info.SubjectAlgorithm.pszObjId = NULL;
5420     value1.cbData = sizeof(serialNum);
5421     value1.pbData = (LPBYTE)serialNum;
5422     attr1.pszObjId = oid1;
5423     attr1.cValue = 1;
5424     attr1.rgValue = &value1;
5425     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5426     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5427     ctlEntry[0].cAttribute = 1;
5428     ctlEntry[0].rgAttribute = &attr1;
5429     info.cCTLEntry = 1;
5430     info.rgCTLEntry = ctlEntry;
5431     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5432      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5433     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5434     if (ret)
5435     {
5436         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5437         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5438         LocalFree(buf);
5439         buf = NULL;
5440     }
5441     value1.cbData = sizeof(emptySequence);
5442     value1.pbData = (LPBYTE)emptySequence;
5443     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5444      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5445     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5446     if (ret)
5447     {
5448         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5449         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5450         LocalFree(buf);
5451         buf = NULL;
5452     }
5453     value2.cbData = sizeof(encodedIPAddr);
5454     value2.pbData = (LPBYTE)encodedIPAddr;
5455     attr2.pszObjId = oid2;
5456     attr2.cValue = 1;
5457     attr2.rgValue = &value2;
5458     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5459     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5460     ctlEntry[1].cAttribute = 1;
5461     ctlEntry[1].rgAttribute = &attr2;
5462     info.cCTLEntry = 2;
5463     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5464      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5465     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5466     if (ret)
5467     {
5468         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5469         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5470         LocalFree(buf);
5471         buf = NULL;
5472     }
5473 }
5474 
5475 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5476  const CTL_INFO *got)
5477 {
5478     DWORD i, j, k;
5479 
5480     ok(expected->dwVersion == got->dwVersion,
5481      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5482      got->dwVersion);
5483     ok(expected->SubjectUsage.cUsageIdentifier ==
5484      got->SubjectUsage.cUsageIdentifier,
5485      "%s: expected %d usage identifiers, got %d\n", header,
5486      expected->SubjectUsage.cUsageIdentifier,
5487      got->SubjectUsage.cUsageIdentifier);
5488     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5489         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5490          got->SubjectUsage.rgpszUsageIdentifier[i]),
5491          "%s[%d]: expected %s, got %s\n", header, i,
5492          expected->SubjectUsage.rgpszUsageIdentifier[i],
5493          got->SubjectUsage.rgpszUsageIdentifier[i]);
5494     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5495      "%s: expected list identifier of %d bytes, got %d\n", header,
5496      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5497     if (expected->ListIdentifier.cbData)
5498         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5499          expected->ListIdentifier.cbData),
5500          "%s: unexpected list identifier value\n", header);
5501     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5502      "%s: expected sequence number of %d bytes, got %d\n", header,
5503      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5504     if (expected->SequenceNumber.cbData)
5505         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5506          expected->SequenceNumber.cbData),
5507          "%s: unexpected sequence number value\n", header);
5508     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5509      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5510      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5511      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5512     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5513      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5514      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5515      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5516     if (expected->SubjectAlgorithm.pszObjId &&
5517      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5518         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5519          expected->SubjectAlgorithm.pszObjId);
5520     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5521         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5522          got->SubjectAlgorithm.pszObjId),
5523          "%s: expected subject algorithm %s, got %s\n", header,
5524          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5525     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5526      got->SubjectAlgorithm.Parameters.cbData,
5527      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5528      expected->SubjectAlgorithm.Parameters.cbData,
5529      got->SubjectAlgorithm.Parameters.cbData);
5530     if (expected->SubjectAlgorithm.Parameters.cbData)
5531         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5532          got->SubjectAlgorithm.Parameters.pbData,
5533          expected->SubjectAlgorithm.Parameters.cbData),
5534          "%s: unexpected subject algorithm parameter value\n", header);
5535     ok(expected->cCTLEntry == got->cCTLEntry,
5536      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5537      got->cCTLEntry);
5538     for (i = 0; i < expected->cCTLEntry; i++)
5539     {
5540         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5541          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5542          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5543          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5544          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5545         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5546             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5547              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5548              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5549              "%s[%d]: unexpected subject identifier value\n",
5550              header, i);
5551         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5552         {
5553             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5554              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5555              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5556              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5557              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5558             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5559             {
5560                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5561                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5562                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5563                  header, i, j, k,
5564                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5565                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5566                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5567                     ok(!memcmp(
5568                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5569                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5570                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5571                      "%s[%d][%d][%d]: unexpected value\n",
5572                      header, i, j, k);
5573             }
5574         }
5575     }
5576     ok(expected->cExtension == got->cExtension,
5577      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5578      got->cExtension);
5579     for (i = 0; i < expected->cExtension; i++)
5580     {
5581         ok(!strcmp(expected->rgExtension[i].pszObjId,
5582          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5583          header, i, expected->rgExtension[i].pszObjId,
5584          got->rgExtension[i].pszObjId);
5585         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5586          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5587          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5588         ok(expected->rgExtension[i].Value.cbData ==
5589          got->rgExtension[i].Value.cbData,
5590          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5591          header, i, expected->rgExtension[i].Value.cbData,
5592          got->rgExtension[i].Value.cbData);
5593         if (expected->rgExtension[i].Value.cbData)
5594             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5595              got->rgExtension[i].Value.pbData,
5596              expected->rgExtension[i].Value.cbData),
5597              "%s[%d]: unexpected extension value\n", header, i);
5598     }
5599 }
5600 
5601 static const BYTE signedCTL[] = {
5602 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5603 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5604 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5605 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5606 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5607 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5608 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5609 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5610 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5611 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5612 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5613 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5614 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5615 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5616 static const BYTE signedCTLWithCTLInnerContent[] = {
5617 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5618 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5619 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5620 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5621 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5622 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5623 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5624 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5625 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5626 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5627 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5628 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5629 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5630 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5631 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5632 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5633 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5634 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5635 0x57,0x6c,0x0b,0x47,0xb8 };
5636 
5637 static void test_decodeCTL(DWORD dwEncoding)
5638 {
5639     static char oid1[] = "1.2.3";
5640     static char oid2[] = "1.5.6";
5641     static BYTE nullData[] = { 5,0 };
5642     char *pOid1 = oid1;
5643     BOOL ret;
5644     BYTE *buf = NULL;
5645     DWORD size = 0;
5646     CTL_INFO info;
5647     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5648     CTL_ENTRY ctlEntry[2];
5649     CRYPT_ATTRIBUTE attr1, attr2;
5650     CRYPT_ATTR_BLOB value1, value2;
5651 
5652     memset(&info, 0, sizeof(info));
5653     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5654      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5655     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5656     if (ret)
5657     {
5658         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5659         LocalFree(buf);
5660         buf = NULL;
5661     }
5662     info.dwVersion = 1;
5663     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5664      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5665      &size);
5666     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5667     if (ret)
5668     {
5669         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5670         LocalFree(buf);
5671         buf = NULL;
5672     }
5673     info.dwVersion = 0;
5674     info.SubjectUsage.cUsageIdentifier = 1;
5675     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5676     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5677      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5678      &buf, &size);
5679     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5680     if (ret)
5681     {
5682         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5683         LocalFree(buf);
5684         buf = NULL;
5685     }
5686     info.SubjectUsage.cUsageIdentifier = 0;
5687     info.ListIdentifier.cbData = sizeof(serialNum);
5688     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5689     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5690      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5691     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5692     if (ret)
5693     {
5694         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5695         LocalFree(buf);
5696         buf = NULL;
5697     }
5698     info.ListIdentifier.cbData = 0;
5699     info.SequenceNumber.cbData = sizeof(serialNum);
5700     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5701     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5702      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5703     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5704     if (ret)
5705     {
5706         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5707         LocalFree(buf);
5708         buf = NULL;
5709     }
5710     info.SequenceNumber.cbData = 0;
5711     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5712     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5713      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5714     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5715     if (ret)
5716     {
5717         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5718         LocalFree(buf);
5719         buf = NULL;
5720     }
5721     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5722     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5723      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5724      &buf, &size);
5725     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5726     if (ret)
5727     {
5728         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5729         LocalFree(buf);
5730         buf = NULL;
5731     }
5732     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5733     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5734     info.SubjectAlgorithm.pszObjId = oid2;
5735     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5736     info.SubjectAlgorithm.Parameters.pbData = nullData;
5737     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5738      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5739     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5740     if (ret)
5741     {
5742         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5743         LocalFree(buf);
5744         buf = NULL;
5745     }
5746     SetLastError(0xdeadbeef);
5747     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5748      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5749     ok(!ret &&
5750      (GetLastError() == CRYPT_E_ASN1_EOD ||
5751       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5752       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5753      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5754      GetLastError());
5755     info.SubjectAlgorithm.Parameters.cbData = 0;
5756     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5757     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5758     info.SubjectAlgorithm.pszObjId = NULL;
5759     value1.cbData = sizeof(emptySequence);
5760     value1.pbData = (LPBYTE)emptySequence;
5761     attr1.pszObjId = oid1;
5762     attr1.cValue = 1;
5763     attr1.rgValue = &value1;
5764     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5765     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5766     ctlEntry[0].cAttribute = 1;
5767     ctlEntry[0].rgAttribute = &attr1;
5768     info.cCTLEntry = 1;
5769     info.rgCTLEntry = ctlEntry;
5770     SetLastError(0xdeadbeef);
5771     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5772      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5773     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5774     if (ret)
5775     {
5776         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5777         LocalFree(buf);
5778         buf = NULL;
5779     }
5780     value2.cbData = sizeof(encodedIPAddr);
5781     value2.pbData = (LPBYTE)encodedIPAddr;
5782     attr2.pszObjId = oid2;
5783     attr2.cValue = 1;
5784     attr2.rgValue = &value2;
5785     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5786     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5787     ctlEntry[1].cAttribute = 1;
5788     ctlEntry[1].rgAttribute = &attr2;
5789     info.cCTLEntry = 2;
5790     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5791      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5792     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5793     if (ret)
5794     {
5795         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5796         LocalFree(buf);
5797         buf = NULL;
5798     }
5799     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5800     SetLastError(0xdeadbeef);
5801     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5802      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5803     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5804      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5805      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5806      GetLastError());
5807     SetLastError(0xdeadbeef);
5808     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5809      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5810      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5811     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5812      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5813      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5814      GetLastError());
5815 }
5816 
5817 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5818 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5819  0x03,0,0,0,0,0,0 };
5820 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5821  0xa0,0x01,0x01 };
5822 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5823  0x03,0x02,0x01,0x01 };
5824 static BYTE bogusDER[] = { 1 };
5825 
5826 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5827 {
5828     BOOL ret;
5829     BYTE *buf = NULL;
5830     DWORD size = 0;
5831     CRYPT_CONTENT_INFO info = { 0 };
5832     char oid1[] = "1.2.3";
5833 
5834     if (0)
5835     {
5836         /* Crashes on win9x */
5837         SetLastError(0xdeadbeef);
5838         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5839          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5840         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5841          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5842     }
5843     SetLastError(0xdeadbeef);
5844     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5845      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5846     ok(!ret && (GetLastError() == E_INVALIDARG ||
5847      GetLastError() == OSS_LIMITED /* Win9x */),
5848      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5849     info.pszObjId = oid1;
5850     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5851      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5852     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5853     if (ret)
5854     {
5855         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5856         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5857         LocalFree(buf);
5858     }
5859     info.Content.pbData = bogusDER;
5860     info.Content.cbData = sizeof(bogusDER);
5861     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5862      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5863     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5864     if (ret)
5865     {
5866         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5867         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5868         LocalFree(buf);
5869     }
5870     info.Content.pbData = (BYTE *)ints[0].encoded;
5871     info.Content.cbData = ints[0].encoded[1] + 2;
5872     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5873      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5874     if (ret)
5875     {
5876         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5877         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5878         LocalFree(buf);
5879     }
5880 }
5881 
5882 static const BYTE indefiniteSignedPKCSContent[] = {
5883 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5884 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5885 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5886 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5887 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5888 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5889 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5890 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5891 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5892 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5893 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5894 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5895 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5896 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5897 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5898 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5899 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5900 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5901 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5902 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5903 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5904 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5905 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5906 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5907 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5908 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5909 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5910 0x00,0x00,0x00,0x00,0x00,0x00 };
5911 
5912 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5913 {
5914     BOOL ret;
5915     LPBYTE buf = NULL;
5916     DWORD size = 0;
5917     CRYPT_CONTENT_INFO *info;
5918 
5919     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5920      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5921      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5922     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5923     if (ret)
5924     {
5925         info = (CRYPT_CONTENT_INFO *)buf;
5926 
5927         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5928          info->pszObjId);
5929         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5930          info->Content.cbData);
5931         LocalFree(buf);
5932     }
5933     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5934      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5935      0, NULL, NULL, &size);
5936     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5937     SetLastError(0xdeadbeef);
5938     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5939      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5940      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5941     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5942      * I doubt an app depends on that.
5943      */
5944     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5945      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5946      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5947      GetLastError());
5948     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5949      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5950      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5951     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5952     if (ret)
5953     {
5954         info = (CRYPT_CONTENT_INFO *)buf;
5955 
5956         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5957          info->pszObjId);
5958         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5959          "Unexpected size %d\n", info->Content.cbData);
5960         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5961          info->Content.cbData), "Unexpected value\n");
5962         LocalFree(buf);
5963     }
5964     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5965      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5966      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5967     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5968     if (ret)
5969     {
5970         info = (CRYPT_CONTENT_INFO *)buf;
5971 
5972         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5973          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5974         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5975          info->Content.cbData);
5976         LocalFree(buf);
5977     }
5978 }
5979 
5980 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5981  0x00 };
5982 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5983  0x01 };
5984 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5985  0x02,0x01,0x01 };
5986 
5987 static void test_encodePKCSAttribute(DWORD dwEncoding)
5988 {
5989     CRYPT_ATTRIBUTE attr = { 0 };
5990     BOOL ret;
5991     LPBYTE buf = NULL;
5992     DWORD size = 0;
5993     CRYPT_ATTR_BLOB blob;
5994     char oid[] = "1.2.3";
5995 
5996     if (0)
5997     {
5998         /* Crashes on win9x */
5999         SetLastError(0xdeadbeef);
6000         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
6001          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6002         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
6003          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
6004     }
6005     SetLastError(0xdeadbeef);
6006     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6007      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6008     ok(!ret && (GetLastError() == E_INVALIDARG ||
6009      GetLastError() == OSS_LIMITED /* Win9x */),
6010      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
6011     attr.pszObjId = oid;
6012     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6013      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6014     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6015     if (ret)
6016     {
6017         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
6018         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
6019         LocalFree(buf);
6020     }
6021     blob.cbData = sizeof(bogusDER);
6022     blob.pbData = bogusDER;
6023     attr.cValue = 1;
6024     attr.rgValue = &blob;
6025     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6026      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6027     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6028     if (ret)
6029     {
6030         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
6031         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6032         LocalFree(buf);
6033     }
6034     blob.pbData = (BYTE *)ints[0].encoded;
6035     blob.cbData = ints[0].encoded[1] + 2;
6036     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6037      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6038     if (ret)
6039     {
6040         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6041         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6042         LocalFree(buf);
6043     }
6044 }
6045 
6046 static void test_decodePKCSAttribute(DWORD dwEncoding)
6047 {
6048     BOOL ret;
6049     LPBYTE buf = NULL;
6050     DWORD size = 0;
6051     CRYPT_ATTRIBUTE *attr;
6052 
6053     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6054      emptyPKCSAttr, sizeof(emptyPKCSAttr),
6055      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6056     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6057     if (ret)
6058     {
6059         attr = (CRYPT_ATTRIBUTE *)buf;
6060 
6061         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6062          attr->pszObjId);
6063         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6064         LocalFree(buf);
6065     }
6066     SetLastError(0xdeadbeef);
6067     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6068      bogusPKCSAttr, sizeof(bogusPKCSAttr),
6069      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6070     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6071      * I doubt an app depends on that.
6072      */
6073     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6074      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6075      GetLastError() == OSS_MORE_INPUT /* Win9x */),
6076      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6077      GetLastError());
6078     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6079      intPKCSAttr, sizeof(intPKCSAttr),
6080      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6081     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6082     if (ret)
6083     {
6084         attr = (CRYPT_ATTRIBUTE *)buf;
6085 
6086         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6087          attr->pszObjId);
6088         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6089         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6090          "Unexpected size %d\n", attr->rgValue[0].cbData);
6091         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6092          attr->rgValue[0].cbData), "Unexpected value\n");
6093         LocalFree(buf);
6094     }
6095 }
6096 
6097 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6098 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6099  0x2a,0x03,0x31,0x00 };
6100 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6101  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6102 
6103 static void test_encodePKCSAttributes(DWORD dwEncoding)
6104 {
6105     CRYPT_ATTRIBUTES attributes = { 0 };
6106     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6107     CRYPT_ATTR_BLOB blob;
6108     BOOL ret;
6109     LPBYTE buf = NULL;
6110     DWORD size = 0;
6111     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6112 
6113     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6114      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6115     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6116     if (ret)
6117     {
6118         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6119         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6120         LocalFree(buf);
6121     }
6122     attributes.cAttr = 1;
6123     attributes.rgAttr = attr;
6124     SetLastError(0xdeadbeef);
6125     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6126      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6127     ok(!ret && (GetLastError() == E_INVALIDARG ||
6128      GetLastError() == OSS_LIMITED /* Win9x */),
6129      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6130     attr[0].pszObjId = oid1;
6131     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6132      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6133     if (ret)
6134     {
6135         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6136         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6137         LocalFree(buf);
6138     }
6139     attr[1].pszObjId = oid2;
6140     attr[1].cValue = 1;
6141     attr[1].rgValue = &blob;
6142     blob.pbData = (BYTE *)ints[0].encoded;
6143     blob.cbData = ints[0].encoded[1] + 2;
6144     attributes.cAttr = 2;
6145     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6146      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6147     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6148     if (ret)
6149     {
6150         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6151         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6152         LocalFree(buf);
6153     }
6154 }
6155 
6156 static void test_decodePKCSAttributes(DWORD dwEncoding)
6157 {
6158     BOOL ret;
6159     LPBYTE buf = NULL;
6160     DWORD size = 0;
6161     CRYPT_ATTRIBUTES *attributes;
6162 
6163     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6164      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6165      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6166     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6167     if (ret)
6168     {
6169         attributes = (CRYPT_ATTRIBUTES *)buf;
6170         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6171          attributes->cAttr);
6172         LocalFree(buf);
6173     }
6174     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6175      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6176      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6177     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6178     if (ret)
6179     {
6180         attributes = (CRYPT_ATTRIBUTES *)buf;
6181         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6182          attributes->cAttr);
6183         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6184          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6185         ok(attributes->rgAttr[0].cValue == 0,
6186          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6187         LocalFree(buf);
6188     }
6189     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6190      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6191      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6192     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6193     if (ret)
6194     {
6195         attributes = (CRYPT_ATTRIBUTES *)buf;
6196         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6197          attributes->cAttr);
6198         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6199          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6200         ok(attributes->rgAttr[0].cValue == 0,
6201          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6202         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6203          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6204         ok(attributes->rgAttr[1].cValue == 1,
6205          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6206         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6207          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6208         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6209          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6210         LocalFree(buf);
6211     }
6212     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6213      doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, NULL, &size);
6214     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6215     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6216     if (buf)
6217     {
6218         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6219          doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, buf, &size);
6220         ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6221         HeapFree(GetProcessHeap(), 0, buf);
6222     }
6223 }
6224 
6225 static const BYTE singleCapability[] = {
6226 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6227 static const BYTE twoCapabilities[] = {
6228 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6229 static const BYTE singleCapabilitywithNULL[] = {
6230 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6231 
6232 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6233 {
6234     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6235     BOOL ret;
6236     LPBYTE buf = NULL;
6237     DWORD size = 0;
6238     CRYPT_SMIME_CAPABILITY capability[2];
6239     CRYPT_SMIME_CAPABILITIES capabilities;
6240 
6241     /* An empty capabilities is allowed */
6242     capabilities.cCapability = 0;
6243     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6244      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6245     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6246     if (ret)
6247     {
6248         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6249         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6250         LocalFree(buf);
6251     }
6252     /* A non-empty capabilities with an empty capability (lacking an OID) is
6253      * not allowed
6254      */
6255     capability[0].pszObjId = NULL;
6256     capability[0].Parameters.cbData = 0;
6257     capabilities.cCapability = 1;
6258     capabilities.rgCapability = capability;
6259     SetLastError(0xdeadbeef);
6260     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6261      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6262     ok(!ret && (GetLastError() == E_INVALIDARG ||
6263      GetLastError() == OSS_LIMITED /* Win9x */),
6264      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6265     capability[0].pszObjId = oid1;
6266     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6267      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6268     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6269     if (ret)
6270     {
6271         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6272         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6273         LocalFree(buf);
6274     }
6275     capability[1].pszObjId = oid2;
6276     capability[1].Parameters.cbData = 0;
6277     capabilities.cCapability = 2;
6278     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6279      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6280     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6281     if (ret)
6282     {
6283         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6284         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6285         LocalFree(buf);
6286     }
6287 }
6288 
6289 static void compareSMimeCapabilities(LPCSTR header,
6290  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6291 {
6292     DWORD i;
6293 
6294     ok(got->cCapability == expected->cCapability,
6295      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6296      got->cCapability);
6297     for (i = 0; i < expected->cCapability; i++)
6298     {
6299         ok(!strcmp(expected->rgCapability[i].pszObjId,
6300          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6301          header, i, expected->rgCapability[i].pszObjId,
6302          got->rgCapability[i].pszObjId);
6303         ok(expected->rgCapability[i].Parameters.cbData ==
6304          got->rgCapability[i].Parameters.cbData,
6305          "%s[%d]: expected %d bytes, got %d\n", header, i,
6306          expected->rgCapability[i].Parameters.cbData,
6307          got->rgCapability[i].Parameters.cbData);
6308         if (expected->rgCapability[i].Parameters.cbData)
6309             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6310              got->rgCapability[i].Parameters.pbData,
6311              expected->rgCapability[i].Parameters.cbData),
6312              "%s[%d]: unexpected value\n", header, i);
6313     }
6314 }
6315 
6316 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6317 {
6318     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6319     BOOL ret;
6320     DWORD size = 0;
6321     CRYPT_SMIME_CAPABILITY capability[2];
6322     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6323 
6324     SetLastError(0xdeadbeef);
6325     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6326      emptySequence, sizeof(emptySequence),
6327      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6329     if (ret)
6330     {
6331         capabilities.cCapability = 0;
6332         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6333         LocalFree(ptr);
6334     }
6335     SetLastError(0xdeadbeef);
6336     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6337      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6338      &ptr, &size);
6339     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6340     if (ret)
6341     {
6342         capability[0].pszObjId = oid1;
6343         capability[0].Parameters.cbData = 0;
6344         capabilities.cCapability = 1;
6345         capabilities.rgCapability = capability;
6346         compareSMimeCapabilities("single capability", &capabilities, ptr);
6347         LocalFree(ptr);
6348     }
6349     SetLastError(0xdeadbeef);
6350     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6351      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6352      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6353     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6354     if (ret)
6355     {
6356         BYTE NULLparam[] = {0x05, 0x00};
6357         capability[0].pszObjId = oid1;
6358         capability[0].Parameters.cbData = 2;
6359         capability[0].Parameters.pbData = NULLparam;
6360         capabilities.cCapability = 1;
6361         capabilities.rgCapability = capability;
6362         compareSMimeCapabilities("single capability with NULL", &capabilities,
6363          ptr);
6364         LocalFree(ptr);
6365     }
6366     SetLastError(0xdeadbeef);
6367     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6368     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6369     &ptr, &size);
6370     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6371     if (ret)
6372     {
6373         capability[0].Parameters.cbData = 0;
6374         capability[1].pszObjId = oid2;
6375         capability[1].Parameters.cbData = 0;
6376         capabilities.cCapability = 2;
6377         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6378         LocalFree(ptr);
6379     }
6380     SetLastError(0xdeadbeef);
6381     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6382      twoCapabilities, sizeof(twoCapabilities), 0, NULL, NULL, &size);
6383     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6384     ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6385     if (ptr)
6386     {
6387         SetLastError(0xdeadbeef);
6388         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6389          twoCapabilities, sizeof(twoCapabilities), 0, NULL, ptr, &size);
6390         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6391         HeapFree(GetProcessHeap(), 0, ptr);
6392     }
6393 }
6394 
6395 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6396  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6397  0x67 };
6398 static const BYTE minimalPKCSSigner[] = {
6399  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6400  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6401  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6402 static const BYTE PKCSSignerWithSerial[] = {
6403  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6404  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6405  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6406  0x00 };
6407 static const BYTE PKCSSignerWithHashAlgo[] = {
6408  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6409  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6410  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6411  0x00,0x04,0x00 };
6412 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6413  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6414  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6415  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6416  0x06,0x05,0x00,0x04,0x00 };
6417 static const BYTE PKCSSignerWithHash[] = {
6418  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6419  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6420  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6421  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6422  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6423 static const BYTE PKCSSignerWithAuthAttr[] = {
6424 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6425 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6426 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6427 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6428 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6429 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6430 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6431 
6432 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6433 {
6434     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6435     BOOL ret;
6436     LPBYTE buf = NULL;
6437     DWORD size = 0;
6438     CMSG_SIGNER_INFO info = { 0 };
6439     char oid_common_name[] = szOID_COMMON_NAME;
6440     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6441      (LPBYTE)encodedCommonName };
6442     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6443 
6444     SetLastError(0xdeadbeef);
6445     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6446      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6447     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6448     {
6449         skip("no PKCS7_SIGNER_INFO encode support\n");
6450         return;
6451     }
6452     ok(!ret && (GetLastError() == E_INVALIDARG ||
6453      GetLastError() == OSS_LIMITED /* Win9x */),
6454      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6455     /* To be encoded, a signer must have an issuer at least, and the encoding
6456      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6457      * see decoding tests.)
6458      */
6459     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6460     info.Issuer.pbData = encodedCommonNameNoNull;
6461     SetLastError(0xdeadbeef);
6462     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6463      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6464     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6465         ok(!ret && GetLastError() == E_INVALIDARG,
6466          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6467     else
6468     {
6469         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6470          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6471         if (ret)
6472         {
6473             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6474             if (size == sizeof(minimalPKCSSigner))
6475                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6476             else
6477                 ok(0, "Unexpected value\n");
6478             LocalFree(buf);
6479         }
6480     }
6481     info.SerialNumber.cbData = sizeof(serialNum);
6482     info.SerialNumber.pbData = (BYTE *)serialNum;
6483     SetLastError(0xdeadbeef);
6484     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6485      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6486     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6487         ok(!ret && GetLastError() == E_INVALIDARG,
6488          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6489     else
6490     {
6491         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6492          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6493         if (ret)
6494         {
6495             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6496              size);
6497             if (size == sizeof(PKCSSignerWithSerial))
6498                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6499                  "Unexpected value\n");
6500             else
6501                 ok(0, "Unexpected value\n");
6502             LocalFree(buf);
6503         }
6504     }
6505     info.HashAlgorithm.pszObjId = oid1;
6506     SetLastError(0xdeadbeef);
6507     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6508      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6509     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6510         ok(!ret && GetLastError() == E_INVALIDARG,
6511          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6512     else
6513     {
6514         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6515          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6516         if (ret)
6517         {
6518             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6519              size);
6520             if (size == sizeof(PKCSSignerWithHashAlgo))
6521                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6522                  "Unexpected value\n");
6523             else
6524                 ok(0, "Unexpected value\n");
6525             LocalFree(buf);
6526         }
6527     }
6528     info.HashEncryptionAlgorithm.pszObjId = oid2;
6529     SetLastError(0xdeadbeef);
6530     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6531      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6532     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6533         ok(!ret && GetLastError() == E_INVALIDARG,
6534          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6535     else
6536     {
6537         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6538         if (ret)
6539         {
6540             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6541              "Unexpected size %d\n", size);
6542             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6543                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6544                  "Unexpected value\n");
6545             else
6546                 ok(0, "Unexpected value\n");
6547             LocalFree(buf);
6548         }
6549     }
6550     info.EncryptedHash.cbData = sizeof(hash);
6551     info.EncryptedHash.pbData = (BYTE *)hash;
6552     SetLastError(0xdeadbeef);
6553     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6554      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6555     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6556         ok(!ret && GetLastError() == E_INVALIDARG,
6557          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6558     else
6559     {
6560         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6561         if (ret)
6562         {
6563             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6564              size);
6565             if (size == sizeof(PKCSSignerWithHash))
6566                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6567                  "Unexpected value\n");
6568             else
6569                 ok(0, "Unexpected value\n");
6570             LocalFree(buf);
6571         }
6572     }
6573     info.AuthAttrs.cAttr = 1;
6574     info.AuthAttrs.rgAttr = &attr;
6575     SetLastError(0xdeadbeef);
6576     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6577      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6578     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6579         ok(!ret && GetLastError() == E_INVALIDARG,
6580          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6581     else
6582     {
6583         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6584         if (ret)
6585         {
6586             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6587              size);
6588             if (size == sizeof(PKCSSignerWithAuthAttr))
6589                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6590                  "Unexpected value\n");
6591             else
6592                 ok(0, "Unexpected value\n");
6593             LocalFree(buf);
6594         }
6595     }
6596 }
6597 
6598 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6599 {
6600     BOOL ret;
6601     LPBYTE buf = NULL;
6602     DWORD size = 0;
6603     CMSG_SIGNER_INFO *info;
6604 
6605     /* A PKCS signer can't be decoded without a serial number. */
6606     SetLastError(0xdeadbeef);
6607     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6608      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6609      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6610     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6611      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6612      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6613      GetLastError());
6614     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6615      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6616      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6617     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6618      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6619     if (ret)
6620     {
6621         info = (CMSG_SIGNER_INFO *)buf;
6622         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6623          info->dwVersion);
6624         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6625          "Unexpected size %d\n", info->Issuer.cbData);
6626         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6627          info->Issuer.cbData), "Unexpected value\n");
6628         ok(info->SerialNumber.cbData == sizeof(serialNum),
6629          "Unexpected size %d\n", info->SerialNumber.cbData);
6630         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6631          "Unexpected value\n");
6632         LocalFree(buf);
6633     }
6634     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6635      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6636      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6637     if (ret)
6638     {
6639         info = (CMSG_SIGNER_INFO *)buf;
6640         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6641          info->dwVersion);
6642         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6643          "Unexpected size %d\n", info->Issuer.cbData);
6644         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6645          info->Issuer.cbData), "Unexpected value\n");
6646         ok(info->SerialNumber.cbData == sizeof(serialNum),
6647          "Unexpected size %d\n", info->SerialNumber.cbData);
6648         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6649          "Unexpected value\n");
6650         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6651          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6652         LocalFree(buf);
6653     }
6654     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6655      PKCSSignerWithHashAndEncryptionAlgo,
6656      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6657      NULL, &buf, &size);
6658     if (ret)
6659     {
6660         info = (CMSG_SIGNER_INFO *)buf;
6661         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6662          info->dwVersion);
6663         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6664          "Unexpected size %d\n", info->Issuer.cbData);
6665         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6666          info->Issuer.cbData), "Unexpected value\n");
6667         ok(info->SerialNumber.cbData == sizeof(serialNum),
6668          "Unexpected size %d\n", info->SerialNumber.cbData);
6669         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6670          "Unexpected value\n");
6671         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6672          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6673         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6674          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6675         LocalFree(buf);
6676     }
6677     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6678      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6679      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6680     if (ret)
6681     {
6682         info = (CMSG_SIGNER_INFO *)buf;
6683         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6684          info->dwVersion);
6685         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6686          "Unexpected size %d\n", info->Issuer.cbData);
6687         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6688          info->Issuer.cbData), "Unexpected value\n");
6689         ok(info->SerialNumber.cbData == sizeof(serialNum),
6690          "Unexpected size %d\n", info->SerialNumber.cbData);
6691         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6692          "Unexpected value\n");
6693         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6694          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6695         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6696          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6697         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6698          info->EncryptedHash.cbData);
6699         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6700          "Unexpected value\n");
6701         LocalFree(buf);
6702     }
6703     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6704      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6705      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6706     if (ret)
6707     {
6708         info = (CMSG_SIGNER_INFO *)buf;
6709         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6710          info->AuthAttrs.cAttr);
6711         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6712          "Expected %s, got %s\n", szOID_COMMON_NAME,
6713          info->AuthAttrs.rgAttr[0].pszObjId);
6714         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6715          info->AuthAttrs.rgAttr[0].cValue);
6716         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6717          sizeof(encodedCommonName), "Unexpected size %d\n",
6718          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6719         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6720          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6721         LocalFree(buf);
6722     }
6723 }
6724 
6725 static const BYTE CMSSignerWithKeyId[] = {
6726 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6727 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6728 
6729 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6730 {
6731     BOOL ret;
6732     LPBYTE buf = NULL;
6733     DWORD size = 0;
6734     CMSG_CMS_SIGNER_INFO info = { 0 };
6735     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6736 
6737     SetLastError(0xdeadbeef);
6738     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6739      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6740     ok(!ret, "Expected failure, got %d\n", ret);
6741     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6742     {
6743         skip("no CMS_SIGNER_INFO encode support\n");
6744         return;
6745     }
6746     ok(GetLastError() == E_INVALIDARG,
6747        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6748     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6749     SetLastError(0xdeadbeef);
6750     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6751      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6752     ok(!ret, "Expected failure, got %d\n", ret);
6753     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6754     {
6755         skip("no CMS_SIGNER_INFO encode support\n");
6756         return;
6757     }
6758     ok(GetLastError() == E_INVALIDARG,
6759        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6760     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6761      * be a key id or an issuer serial number with at least the issuer set, and
6762      * the encoding must include PKCS_7_ASN_ENCODING.
6763      * (That isn't enough to be decoded, see decoding tests.)
6764      */
6765     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6766      sizeof(encodedCommonNameNoNull);
6767     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6768     SetLastError(0xdeadbeef);
6769     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6770      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6771     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6772         ok(!ret && GetLastError() == E_INVALIDARG,
6773          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6774     else
6775     {
6776         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6777         if (ret)
6778         {
6779             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6780             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6781             LocalFree(buf);
6782         }
6783     }
6784     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6785     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6786     SetLastError(0xdeadbeef);
6787     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6788      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6789     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6790         ok(!ret && GetLastError() == E_INVALIDARG,
6791          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6792     else
6793     {
6794         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6795         if (ret)
6796         {
6797             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6798              size);
6799             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6800             LocalFree(buf);
6801         }
6802     }
6803     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6804     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6805     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6806     SetLastError(0xdeadbeef);
6807     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6808      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6809     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6810         ok(!ret && GetLastError() == E_INVALIDARG,
6811          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6812     else
6813     {
6814         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6815         if (ret)
6816         {
6817             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6818              size);
6819             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6820             LocalFree(buf);
6821         }
6822     }
6823     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6824      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6825      * (see RFC 3852, section 5.3.)
6826      */
6827     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6828     U(info.SignerId).HashId.cbData = sizeof(hash);
6829     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6830     SetLastError(0xdeadbeef);
6831     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6832      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6833     ok(!ret && GetLastError() == E_INVALIDARG,
6834      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6835     /* Now with a hash algo */
6836     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6837     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6838      sizeof(encodedCommonNameNoNull);
6839     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6840     info.HashAlgorithm.pszObjId = oid1;
6841     SetLastError(0xdeadbeef);
6842     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6843      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6844     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6845         ok(!ret && GetLastError() == E_INVALIDARG,
6846          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6847     else
6848     {
6849         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6850         if (ret)
6851         {
6852             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6853              size);
6854             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6855              "Unexpected value\n");
6856             LocalFree(buf);
6857         }
6858     }
6859     info.HashEncryptionAlgorithm.pszObjId = oid2;
6860     SetLastError(0xdeadbeef);
6861     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6862      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6863     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6864         ok(!ret && GetLastError() == E_INVALIDARG,
6865          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6866     else
6867     {
6868         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6869         if (ret)
6870         {
6871             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6872              "Unexpected size %d\n", size);
6873             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6874              "Unexpected value\n");
6875             LocalFree(buf);
6876         }
6877     }
6878     info.EncryptedHash.cbData = sizeof(hash);
6879     info.EncryptedHash.pbData = (BYTE *)hash;
6880     SetLastError(0xdeadbeef);
6881     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6882      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6883     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6884         ok(!ret && GetLastError() == E_INVALIDARG,
6885          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6886     else
6887     {
6888         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6889         if (ret)
6890         {
6891             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6892              size);
6893             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6894             LocalFree(buf);
6895         }
6896     }
6897 }
6898 
6899 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6900 {
6901     BOOL ret;
6902     LPBYTE buf = NULL;
6903     DWORD size = 0;
6904     CMSG_CMS_SIGNER_INFO *info;
6905     static const char oid1[] = "1.2.3", oid2[] = "1.5.6";
6906 
6907     /* A CMS signer can't be decoded without a serial number. */
6908     SetLastError(0xdeadbeef);
6909     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6910      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6911      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6912     ok(!ret, "expected failure\n");
6913     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6914     {
6915         skip("no CMS_SIGNER_INFO decode support\n");
6916         return;
6917     }
6918     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6919      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6920     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6921      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6922      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6923     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6924     if (ret)
6925     {
6926         info = (CMSG_CMS_SIGNER_INFO *)buf;
6927         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6928          info->dwVersion);
6929         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6930          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6931          info->SignerId.dwIdChoice);
6932         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6933          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6934          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6935         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6936          encodedCommonNameNoNull,
6937          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6938          "Unexpected value\n");
6939         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6940          sizeof(serialNum), "Unexpected size %d\n",
6941          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6942         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6943          serialNum, sizeof(serialNum)), "Unexpected value\n");
6944         LocalFree(buf);
6945     }
6946     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6947      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6948      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6949     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6950     if (ret)
6951     {
6952         info = (CMSG_CMS_SIGNER_INFO *)buf;
6953         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6954          info->dwVersion);
6955         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6956          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6957          info->SignerId.dwIdChoice);
6958         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6959          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6960          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6961         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6962          encodedCommonNameNoNull,
6963          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6964          "Unexpected value\n");
6965         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6966          sizeof(serialNum), "Unexpected size %d\n",
6967          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6968         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6969          serialNum, sizeof(serialNum)), "Unexpected value\n");
6970         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6971          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6972         LocalFree(buf);
6973     }
6974     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6975      PKCSSignerWithHashAndEncryptionAlgo,
6976      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6977      NULL, &buf, &size);
6978     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6979     if (ret)
6980     {
6981         info = (CMSG_CMS_SIGNER_INFO *)buf;
6982         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6983          info->dwVersion);
6984         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6985          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6986          info->SignerId.dwIdChoice);
6987         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6988          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6989          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6990         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6991          encodedCommonNameNoNull,
6992          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6993          "Unexpected value\n");
6994         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6995          sizeof(serialNum), "Unexpected size %d\n",
6996          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6997         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6998          serialNum, sizeof(serialNum)), "Unexpected value\n");
6999         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7000          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7001         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7002          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7003         LocalFree(buf);
7004     }
7005     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7006      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
7007      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7008     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7009     if (ret)
7010     {
7011         info = (CMSG_CMS_SIGNER_INFO *)buf;
7012         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7013          info->dwVersion);
7014         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7015          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7016          info->SignerId.dwIdChoice);
7017         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7018          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7019          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7020         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7021          encodedCommonNameNoNull,
7022          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7023          "Unexpected value\n");
7024         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7025          sizeof(serialNum), "Unexpected size %d\n",
7026          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7027         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7028          serialNum, sizeof(serialNum)), "Unexpected value\n");
7029         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7030          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7031         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7032          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7033         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
7034          info->EncryptedHash.cbData);
7035         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
7036          "Unexpected value\n");
7037         LocalFree(buf);
7038     }
7039     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7040      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
7041      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7042     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7043     if (ret)
7044     {
7045         info = (CMSG_CMS_SIGNER_INFO *)buf;
7046         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7047          info->dwVersion);
7048         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
7049          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
7050          info->SignerId.dwIdChoice);
7051         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
7052          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
7053         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
7054          "Unexpected value\n");
7055         LocalFree(buf);
7056     }
7057 }
7058 
7059 static BYTE emptyDNSPermittedConstraints[] = {
7060 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7061 static BYTE emptyDNSExcludedConstraints[] = {
7062 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7063 static BYTE DNSExcludedConstraints[] = {
7064 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7065 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7066 static BYTE permittedAndExcludedConstraints[] = {
7067 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7068 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7069 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7070 static BYTE permittedAndExcludedWithMinConstraints[] = {
7071 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7072 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7073 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7074 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7075 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7076 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7077 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7078 
7079 static void test_encodeNameConstraints(DWORD dwEncoding)
7080 {
7081     BOOL ret;
7082     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7083     CERT_GENERAL_SUBTREE permitted = { { 0 } };
7084     CERT_GENERAL_SUBTREE excluded = { { 0 } };
7085     LPBYTE buf;
7086     DWORD size;
7087 
7088     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7089      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7090     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7091     {
7092         skip("no X509_NAME_CONSTRAINTS encode support\n");
7093         return;
7094     }
7095     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7096     if (ret)
7097     {
7098         ok(size == sizeof(emptySequence), "Unexpected size\n");
7099         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7100         LocalFree(buf);
7101     }
7102     constraints.cPermittedSubtree = 1;
7103     constraints.rgPermittedSubtree = &permitted;
7104     SetLastError(0xdeadbeef);
7105     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7106      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7107     ok(!ret && GetLastError() == E_INVALIDARG,
7108      "Expected E_INVALIDARG, got %08x\n", GetLastError());
7109     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7110     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7111      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7112     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7113     if (ret)
7114     {
7115         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7116         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7117          "Unexpected value\n");
7118         LocalFree(buf);
7119     }
7120     constraints.cPermittedSubtree = 0;
7121     constraints.cExcludedSubtree = 1;
7122     constraints.rgExcludedSubtree = &excluded;
7123     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7124     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7125      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7126     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7127     if (ret)
7128     {
7129         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7130         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7131          "Unexpected value\n");
7132         LocalFree(buf);
7133     }
7134     U(excluded.Base).pwszURL = (LPWSTR)url;
7135     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7136      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7137     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7138     if (ret)
7139     {
7140         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7141         ok(!memcmp(buf, DNSExcludedConstraints, size),
7142          "Unexpected value\n");
7143         LocalFree(buf);
7144     }
7145     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7146     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7147     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7148     constraints.cPermittedSubtree = 1;
7149     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7150      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7151     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7152     if (ret)
7153     {
7154         ok(size == sizeof(permittedAndExcludedConstraints),
7155          "Unexpected size\n");
7156         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7157          "Unexpected value\n");
7158         LocalFree(buf);
7159     }
7160     permitted.dwMinimum = 5;
7161     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7162      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7163     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7164     if (ret)
7165     {
7166         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7167          "Unexpected size\n");
7168         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7169          "Unexpected value\n");
7170         LocalFree(buf);
7171     }
7172     permitted.fMaximum = TRUE;
7173     permitted.dwMaximum = 3;
7174     SetLastError(0xdeadbeef);
7175     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7176      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7177     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7178     if (ret)
7179     {
7180         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7181          "Unexpected size\n");
7182         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7183          "Unexpected value\n");
7184         LocalFree(buf);
7185     }
7186 }
7187 
7188 struct EncodedNameConstraints
7189 {
7190     CRYPT_DATA_BLOB            encoded;
7191     CERT_NAME_CONSTRAINTS_INFO constraints;
7192 };
7193 
7194 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7195  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7196 static CERT_GENERAL_SUBTREE DNSSubtree = {
7197  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7198 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7199  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7200 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7201  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7202 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7203  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7204 
7205 static const struct EncodedNameConstraints encodedNameConstraints[] = {
7206  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7207  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7208    { 1, &emptyDNSSubtree, 0, NULL } },
7209  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7210    { 0, NULL, 1, &emptyDNSSubtree } },
7211  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7212    { 0, NULL, 1, &DNSSubtree } },
7213  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7214    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7215  { { sizeof(permittedAndExcludedWithMinConstraints),
7216      permittedAndExcludedWithMinConstraints },
7217    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7218  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7219      permittedAndExcludedWithMinMaxConstraints },
7220    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7221 };
7222 
7223 static void test_decodeNameConstraints(DWORD dwEncoding)
7224 {
7225     BOOL ret;
7226     DWORD i;
7227     CERT_NAME_CONSTRAINTS_INFO *constraints;
7228 
7229     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7230     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7231     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7232     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7233     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7234     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7235     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7236     for (i = 0;
7237      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7238      i++)
7239     {
7240         DWORD size;
7241 
7242         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7243          encodedNameConstraints[i].encoded.pbData,
7244          encodedNameConstraints[i].encoded.cbData,
7245          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7246         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7247         {
7248             skip("no X509_NAME_CONSTRAINTS decode support\n");
7249             return;
7250         }
7251         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7252         if (ret)
7253         {
7254             DWORD j;
7255 
7256             if (constraints->cPermittedSubtree !=
7257              encodedNameConstraints[i].constraints.cPermittedSubtree)
7258                 fprintf(stderr, "%d: expected %u permitted, got %u\n", i,
7259                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7260                  constraints->cPermittedSubtree);
7261             if (constraints->cPermittedSubtree ==
7262              encodedNameConstraints[i].constraints.cPermittedSubtree)
7263             {
7264                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7265                 {
7266                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7267                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7268                 }
7269             }
7270             if (constraints->cExcludedSubtree !=
7271              encodedNameConstraints[i].constraints.cExcludedSubtree)
7272                 fprintf(stderr, "%d: expected %u excluded, got %u\n", i,
7273                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7274                  constraints->cExcludedSubtree);
7275             if (constraints->cExcludedSubtree ==
7276              encodedNameConstraints[i].constraints.cExcludedSubtree)
7277             {
7278                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7279                 {
7280                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7281                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7282                 }
7283             }
7284             LocalFree(constraints);
7285         }
7286     }
7287 }
7288 
7289 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7290  'n','o','t','i','c','e',0 };
7291 static const BYTE noticeWithDisplayText[] = {
7292  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7293  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7294  0x00,0x69,0x00,0x63,0x00,0x65
7295 };
7296 static char org[] = "Wine";
7297 static int noticeNumbers[] = { 2,3 };
7298 static BYTE noticeWithReference[] = {
7299  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7300  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7301  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7302  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7303 };
7304 
7305 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7306 {
7307     BOOL ret;
7308     LPBYTE buf;
7309     DWORD size;
7310     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7311     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7312 
7313     memset(&notice, 0, sizeof(notice));
7314     ret = pCryptEncodeObjectEx(dwEncoding,
7315      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7316      NULL, &buf, &size);
7317     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7318     {
7319         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7320         return;
7321     }
7322     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7323     if (ret)
7324     {
7325         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7326         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7327         LocalFree(buf);
7328     }
7329     notice.pszDisplayText = noticeText;
7330     ret = pCryptEncodeObjectEx(dwEncoding,
7331      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7332      NULL, &buf, &size);
7333     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7334     if (ret)
7335     {
7336         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7337         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7338         LocalFree(buf);
7339     }
7340     reference.pszOrganization = org;
7341     reference.cNoticeNumbers = 2;
7342     reference.rgNoticeNumbers = noticeNumbers;
7343     notice.pNoticeReference = &reference;
7344     ret = pCryptEncodeObjectEx(dwEncoding,
7345      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7346      NULL, &buf, &size);
7347     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7348     if (ret)
7349     {
7350         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7351         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7352         LocalFree(buf);
7353     }
7354 }
7355 
7356 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7357 {
7358     BOOL ret;
7359     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7360     DWORD size;
7361 
7362     ret = pCryptDecodeObjectEx(dwEncoding,
7363      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7364      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7365      &notice, &size);
7366     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7367     {
7368         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7369         return;
7370     }
7371     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7372     if (ret)
7373     {
7374         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7375         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7376         LocalFree(notice);
7377     }
7378     ret = pCryptDecodeObjectEx(dwEncoding,
7379      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7380      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7381      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7382     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7383     if (ret)
7384     {
7385         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7386          "unexpected display text\n");
7387         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7388         LocalFree(notice);
7389     }
7390     ret = pCryptDecodeObjectEx(dwEncoding,
7391      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7392      noticeWithReference, sizeof(noticeWithReference),
7393      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7394     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7395     if (ret)
7396     {
7397         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7398          "unexpected display text\n");
7399         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7400         if (notice->pNoticeReference)
7401         {
7402             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7403              "unexpected organization %s\n",
7404              notice->pNoticeReference->pszOrganization);
7405             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7406              "expected 2 notice numbers, got %d\n",
7407              notice->pNoticeReference->cNoticeNumbers);
7408             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7409              "unexpected notice number %d\n",
7410              notice->pNoticeReference->rgNoticeNumbers[0]);
7411             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7412              "unexpected notice number %d\n",
7413              notice->pNoticeReference->rgNoticeNumbers[1]);
7414         }
7415         LocalFree(notice);
7416     }
7417 }
7418 
7419 static char oid_any_policy[] = "2.5.29.32.0";
7420 static const BYTE policiesWithAnyPolicy[] = {
7421  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7422 };
7423 static char oid1[] = "1.2.3";
7424 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7425 static const BYTE twoPolicies[] = {
7426  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7427  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7428  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7429  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7430  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7431  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7432 };
7433 
7434 static void test_encodeCertPolicies(DWORD dwEncoding)
7435 {
7436     BOOL ret;
7437     CERT_POLICIES_INFO info;
7438     CERT_POLICY_INFO policy[2];
7439     CERT_POLICY_QUALIFIER_INFO qualifier;
7440     LPBYTE buf;
7441     DWORD size;
7442 
7443     memset(&info, 0, sizeof(info));
7444     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7445      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7446     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7447     if (ret)
7448     {
7449         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7450         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7451         LocalFree(buf);
7452     }
7453     memset(policy, 0, sizeof(policy));
7454     info.cPolicyInfo = 1;
7455     info.rgPolicyInfo = policy;
7456     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7457      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7458     ok(!ret && (GetLastError() == E_INVALIDARG ||
7459      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7460      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7461     policy[0].pszPolicyIdentifier = oid_any_policy;
7462     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7463      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7464     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7465     if (ret)
7466     {
7467         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7468         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7469         LocalFree(buf);
7470     }
7471     policy[1].pszPolicyIdentifier = oid1;
7472     memset(&qualifier, 0, sizeof(qualifier));
7473     qualifier.pszPolicyQualifierId = oid_user_notice;
7474     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7475     qualifier.Qualifier.pbData = noticeWithReference;
7476     policy[1].cPolicyQualifier = 1;
7477     policy[1].rgPolicyQualifier = &qualifier;
7478     info.cPolicyInfo = 2;
7479     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7480      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7481     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7482     if (ret)
7483     {
7484         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7485         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7486         LocalFree(buf);
7487     }
7488 }
7489 
7490 static void test_decodeCertPolicies(DWORD dwEncoding)
7491 {
7492     BOOL ret;
7493     CERT_POLICIES_INFO *info;
7494     DWORD size;
7495 
7496     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7497      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7498      &info, &size);
7499     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7500     if (ret)
7501     {
7502         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7503          info->cPolicyInfo);
7504         LocalFree(info);
7505     }
7506     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7507      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7508      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7509     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7510     if (ret)
7511     {
7512         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7513          info->cPolicyInfo);
7514         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7515          "unexpected policy id %s\n",
7516          info->rgPolicyInfo[0].pszPolicyIdentifier);
7517         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7518          "unexpected policy qualifier count %d\n",
7519          info->rgPolicyInfo[0].cPolicyQualifier);
7520         LocalFree(info);
7521     }
7522     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7523      twoPolicies, sizeof(twoPolicies),
7524      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7525     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7526     if (ret)
7527     {
7528         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7529          info->cPolicyInfo);
7530         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7531          "unexpected policy id %s\n",
7532          info->rgPolicyInfo[0].pszPolicyIdentifier);
7533         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7534          "unexpected policy qualifier count %d\n",
7535          info->rgPolicyInfo[0].cPolicyQualifier);
7536         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7537          "unexpected policy id %s\n",
7538          info->rgPolicyInfo[1].pszPolicyIdentifier);
7539         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7540          "unexpected policy qualifier count %d\n",
7541          info->rgPolicyInfo[1].cPolicyQualifier);
7542         ok(!strcmp(
7543          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7544          oid_user_notice), "unexpected policy qualifier id %s\n",
7545          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7546         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7547          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7548          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7549         ok(!memcmp(
7550          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7551          noticeWithReference, sizeof(noticeWithReference)),
7552          "unexpected qualifier value\n");
7553         LocalFree(info);
7554     }
7555     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7556      twoPolicies, sizeof(twoPolicies), 0, NULL, NULL, &size);
7557     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7558     info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7559     if (info)
7560     {
7561         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7562          twoPolicies, sizeof(twoPolicies), 0, NULL, info, &size);
7563         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7564         HeapFree(GetProcessHeap(), 0, info);
7565     }
7566 }
7567 
7568 static const BYTE policyMappingWithOneMapping[] = {
7569 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7570 static const BYTE policyMappingWithTwoMappings[] = {
7571 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7572 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7573 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7574  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7575 
7576 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7577 {
7578     static char oid2[] = "2.3.4";
7579     static char oid3[] = "1.3.4";
7580     static char oid4[] = "2.5.6";
7581     BOOL ret;
7582     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7583     CERT_POLICY_MAPPING mapping[2];
7584     LPBYTE buf;
7585     DWORD size, i;
7586 
7587     /* Each of the mapping OIDs is equivalent, so check with all of them */
7588     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7589     {
7590         memset(&info, 0, sizeof(info));
7591         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7592          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7593         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7594          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7595         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7596         {
7597             win_skip("no policy mappings support\n");
7598             return;
7599         }
7600         if (ret)
7601         {
7602             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7603             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7604              "unexpected value\n");
7605             LocalFree(buf);
7606         }
7607         mapping[0].pszIssuerDomainPolicy = NULL;
7608         mapping[0].pszSubjectDomainPolicy = NULL;
7609         info.cPolicyMapping = 1;
7610         info.rgPolicyMapping = mapping;
7611         SetLastError(0xdeadbeef);
7612         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7613          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7614         ok(!ret && GetLastError() == E_INVALIDARG,
7615          "expected E_INVALIDARG, got %08x\n", GetLastError());
7616         mapping[0].pszIssuerDomainPolicy = oid1;
7617         mapping[0].pszSubjectDomainPolicy = oid2;
7618         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7619          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7620         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7621         if (ret)
7622         {
7623             ok(size == sizeof(policyMappingWithOneMapping),
7624              "unexpected size %d\n", size);
7625             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7626              "unexpected value\n");
7627             LocalFree(buf);
7628         }
7629         mapping[1].pszIssuerDomainPolicy = oid3;
7630         mapping[1].pszSubjectDomainPolicy = oid4;
7631         info.cPolicyMapping = 2;
7632         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7633          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7634         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7635         if (ret)
7636         {
7637             ok(size == sizeof(policyMappingWithTwoMappings),
7638              "unexpected size %d\n", size);
7639             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7640              "unexpected value\n");
7641             LocalFree(buf);
7642         }
7643     }
7644 }
7645 
7646 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7647 {
7648     DWORD size, i;
7649     CERT_POLICY_MAPPINGS_INFO *info;
7650     BOOL ret;
7651 
7652     /* Each of the mapping OIDs is equivalent, so check with all of them */
7653     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7654     {
7655         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7656          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7657          &info, &size);
7658         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7659          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7660         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7661         {
7662             win_skip("no policy mappings support\n");
7663             return;
7664         }
7665         if (ret)
7666         {
7667             ok(info->cPolicyMapping == 0,
7668              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7669             LocalFree(info);
7670         }
7671         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7672          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7673          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7674         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7675         if (ret)
7676         {
7677             ok(info->cPolicyMapping == 1,
7678              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7679             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7680              "unexpected issuer policy %s\n",
7681              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7682             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7683              "2.3.4"), "unexpected subject policy %s\n",
7684              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7685             LocalFree(info);
7686         }
7687         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7688          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7689          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7690         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7691         if (ret)
7692         {
7693             ok(info->cPolicyMapping == 2,
7694              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7695             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7696              "unexpected issuer policy %s\n",
7697              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7698             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7699              "2.3.4"), "unexpected subject policy %s\n",
7700              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7701             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7702              "unexpected issuer policy %s\n",
7703              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7704             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7705              "2.5.6"), "unexpected subject policy %s\n",
7706              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7707             LocalFree(info);
7708         }
7709         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7710          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7711          NULL, NULL, &size);
7712         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7713         info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7714         if (info)
7715         {
7716             ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7717              policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7718              NULL, info, &size);
7719             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7720             HeapFree(GetProcessHeap(), 0, info);
7721         }
7722     }
7723 }
7724 
7725 static const BYTE policyConstraintsWithRequireExplicit[] = {
7726 0x30,0x03,0x80,0x01,0x00 };
7727 static const BYTE policyConstraintsWithInhibitMapping[] = {
7728 0x30,0x03,0x81,0x01,0x01 };
7729 static const BYTE policyConstraintsWithBoth[] = {
7730 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7731 
7732 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7733 {
7734     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7735     LPBYTE buf;
7736     DWORD size;
7737     BOOL ret;
7738 
7739     /* Even though RFC 5280 explicitly states CAs must not issue empty
7740      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7741      */
7742     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7743      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7744     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7745      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7746     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7747     {
7748         win_skip("no policy constraints support\n");
7749         return;
7750     }
7751     if (ret)
7752     {
7753         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7754         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7755          "unexpected value\n");
7756         LocalFree(buf);
7757     }
7758     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7759      * is not, then a skip of 0 is encoded.
7760      */
7761     info.fRequireExplicitPolicy = TRUE;
7762     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7763      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7764     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7765     if (ret)
7766     {
7767         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7768          "unexpected size %d\n", size);
7769         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7770          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7771         LocalFree(buf);
7772     }
7773     /* With inhibit policy mapping */
7774     info.fRequireExplicitPolicy = FALSE;
7775     info.dwRequireExplicitPolicySkipCerts = 0;
7776     info.fInhibitPolicyMapping = TRUE;
7777     info.dwInhibitPolicyMappingSkipCerts = 1;
7778     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7779      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7780     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7781     if (ret)
7782     {
7783         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7784          "unexpected size %d\n", size);
7785         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7786          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7787         LocalFree(buf);
7788     }
7789     /* And with both */
7790     info.fRequireExplicitPolicy = TRUE;
7791     info.dwRequireExplicitPolicySkipCerts = 1;
7792     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7793      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7794     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7795     if (ret)
7796     {
7797         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7798          size);
7799         ok(!memcmp(buf, policyConstraintsWithBoth,
7800          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7801         LocalFree(buf);
7802     }
7803 }
7804 
7805 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7806 {
7807     CERT_POLICY_CONSTRAINTS_INFO *info;
7808     DWORD size;
7809     BOOL ret;
7810 
7811     /* Again, even though CAs must not issue such constraints, they can be
7812      * decoded.
7813      */
7814     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7815      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7816      &info, &size);
7817     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7818      "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7819     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7820     {
7821         win_skip("no policy mappings support\n");
7822         return;
7823     }
7824     if (ret)
7825     {
7826         ok(!info->fRequireExplicitPolicy,
7827          "expected require explicit = FALSE\n");
7828         ok(!info->fInhibitPolicyMapping,
7829          "expected implicit mapping = FALSE\n");
7830         LocalFree(info);
7831     }
7832     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7833      policyConstraintsWithRequireExplicit,
7834      sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7835      NULL, &info, &size);
7836     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7837     if (ret)
7838     {
7839         ok(info->fRequireExplicitPolicy,
7840          "expected require explicit = TRUE\n");
7841         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7842          info->dwRequireExplicitPolicySkipCerts);
7843         ok(!info->fInhibitPolicyMapping,
7844          "expected implicit mapping = FALSE\n");
7845         LocalFree(info);
7846     }
7847     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7848      policyConstraintsWithInhibitMapping,
7849      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7850      NULL, &info, &size);
7851     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7852     if (ret)
7853     {
7854         ok(!info->fRequireExplicitPolicy,
7855          "expected require explicit = FALSE\n");
7856         ok(info->fInhibitPolicyMapping,
7857          "expected implicit mapping = TRUE\n");
7858         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7859          info->dwInhibitPolicyMappingSkipCerts);
7860         LocalFree(info);
7861     }
7862     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7863      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7864      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7865     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7866     if (ret)
7867     {
7868         ok(info->fRequireExplicitPolicy,
7869          "expected require explicit = TRUE\n");
7870         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7871          info->dwRequireExplicitPolicySkipCerts);
7872         ok(info->fInhibitPolicyMapping,
7873          "expected implicit mapping = TRUE\n");
7874         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7875          info->dwInhibitPolicyMappingSkipCerts);
7876         LocalFree(info);
7877     }
7878 }
7879 
7880 static const BYTE rsaPrivKeyDer[] = {
7881 0x30,0x82,0x04,0xa5,0x02,0x01,0x00,0x02,0x82,0x01,0x01,0x00,
7882 0xae,0xba,0x3c,0x41,0xeb,0x25,0x41,0xb0,0x1c,0x41,0xd4,0x26,
7883 0xf9,0xf8,0x31,0x64,0x7e,0x97,0x65,0x54,0x9c,0x90,0xdf,0x34,
7884 0x07,0xfb,0xb0,0x69,0x99,0x3b,0x45,0x39,0x06,0xe4,0x3a,0x7a,
7885 0x01,0xe0,0xeb,0x3f,0xe1,0xd5,0x91,0xe0,0x16,0xe0,0xf2,0x35,
7886 0x59,0xdf,0x32,0x2d,0x69,0x3a,0x4a,0xbc,0xd1,0xba,0x1b,0x3b,
7887 0x7a,0x55,0x76,0xba,0x11,0xdd,0x2f,0xc7,0x58,0x66,0xf2,0x6c,
7888 0xd1,0x68,0x27,0x6c,0x85,0x74,0x0b,0xc9,0x7b,0x1a,0xde,0x3c,
7889 0x62,0x73,0xe2,0x9e,0x36,0x3a,0x29,0x3b,0x91,0x85,0x3d,0xd2,
7890 0xe1,0xe5,0x61,0x84,0x1e,0x28,0xfd,0xb7,0x97,0x68,0xc1,0xbb,
7891 0x0f,0x93,0x14,0xc2,0x03,0x60,0x41,0x11,0x7a,0xda,0x76,0x01,
7892 0x65,0x08,0xe6,0x0c,0xf6,0xfc,0x1d,0x64,0x12,0x7b,0x42,0xb0,
7893 0xb8,0xfe,0x61,0xe5,0xe2,0xe5,0x61,0x44,0xcc,0x94,0xe8,0xc0,
7894 0x4f,0x58,0x9a,0xea,0x99,0xaf,0x9c,0xa4,0xf2,0xd7,0x2b,0x31,
7895 0x90,0x3b,0x41,0x2e,0x4a,0x74,0x7c,0x1a,0xfc,0x42,0xa9,0x17,
7896 0xff,0x53,0x20,0x76,0xa7,0xf0,0x2c,0xb9,0xd5,0x1f,0xa9,0x8a,
7897 0x77,0xa8,0x09,0x5c,0x0e,0xd1,0x54,0xc5,0xf2,0x86,0xf1,0x2f,
7898 0x23,0xd6,0x63,0xba,0xe9,0x2b,0x73,0xf9,0xf0,0xdc,0xcb,0xf9,
7899 0xcb,0xe8,0x40,0x62,0x47,0x09,0x85,0xe1,0x9c,0xfd,0xcf,0x75,
7900 0x5a,0x65,0xfd,0x86,0x1c,0x50,0xfa,0x24,0x36,0x0f,0x54,0x5e,
7901 0x81,0xe7,0xf6,0x63,0x2d,0x87,0x0c,0x50,0x03,0x25,0x49,0xe7,
7902 0xc5,0x20,0xaa,0xbc,0x6c,0xf9,0xbe,0x49,0x8f,0x4f,0xb8,0x9a,
7903 0x73,0x9f,0x55,0x43,0x02,0x03,0x01,0x00,0x01,0x02,0x82,0x01,
7904 0x01,0x00,0x99,0x03,0xcd,0x5b,0x69,0x03,0x32,0x98,0x78,0xd6,
7905 0x89,0x65,0x2c,0xc9,0xd6,0xef,0x8c,0x11,0x27,0x93,0x46,0x9d,
7906 0x74,0x6a,0xcb,0x86,0xf6,0x02,0x34,0x47,0xfc,0xa2,0x29,0x4f,
7907 0xdb,0x8a,0x17,0x75,0x12,0x6f,0xda,0x65,0x3f,0x1f,0xc0,0xc9,
7908 0x74,0x33,0x96,0xa5,0xe8,0xfa,0x6d,0xc9,0xb7,0xc3,0xcd,0xe3,
7909 0x2e,0x90,0x12,0xdd,0x1f,0x61,0x69,0xdd,0x8b,0x47,0x07,0x3a,
7910 0xf8,0x98,0xa5,0x76,0x91,0xf7,0xee,0x93,0x26,0xf3,0x66,0x54,
7911 0xac,0x44,0xb3,0x6f,0x8b,0x09,0x44,0xb2,0x00,0x84,0x03,0x37,
7912 0x6d,0x61,0xed,0xa4,0x04,0x97,0x40,0x16,0x63,0xc2,0xd0,0xdc,
7913 0xd3,0xb3,0xee,0xba,0xbe,0x95,0xfd,0x80,0xe0,0xda,0xde,0xfc,
7914 0xcc,0x15,0x02,0x97,0x1d,0x68,0x43,0x2f,0x9c,0xc8,0x20,0x23,
7915 0xeb,0x00,0x4c,0x74,0x3d,0x27,0x20,0x14,0x23,0x95,0xfc,0x8c,
7916 0xb7,0x7e,0x7f,0xb0,0xdb,0xaf,0x8a,0x48,0x1b,0xfe,0x59,0xab,
7917 0x75,0xe2,0xbf,0x69,0xf2,0x73,0xe3,0xb9,0x92,0xa9,0x90,0x03,
7918 0xe5,0xd4,0x2d,0x86,0xff,0x12,0x54,0xb3,0xbb,0xe2,0xce,0x81,
7919 0x58,0x71,0xa4,0xde,0x45,0x05,0xf8,0x2d,0x45,0xf5,0xd8,0x5e,
7920 0x4c,0x5d,0x06,0x69,0x0c,0x86,0x9f,0x66,0x9f,0xb1,0x60,0xfd,
7921 0xf2,0x33,0x85,0x15,0xd5,0x18,0xf7,0xba,0x99,0x65,0x15,0x1d,
7922 0xfa,0xaa,0x76,0xdd,0x25,0xed,0xdf,0x90,0x6e,0xba,0x61,0x96,
7923 0x79,0xde,0xd2,0xda,0x66,0x03,0x74,0x3b,0x13,0x39,0x68,0xbc,
7924 0x94,0x01,0x00,0x2d,0xf8,0xf0,0x8c,0xbd,0x4c,0x9c,0x7e,0x87,
7925 0x9c,0x62,0x9f,0xb6,0x90,0x11,0x02,0x81,0x81,0x00,0xe3,0x5e,
7926 0xfe,0xdd,0xed,0x76,0xb6,0x4e,0xfc,0x5b,0xe0,0x20,0x99,0x7b,
7927 0x48,0x3b,0x1e,0x5f,0x7f,0x9f,0xa4,0x68,0xbe,0xc3,0x7f,0xb8,
7928 0x62,0x98,0xb0,0x95,0x8a,0xfa,0x0d,0xa3,0x79,0x63,0x39,0xf7,
7929 0xdb,0x76,0x3d,0x53,0x4a,0x0a,0x33,0xdf,0xe0,0x47,0x22,0xd5,
7930 0x96,0x80,0xc7,0xcd,0x24,0xef,0xac,0x49,0x46,0x37,0x6c,0x25,
7931 0xcf,0x6c,0x4d,0xe5,0x31,0xf8,0x2f,0xd2,0x59,0x74,0x00,0x38,
7932 0xdb,0xce,0xd1,0x72,0xc3,0xa8,0x30,0x70,0xd8,0x02,0x20,0xe7,
7933 0x56,0xe7,0xca,0xf0,0x3b,0x52,0x5d,0x11,0xbe,0x53,0x4e,0xd0,
7934 0xd9,0x2e,0xa6,0xb8,0xe2,0xd9,0xbf,0xb9,0x77,0xe7,0x3b,0xed,
7935 0x5e,0xd7,0x16,0x4a,0x3a,0xc5,0x86,0xd7,0x74,0x20,0xa7,0x8e,
7936 0xbf,0xb7,0x33,0xdb,0x51,0xe9,0x02,0x81,0x81,0x00,0xc4,0xba,
7937 0x57,0xf0,0x6e,0xcf,0xe8,0xce,0xce,0x9d,0x4a,0xe9,0x0f,0xe1,
7938 0xab,0x91,0x62,0xaa,0x66,0x5d,0x82,0x66,0x1c,0x72,0x18,0x6f,
7939 0x68,0x9c,0x7d,0x5e,0xfc,0xaf,0x4a,0xd6,0x8e,0xc6,0xae,0x40,
7940 0xf2,0x40,0x84,0x93,0xee,0x7c,0x87,0xa9,0xa6,0xcd,0x2b,0xc3,
7941 0xe6,0x29,0x3a,0xe2,0x4a,0xed,0xb0,0x4d,0x9f,0xc0,0xe9,0xd6,
7942 0xa3,0xca,0x97,0xee,0xac,0xab,0xa4,0x32,0x05,0x40,0x4d,0xf2,
7943 0x95,0x99,0xaf,0xa0,0xe1,0xe1,0xe7,0x3a,0x64,0xa4,0x70,0x6b,
7944 0x3d,0x1d,0x7b,0xf1,0x53,0xfa,0xb0,0xe0,0xe2,0x68,0x1a,0x61,
7945 0x2c,0x37,0xa5,0x39,0x7b,0xb2,0xcf,0xe6,0x5f,0x9b,0xc6,0x64,
7946 0xaf,0x48,0x86,0xfb,0xc1,0xf3,0x39,0x97,0x10,0x36,0xf5,0xa9,
7947 0x3d,0x08,0xa5,0x2f,0xe6,0x4b,0x02,0x81,0x81,0x00,0x86,0xe7,
7948 0x02,0x08,0xe2,0xaf,0xa0,0x93,0x54,0x9f,0x9e,0x67,0x39,0x29,
7949 0x30,0x3e,0x03,0x53,0x5e,0x01,0x76,0x26,0xbf,0xa8,0x76,0xcb,
7950 0x0b,0x94,0xd4,0x90,0xa5,0x98,0x9f,0x26,0xf3,0x0a,0xb0,0x86,
7951 0x22,0xac,0x10,0xce,0xae,0x0b,0x47,0xa3,0xf9,0x09,0xbb,0xdd,
7952 0x46,0x22,0xba,0x69,0x39,0x15,0x0a,0xff,0x9e,0xad,0x9b,0x79,
7953 0x03,0x8c,0x9a,0xda,0xf5,0xbe,0xef,0x80,0xba,0x9a,0x5c,0xd7,
7954 0x5f,0x73,0x62,0x49,0xd9,0x54,0x9d,0x09,0x16,0xe0,0x8c,0x6d,
7955 0x35,0xde,0xe9,0x45,0x87,0xac,0xe2,0x93,0x78,0x7d,0x2d,0x32,
7956 0x34,0xe9,0xbc,0xf9,0xcd,0x7e,0xac,0x86,0x7a,0x61,0xb3,0xe8,
7957 0xae,0x70,0xa7,0x44,0xfb,0x81,0xde,0xf3,0x4e,0x6f,0x61,0x7b,
7958 0x0c,0xbc,0xc2,0x03,0xca,0xa1,0x02,0x81,0x80,0x69,0x5b,0x4a,
7959 0xa1,0x4f,0x17,0x35,0x9d,0x1b,0xf6,0x0d,0x1a,0x48,0x11,0x19,
7960 0xab,0x20,0xe6,0x15,0x30,0x5b,0x17,0x88,0x80,0x6a,0x29,0xb0,
7961 0x22,0xae,0xd9,0xe2,0x05,0x96,0xd4,0xd5,0x5d,0xfe,0x10,0x76,
7962 0x2c,0xab,0x53,0xf6,0x52,0xe6,0xec,0xaa,0x92,0x12,0xb0,0x35,
7963 0x61,0x3b,0x51,0xd9,0xc2,0xf5,0xba,0x7c,0xa5,0xfa,0x15,0xa3,
7964 0x5e,0x6a,0x83,0xbe,0x21,0xa6,0x2b,0xcb,0xb8,0x26,0x86,0x96,
7965 0x2b,0xda,0x6d,0x14,0xcb,0xc0,0xe3,0xfa,0xe6,0x3d,0xf6,0x90,
7966 0xa2,0x6b,0xb0,0x50,0xc3,0x5f,0x5a,0xf0,0xa5,0xc4,0x0a,0xea,
7967 0x7d,0x5a,0x95,0x30,0x74,0x10,0xf7,0x55,0x98,0xbd,0x65,0x4a,
7968 0xa2,0x52,0xf8,0x1d,0x64,0xbf,0x20,0xf1,0xe4,0x1d,0x28,0x67,
7969 0xb1,0x6b,0x95,0xfd,0x85,0x02,0x81,0x81,0x00,0xda,0xb4,0x31,
7970 0x34,0xe1,0xec,0x9a,0x1e,0x07,0xd7,0xda,0x20,0x46,0xbf,0x6b,
7971 0xf0,0x45,0xbd,0x50,0xa2,0x0f,0x8a,0x14,0x51,0x52,0x83,0x7c,
7972 0x47,0xc8,0x9c,0x4e,0x68,0x6b,0xae,0x00,0x25,0x63,0xdd,0x13,
7973 0x2a,0x66,0x65,0xb6,0x74,0x91,0x5b,0xb6,0x47,0x3e,0x8e,0x46,
7974 0x62,0xcd,0x9d,0xc1,0xf7,0x14,0x14,0xbc,0x60,0xd6,0x3c,0x7c,
7975 0x3a,0xce,0xff,0x96,0x04,0x84,0xf6,0x44,0x1a,0xf8,0xdb,0x40,
7976 0x1c,0xf2,0xf1,0x4d,0xb2,0x68,0x3e,0xa3,0x0b,0xc6,0xb1,0xd0,
7977 0xa6,0x88,0x18,0x68,0xa1,0x05,0x2a,0xfc,0x2b,0x3a,0xa1,0xe6,
7978 0x31,0x4a,0x46,0x88,0x39,0x1e,0x44,0x11,0x6c,0xc5,0x8b,0xb6,
7979 0x8b,0xce,0x3d,0xd5,0xcb,0xbd,0xf0,0xd4,0xd9,0xfb,0x02,0x35,
7980 0x96,0x39,0x26,0x85,0xf9 };
7981 static const BYTE rsaPrivKeyModulus[] = {
7982 0x43,0x55,0x9f,0x73,0x9a,0xb8,0x4f,0x8f,0x49,0xbe,0xf9,0x6c,
7983 0xbc,0xaa,0x20,0xc5,0xe7,0x49,0x25,0x03,0x50,0x0c,0x87,0x2d,
7984 0x63,0xf6,0xe7,0x81,0x5e,0x54,0x0f,0x36,0x24,0xfa,0x50,0x1c,
7985 0x86,0xfd,0x65,0x5a,0x75,0xcf,0xfd,0x9c,0xe1,0x85,0x09,0x47,
7986 0x62,0x40,0xe8,0xcb,0xf9,0xcb,0xdc,0xf0,0xf9,0x73,0x2b,0xe9,
7987 0xba,0x63,0xd6,0x23,0x2f,0xf1,0x86,0xf2,0xc5,0x54,0xd1,0x0e,
7988 0x5c,0x09,0xa8,0x77,0x8a,0xa9,0x1f,0xd5,0xb9,0x2c,0xf0,0xa7,
7989 0x76,0x20,0x53,0xff,0x17,0xa9,0x42,0xfc,0x1a,0x7c,0x74,0x4a,
7990 0x2e,0x41,0x3b,0x90,0x31,0x2b,0xd7,0xf2,0xa4,0x9c,0xaf,0x99,
7991 0xea,0x9a,0x58,0x4f,0xc0,0xe8,0x94,0xcc,0x44,0x61,0xe5,0xe2,
7992 0xe5,0x61,0xfe,0xb8,0xb0,0x42,0x7b,0x12,0x64,0x1d,0xfc,0xf6,
7993 0x0c,0xe6,0x08,0x65,0x01,0x76,0xda,0x7a,0x11,0x41,0x60,0x03,
7994 0xc2,0x14,0x93,0x0f,0xbb,0xc1,0x68,0x97,0xb7,0xfd,0x28,0x1e,
7995 0x84,0x61,0xe5,0xe1,0xd2,0x3d,0x85,0x91,0x3b,0x29,0x3a,0x36,
7996 0x9e,0xe2,0x73,0x62,0x3c,0xde,0x1a,0x7b,0xc9,0x0b,0x74,0x85,
7997 0x6c,0x27,0x68,0xd1,0x6c,0xf2,0x66,0x58,0xc7,0x2f,0xdd,0x11,
7998 0xba,0x76,0x55,0x7a,0x3b,0x1b,0xba,0xd1,0xbc,0x4a,0x3a,0x69,
7999 0x2d,0x32,0xdf,0x59,0x35,0xf2,0xe0,0x16,0xe0,0x91,0xd5,0xe1,
8000 0x3f,0xeb,0xe0,0x01,0x7a,0x3a,0xe4,0x06,0x39,0x45,0x3b,0x99,
8001 0x69,0xb0,0xfb,0x07,0x34,0xdf,0x90,0x9c,0x54,0x65,0x97,0x7e,
8002 0x64,0x31,0xf8,0xf9,0x26,0xd4,0x41,0x1c,0xb0,0x41,0x25,0xeb,
8003 0x41,0x3c,0xba,0xae };
8004 static const BYTE rsaPrivKeyPrime1[] = {
8005 0xe9,0x51,0xdb,0x33,0xb7,0xbf,0x8e,0xa7,0x20,0x74,0xd7,0x86,
8006 0xc5,0x3a,0x4a,0x16,0xd7,0x5e,0xed,0x3b,0xe7,0x77,0xb9,0xbf,
8007 0xd9,0xe2,0xb8,0xa6,0x2e,0xd9,0xd0,0x4e,0x53,0xbe,0x11,0x5d,
8008 0x52,0x3b,0xf0,0xca,0xe7,0x56,0xe7,0x20,0x02,0xd8,0x70,0x30,
8009 0xa8,0xc3,0x72,0xd1,0xce,0xdb,0x38,0x00,0x74,0x59,0xd2,0x2f,
8010 0xf8,0x31,0xe5,0x4d,0x6c,0xcf,0x25,0x6c,0x37,0x46,0x49,0xac,
8011 0xef,0x24,0xcd,0xc7,0x80,0x96,0xd5,0x22,0x47,0xe0,0xdf,0x33,
8012 0x0a,0x4a,0x53,0x3d,0x76,0xdb,0xf7,0x39,0x63,0x79,0xa3,0x0d,
8013 0xfa,0x8a,0x95,0xb0,0x98,0x62,0xb8,0x7f,0xc3,0xbe,0x68,0xa4,
8014 0x9f,0x7f,0x5f,0x1e,0x3b,0x48,0x7b,0x99,0x20,0xe0,0x5b,0xfc,
8015 0x4e,0xb6,0x76,0xed,0xdd,0xfe,0x5e,0xe3 };
8016 static const BYTE rsaPrivKeyPrime2[] = {
8017 0x4b,0xe6,0x2f,0xa5,0x08,0x3d,0xa9,0xf5,0x36,0x10,0x97,0x39,
8018 0xf3,0xc1,0xfb,0x86,0x48,0xaf,0x64,0xc6,0x9b,0x5f,0xe6,0xcf,
8019 0xb2,0x7b,0x39,0xa5,0x37,0x2c,0x61,0x1a,0x68,0xe2,0xe0,0xb0,
8020 0xfa,0x53,0xf1,0x7b,0x1d,0x3d,0x6b,0x70,0xa4,0x64,0x3a,0xe7,
8021 0xe1,0xe1,0xa0,0xaf,0x99,0x95,0xf2,0x4d,0x40,0x05,0x32,0xa4,
8022 0xab,0xac,0xee,0x97,0xca,0xa3,0xd6,0xe9,0xc0,0x9f,0x4d,0xb0,
8023 0xed,0x4a,0xe2,0x3a,0x29,0xe6,0xc3,0x2b,0xcd,0xa6,0xa9,0x87,
8024 0x7c,0xee,0x93,0x84,0x40,0xf2,0x40,0xae,0xc6,0x8e,0xd6,0x4a,
8025 0xaf,0xfc,0x5e,0x7d,0x9c,0x68,0x6f,0x18,0x72,0x1c,0x66,0x82,
8026 0x5d,0x66,0xaa,0x62,0x91,0xab,0xe1,0x0f,0xe9,0x4a,0x9d,0xce,
8027 0xce,0xe8,0xcf,0x6e,0xf0,0x57,0xba,0xc4 };
8028 static const BYTE rsaPrivKeyExponent1[] = {
8029 0xa1,0xca,0x03,0xc2,0xbc,0x0c,0x7b,0x61,0x6f,0x4e,0xf3,0xde,
8030 0x81,0xfb,0x44,0xa7,0x70,0xae,0xe8,0xb3,0x61,0x7a,0x86,0xac,
8031 0x7e,0xcd,0xf9,0xbc,0xe9,0x34,0x32,0x2d,0x7d,0x78,0x93,0xe2,
8032 0xac,0x87,0x45,0xe9,0xde,0x35,0x6d,0x8c,0xe0,0x16,0x09,0x9d,
8033 0x54,0xd9,0x49,0x62,0x73,0x5f,0xd7,0x5c,0x9a,0xba,0x80,0xef,
8034 0xbe,0xf5,0xda,0x9a,0x8c,0x03,0x79,0x9b,0xad,0x9e,0xff,0x0a,
8035 0x15,0x39,0x69,0xba,0x22,0x46,0xdd,0xbb,0x09,0xf9,0xa3,0x47,
8036 0x0b,0xae,0xce,0x10,0xac,0x22,0x86,0xb0,0x0a,0xf3,0x26,0x9f,
8037 0x98,0xa5,0x90,0xd4,0x94,0x0b,0xcb,0x76,0xa8,0xbf,0x26,0x76,
8038 0x01,0x5e,0x53,0x03,0x3e,0x30,0x29,0x39,0x67,0x9e,0x9f,0x54,
8039 0x93,0xa0,0xaf,0xe2,0x08,0x02,0xe7,0x86 };
8040 static const BYTE rsaPrivKeyExponent2[] = {
8041 0x85,0xfd,0x95,0x6b,0xb1,0x67,0x28,0x1d,0xe4,0xf1,0x20,0xbf,
8042 0x64,0x1d,0xf8,0x52,0xa2,0x4a,0x65,0xbd,0x98,0x55,0xf7,0x10,
8043 0x74,0x30,0x95,0x5a,0x7d,0xea,0x0a,0xc4,0xa5,0xf0,0x5a,0x5f,
8044 0xc3,0x50,0xb0,0x6b,0xa2,0x90,0xf6,0x3d,0xe6,0xfa,0xe3,0xc0,
8045 0xcb,0x14,0x6d,0xda,0x2b,0x96,0x86,0x26,0xb8,0xcb,0x2b,0xa6,
8046 0x21,0xbe,0x83,0x6a,0x5e,0xa3,0x15,0xfa,0xa5,0x7c,0xba,0xf5,
8047 0xc2,0xd9,0x51,0x3b,0x61,0x35,0xb0,0x12,0x92,0xaa,0xec,0xe6,
8048 0x52,0xf6,0x53,0xab,0x2c,0x76,0x10,0xfe,0x5d,0xd5,0xd4,0x96,
8049 0x05,0xe2,0xd9,0xae,0x22,0xb0,0x29,0x6a,0x80,0x88,0x17,0x5b,
8050 0x30,0x15,0xe6,0x20,0xab,0x19,0x11,0x48,0x1a,0x0d,0xf6,0x1b,
8051 0x9d,0x35,0x17,0x4f,0xa1,0x4a,0x5b,0x69 };
8052 static const BYTE rsaPrivKeyCoefficient[] = {
8053 0xf9,0x85,0x26,0x39,0x96,0x35,0x02,0xfb,0xd9,0xd4,0xf0,0xbd,
8054 0xcb,0xd5,0x3d,0xce,0x8b,0xb6,0x8b,0xc5,0x6c,0x11,0x44,0x1e,
8055 0x39,0x88,0x46,0x4a,0x31,0xe6,0xa1,0x3a,0x2b,0xfc,0x2a,0x05,
8056 0xa1,0x68,0x18,0x88,0xa6,0xd0,0xb1,0xc6,0x0b,0xa3,0x3e,0x68,
8057 0xb2,0x4d,0xf1,0xf2,0x1c,0x40,0xdb,0xf8,0x1a,0x44,0xf6,0x84,
8058 0x04,0x96,0xff,0xce,0x3a,0x7c,0x3c,0xd6,0x60,0xbc,0x14,0x14,
8059 0xf7,0xc1,0x9d,0xcd,0x62,0x46,0x8e,0x3e,0x47,0xb6,0x5b,0x91,
8060 0x74,0xb6,0x65,0x66,0x2a,0x13,0xdd,0x63,0x25,0x00,0xae,0x6b,
8061 0x68,0x4e,0x9c,0xc8,0x47,0x7c,0x83,0x52,0x51,0x14,0x8a,0x0f,
8062 0xa2,0x50,0xbd,0x45,0xf0,0x6b,0xbf,0x46,0x20,0xda,0xd7,0x07,
8063 0x1e,0x9a,0xec,0xe1,0x34,0x31,0xb4,0xda };
8064 static const BYTE rsaPrivKeyPrivateExponent[] = {
8065 0x11,0x90,0xb6,0x9f,0x62,0x9c,0x87,0x7e,0x9c,0x4c,0xbd,0x8c,
8066 0xf0,0xf8,0x2d,0x00,0x01,0x94,0xbc,0x68,0x39,0x13,0x3b,0x74,
8067 0x03,0x66,0xda,0xd2,0xde,0x79,0x96,0x61,0xba,0x6e,0x90,0xdf,
8068 0xed,0x25,0xdd,0x76,0xaa,0xfa,0x1d,0x15,0x65,0x99,0xba,0xf7,
8069 0x18,0xd5,0x15,0x85,0x33,0xf2,0xfd,0x60,0xb1,0x9f,0x66,0x9f,
8070 0x86,0x0c,0x69,0x06,0x5d,0x4c,0x5e,0xd8,0xf5,0x45,0x2d,0xf8,
8071 0x05,0x45,0xde,0xa4,0x71,0x58,0x81,0xce,0xe2,0xbb,0xb3,0x54,
8072 0x12,0xff,0x86,0x2d,0xd4,0xe5,0x03,0x90,0xa9,0x92,0xb9,0xe3,
8073 0x73,0xf2,0x69,0xbf,0xe2,0x75,0xab,0x59,0xfe,0x1b,0x48,0x8a,
8074 0xaf,0xdb,0xb0,0x7f,0x7e,0xb7,0x8c,0xfc,0x95,0x23,0x14,0x20,
8075 0x27,0x3d,0x74,0x4c,0x00,0xeb,0x23,0x20,0xc8,0x9c,0x2f,0x43,
8076 0x68,0x1d,0x97,0x02,0x15,0xcc,0xfc,0xde,0xda,0xe0,0x80,0xfd,
8077 0x95,0xbe,0xba,0xee,0xb3,0xd3,0xdc,0xd0,0xc2,0x63,0x16,0x40,
8078 0x97,0x04,0xa4,0xed,0x61,0x6d,0x37,0x03,0x84,0x00,0xb2,0x44,
8079 0x09,0x8b,0x6f,0xb3,0x44,0xac,0x54,0x66,0xf3,0x26,0x93,0xee,
8080 0xf7,0x91,0x76,0xa5,0x98,0xf8,0x3a,0x07,0x47,0x8b,0xdd,0x69,
8081 0x61,0x1f,0xdd,0x12,0x90,0x2e,0xe3,0xcd,0xc3,0xb7,0xc9,0x6d,
8082 0xfa,0xe8,0xa5,0x96,0x33,0x74,0xc9,0xc0,0x1f,0x3f,0x65,0xda,
8083 0x6f,0x12,0x75,0x17,0x8a,0xdb,0x4f,0x29,0xa2,0xfc,0x47,0x34,
8084 0x02,0xf6,0x86,0xcb,0x6a,0x74,0x9d,0x46,0x93,0x27,0x11,0x8c,
8085 0xef,0xd6,0xc9,0x2c,0x65,0x89,0xd6,0x78,0x98,0x32,0x03,0x69,
8086 0x5b,0xcd,0x03,0x99 };
8087 
8088 static void test_decodeRsaPrivateKey(DWORD dwEncoding)
8089 {
8090     LPBYTE buf = NULL;
8091     DWORD bufSize = 0;
8092     BOOL ret;
8093 
8094     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
8095      rsaPrivKeyDer, sizeof(rsaPrivKeyDer)-10,
8096      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
8097     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD),
8098      "Expected CRYPT_E_ASN1_EOD, got %08x\n",
8099      GetLastError());
8100 
8101     buf = NULL;
8102     bufSize = 0;
8103     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
8104      rsaPrivKeyDer, sizeof(rsaPrivKeyDer),
8105      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
8106     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
8107 
8108     if (ret)
8109     {
8110         BLOBHEADER *hdr = (BLOBHEADER *)buf;
8111         RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
8112         static const int bitlen = 2048;
8113         BYTE *modulus = (BYTE*)(rsaPubKey + 1);
8114         BYTE *prime1 = modulus + bitlen/8;
8115         BYTE *prime2 = prime1 + bitlen/16;
8116         BYTE *exponent1 = prime2 + bitlen/16;
8117         BYTE *exponent2 = exponent1 + bitlen/16;
8118         BYTE *coefficient = exponent2 + bitlen/16;
8119         BYTE *privateExponent = coefficient + bitlen/16;
8120 
8121         ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
8122             (bitlen * 9 / 16),
8123          "Wrong size %d\n", bufSize);
8124 
8125         ok(hdr->bType == PRIVATEKEYBLOB,
8126          "Expected type PRIVATEKEYBLOB (%d), got %d\n", PRIVATEKEYBLOB,
8127          hdr->bType);
8128         ok(hdr->bVersion == CUR_BLOB_VERSION,
8129          "Expected version CUR_BLOB_VERSION (%d), got %d\n",
8130          CUR_BLOB_VERSION, hdr->bVersion);
8131         ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
8132          hdr->reserved);
8133         ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
8134          "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
8135 
8136         ok(rsaPubKey->magic == 0x32415352,
8137          "Expected magic 0x32415352, got 0x%x\n", rsaPubKey->magic);
8138         ok(rsaPubKey->bitlen == bitlen,
8139          "Expected bitlen %d, got %d\n", bitlen, rsaPubKey->bitlen);
8140         ok(rsaPubKey->pubexp == 65537,
8141          "Expected pubexp 65537, got %d\n", rsaPubKey->pubexp);
8142 
8143         ok(!memcmp(modulus, rsaPrivKeyModulus, bitlen/8),
8144          "unexpected modulus\n");
8145         ok(!memcmp(prime1, rsaPrivKeyPrime1, bitlen/16),
8146          "unexpected prime1\n");
8147         ok(!memcmp(prime2, rsaPrivKeyPrime2, bitlen/16),
8148          "unexpected prime2\n");
8149         ok(!memcmp(exponent1, rsaPrivKeyExponent1, bitlen/16),
8150          "unexpected exponent1\n");
8151         ok(!memcmp(exponent2, rsaPrivKeyExponent2, bitlen/16),
8152          "unexpected exponent2\n");
8153         ok(!memcmp(coefficient, rsaPrivKeyCoefficient, bitlen/16),
8154          "unexpected coefficient\n");
8155         ok(!memcmp(privateExponent, rsaPrivKeyPrivateExponent, bitlen/8),
8156          "unexpected privateExponent\n");
8157 
8158         LocalFree(buf);
8159     }
8160 }
8161 
8162 /* Free *pInfo with HeapFree */
8163 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
8164 {
8165     BOOL ret;
8166     DWORD size = 0;
8167     HCRYPTKEY key;
8168 
8169     /* This crashes
8170     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
8171      */
8172     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
8173     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8174      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8175     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
8176      &size);
8177     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8178      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8179     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
8180      NULL, &size);
8181     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8182      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8183     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
8184      0, NULL, NULL, &size);
8185     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8186      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8187     /* Test with no key */
8188     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
8189      0, NULL, NULL, &size);
8190     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
8191      GetLastError());
8192     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
8193     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
8194     if (ret)
8195     {
8196         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
8197          NULL, 0, NULL, NULL, &size);
8198         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
8199         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
8200         if (*pInfo)
8201         {
8202             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
8203              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
8204             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
8205              GetLastError());
8206             if (ret)
8207             {
8208                 /* By default (we passed NULL as the OID) the OID is
8209                  * szOID_RSA_RSA.
8210                  */
8211                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
8212                  "Expected %s, got %s\n", szOID_RSA_RSA,
8213                  (*pInfo)->Algorithm.pszObjId);
8214             }
8215         }
8216     }
8217     CryptDestroyKey(key);
8218 }
8219 
8220 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
8221  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
8222  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
8223  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
8224  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
8225  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
8226  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
8227  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
8228  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
8229  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
8230  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
8231  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
8232  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
8233  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
8234  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
8235  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
8236  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
8237  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
8238  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
8239  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
8240  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
8241  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
8242  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
8243  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
8244  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
8245 
8246 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
8247 {
8248     BOOL ret;
8249     HCRYPTKEY key;
8250     PCCERT_CONTEXT context;
8251     DWORD dwSize;
8252     ALG_ID ai;
8253 
8254     /* These crash
8255     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
8256     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
8257     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
8258     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
8259      NULL);
8260      */
8261     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
8262     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
8263      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
8264     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
8265     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
8266      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
8267     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
8268      &key);
8269     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8270      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8271 
8272     /* Export key with standard algorithm (CALG_RSA_KEYX) */
8273     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
8274      &key);
8275     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8276 
8277     dwSize = sizeof(ai);
8278     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8279     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8280     if(ret)
8281     {
8282       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8283       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
8284     }
8285 
8286     CryptDestroyKey(key);
8287 
8288     /* Repeat with forced algorithm */
8289     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
8290      &key);
8291     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8292 
8293     dwSize = sizeof(ai);
8294     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8295     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8296     if(ret)
8297     {
8298       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8299       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
8300     }
8301 
8302     CryptDestroyKey(key);
8303 
8304     /* Test importing a public key from a certificate context */
8305     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
8306      sizeof(expiredCert));
8307     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
8308      GetLastError());
8309     if (context)
8310     {
8311         ok(!strcmp(szOID_RSA_RSA,
8312          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
8313          "Expected %s, got %s\n", szOID_RSA_RSA,
8314          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
8315         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
8316          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
8317         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8318         CryptDestroyKey(key);
8319         CertFreeCertificateContext(context);
8320     }
8321 }
8322 
8323 static const char cspName[] = "WineCryptTemp";
8324 
8325 static void testPortPublicKeyInfo(void)
8326 {
8327     HCRYPTPROV csp;
8328     BOOL ret;
8329     PCERT_PUBLIC_KEY_INFO info = NULL;
8330 
8331     /* Just in case a previous run failed, delete this thing */
8332     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8333      CRYPT_DELETEKEYSET);
8334     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8335      CRYPT_NEWKEYSET);
8336     ok(ret,"CryptAcquireContextA failed\n");
8337 
8338     testExportPublicKey(csp, &info);
8339     testImportPublicKey(csp, info);
8340 
8341     HeapFree(GetProcessHeap(), 0, info);
8342     CryptReleaseContext(csp, 0);
8343     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8344      CRYPT_DELETEKEYSET);
8345     ok(ret,"CryptAcquireContextA failed\n");
8346 }
8347 
8348 START_TEST(encode)
8349 {
8350     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
8351      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
8352     HMODULE hCrypt32;
8353     DWORD i;
8354 
8355     hCrypt32 = GetModuleHandleA("crypt32.dll");
8356     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
8357     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
8358     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
8359     {
8360         win_skip("CryptDecodeObjectEx() is not available\n");
8361         return;
8362     }
8363 
8364     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
8365     {
8366         test_encodeInt(encodings[i]);
8367         test_decodeInt(encodings[i]);
8368         test_encodeEnumerated(encodings[i]);
8369         test_decodeEnumerated(encodings[i]);
8370         test_encodeFiletime(encodings[i]);
8371         test_decodeFiletime(encodings[i]);
8372         test_encodeName(encodings[i]);
8373         test_decodeName(encodings[i]);
8374         test_encodeUnicodeName(encodings[i]);
8375         test_decodeUnicodeName(encodings[i]);
8376         test_encodeNameValue(encodings[i]);
8377         test_decodeNameValue(encodings[i]);
8378         test_encodeUnicodeNameValue(encodings[i]);
8379         test_decodeUnicodeNameValue(encodings[i]);
8380         test_encodeAltName(encodings[i]);
8381         test_decodeAltName(encodings[i]);
8382         test_encodeOctets(encodings[i]);
8383         test_decodeOctets(encodings[i]);
8384         test_encodeBits(encodings[i]);
8385         test_decodeBits(encodings[i]);
8386         test_encodeBasicConstraints(encodings[i]);
8387         test_decodeBasicConstraints(encodings[i]);
8388         test_encodeRsaPublicKey(encodings[i]);
8389         test_decodeRsaPublicKey(encodings[i]);
8390         test_encodeSequenceOfAny(encodings[i]);
8391         test_decodeSequenceOfAny(encodings[i]);
8392         test_encodeExtensions(encodings[i]);
8393         test_decodeExtensions(encodings[i]);
8394         test_encodePublicKeyInfo(encodings[i]);
8395         test_decodePublicKeyInfo(encodings[i]);
8396         test_encodeCertToBeSigned(encodings[i]);
8397         test_decodeCertToBeSigned(encodings[i]);
8398         test_encodeCert(encodings[i]);
8399         test_decodeCert(encodings[i]);
8400         test_encodeCRLDistPoints(encodings[i]);
8401         test_decodeCRLDistPoints(encodings[i]);
8402         test_encodeCRLIssuingDistPoint(encodings[i]);
8403         test_decodeCRLIssuingDistPoint(encodings[i]);
8404         test_encodeCRLToBeSigned(encodings[i]);
8405         test_decodeCRLToBeSigned(encodings[i]);
8406         test_encodeEnhancedKeyUsage(encodings[i]);
8407         test_decodeEnhancedKeyUsage(encodings[i]);
8408         test_encodeAuthorityKeyId(encodings[i]);
8409         test_decodeAuthorityKeyId(encodings[i]);
8410         test_encodeAuthorityKeyId2(encodings[i]);
8411         test_decodeAuthorityKeyId2(encodings[i]);
8412         test_encodeAuthorityInfoAccess(encodings[i]);
8413         test_decodeAuthorityInfoAccess(encodings[i]);
8414         test_encodeCTL(encodings[i]);
8415         test_decodeCTL(encodings[i]);
8416         test_encodePKCSContentInfo(encodings[i]);
8417         test_decodePKCSContentInfo(encodings[i]);
8418         test_encodePKCSAttribute(encodings[i]);
8419         test_decodePKCSAttribute(encodings[i]);
8420         test_encodePKCSAttributes(encodings[i]);
8421         test_decodePKCSAttributes(encodings[i]);
8422         test_encodePKCSSMimeCapabilities(encodings[i]);
8423         test_decodePKCSSMimeCapabilities(encodings[i]);
8424         test_encodePKCSSignerInfo(encodings[i]);
8425         test_decodePKCSSignerInfo(encodings[i]);
8426         test_encodeCMSSignerInfo(encodings[i]);
8427         test_decodeCMSSignerInfo(encodings[i]);
8428         test_encodeNameConstraints(encodings[i]);
8429         test_decodeNameConstraints(encodings[i]);
8430         test_encodePolicyQualifierUserNotice(encodings[i]);
8431         test_decodePolicyQualifierUserNotice(encodings[i]);
8432         test_encodeCertPolicies(encodings[i]);
8433         test_decodeCertPolicies(encodings[i]);
8434         test_encodeCertPolicyMappings(encodings[i]);
8435         test_decodeCertPolicyMappings(encodings[i]);
8436         test_encodeCertPolicyConstraints(encodings[i]);
8437         test_decodeCertPolicyConstraints(encodings[i]);
8438         test_decodeRsaPrivateKey(encodings[i]);
8439     }
8440     testPortPublicKeyInfo();
8441 }
8442