Release 1.5.29.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35     int val;
36     const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48  { 1,          bin1 },
49  { 127,        bin2 },
50  { 128,        bin3 },
51  { 256,        bin4 },
52  { -128,       bin5 },
53  { -129,       bin6 },
54  { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59     const BYTE *val;
60     const BYTE *encoded;
61     const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73  { bin8, bin9, bin10 },
74  { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84  { bin14, bin15, NULL },
85  { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90     DWORD bufSize = 0;
91     int i;
92     BOOL ret;
93     CRYPT_INTEGER_BLOB blob;
94     BYTE *buf = NULL;
95
96     /* CryptEncodeObjectEx with NULL bufSize crashes..
97     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      NULL);
99      */
100     /* check bogus encoding */
101     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102      &bufSize);
103     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105     if (0)
106     {
107         /* check with NULL integer buffer.  Windows XP incorrectly returns an
108          * NTSTATUS (crashes on win9x).
109          */
110         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111          &bufSize);
112         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114     }
115     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116     {
117         /* encode as normal integer */
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119          NULL, NULL, &bufSize);
120         ok(ret, "Expected success, got %d\n", GetLastError());
121         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124         if (ret)
125         {
126             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127              buf[0]);
128             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129              buf[1], ints[i].encoded[1]);
130             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132             LocalFree(buf);
133         }
134         /* encode as multibyte integer */
135         blob.cbData = sizeof(ints[i].val);
136         blob.pbData = (BYTE *)&ints[i].val;
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          0, NULL, NULL, &bufSize);
139         ok(ret, "Expected success, got %d\n", GetLastError());
140         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143         if (ret)
144         {
145             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146              buf[0]);
147             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148              buf[1], ints[i].encoded[1]);
149             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151             LocalFree(buf);
152         }
153     }
154     /* encode a couple bigger ints, just to show it's little-endian and leading
155      * sign bytes are dropped
156      */
157     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158     {
159         blob.cbData = strlen((const char*)bigInts[i].val);
160         blob.pbData = (BYTE *)bigInts[i].val;
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          0, NULL, NULL, &bufSize);
163         ok(ret, "Expected success, got %d\n", GetLastError());
164         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167         if (ret)
168         {
169             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170              buf[0]);
171             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172              buf[1], bigInts[i].encoded[1]);
173             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174              bigInts[i].encoded[1] + 1),
175              "Encoded value didn't match expected\n");
176             LocalFree(buf);
177         }
178     }
179     /* and, encode some uints */
180     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181     {
182         blob.cbData = strlen((const char*)bigUInts[i].val);
183         blob.pbData = (BYTE*)bigUInts[i].val;
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          0, NULL, NULL, &bufSize);
186         ok(ret, "Expected success, got %d\n", GetLastError());
187         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190         if (ret)
191         {
192             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193              buf[0]);
194             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195              buf[1], bigUInts[i].encoded[1]);
196             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197              bigUInts[i].encoded[1] + 1),
198              "Encoded value didn't match expected\n");
199             LocalFree(buf);
200         }
201     }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211     BYTE *buf = NULL;
212     DWORD bufSize = 0;
213     int i;
214     BOOL ret;
215
216     /* CryptDecodeObjectEx with NULL bufSize crashes..
217     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219      */
220     /* check bogus encoding */
221     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225     /* check with NULL integer buffer */
226     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227      &bufSize);
228     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229      GetLastError() == OSS_BAD_ARG /* Win9x */),
230      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231     /* check with a valid, but too large, integer */
232     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
234     ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235      broken(ret) /* Win9x */,
236      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237     /* check with a DER-encoded string */
238     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
240     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241      GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242      "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243      GetLastError());
244     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
245     {
246         /* When the output buffer is NULL, this always succeeds */
247         SetLastError(0xdeadbeef);
248         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250          &bufSize);
251         ok(ret && GetLastError() == NOERROR,
252          "Expected success and NOERROR, got %d\n", GetLastError());
253         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254          ints[i].encoded, ints[i].encoded[1] + 2,
255          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
256         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258         ok(buf != NULL, "Expected allocated buffer\n");
259         if (ret)
260         {
261             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262              ints[i].val, *(int *)buf);
263             LocalFree(buf);
264         }
265     }
266     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267     {
268         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270          &bufSize);
271         ok(ret && GetLastError() == NOERROR,
272          "Expected success and NOERROR, got %d\n", GetLastError());
273         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278         ok(buf != NULL, "Expected allocated buffer\n");
279         if (ret)
280         {
281             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285              blob->cbData);
286             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287              "Unexpected value\n");
288             LocalFree(buf);
289         }
290     }
291     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292     {
293         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295          &bufSize);
296         ok(ret && GetLastError() == NOERROR,
297          "Expected success and NOERROR, got %d\n", GetLastError());
298         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303         ok(buf != NULL, "Expected allocated buffer\n");
304         if (ret)
305         {
306             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310              blob->cbData);
311             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312              "Unexpected value\n");
313             LocalFree(buf);
314         }
315     }
316     /* Decode the value 1 with long-form length */
317     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320     if (ret)
321     {
322         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323         LocalFree(buf);
324     }
325     /* check with extra bytes at the end */
326     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329     if (ret)
330     {
331         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332         LocalFree(buf);
333     }
334     /* Try to decode some bogus large items */
335     /* The buffer size is smaller than the encoded length, so this should fail
336      * with CRYPT_E_ASN1_EOD if it's being decoded.
337      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339      * So this test unfortunately isn't useful.
340     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344      */
345     /* This will try to decode the buffer and overflow it, check that it's
346      * caught.
347      */
348     if (0)
349     {
350     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355     }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362  * particular value
363  */
364 static const struct encodedInt enums[] = {
365  { 1,    bin18 },
366  { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370  * X509_ENUMERATED.
371  */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373  szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377     DWORD i, j;
378
379     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380     {
381         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382         {
383             BOOL ret;
384             BYTE *buf = NULL;
385             DWORD bufSize = 0;
386
387             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389              &bufSize);
390             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391             if (ret)
392             {
393                 ok(buf[0] == 0xa,
394                  "Got unexpected type %d for enumerated (expected 0xa)\n",
395                  buf[0]);
396                 ok(buf[1] == enums[j].encoded[1],
397                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399                  enums[j].encoded[1] + 1),
400                  "Encoded value of 0x%08x didn't match expected\n",
401                  enums[j].val);
402                 LocalFree(buf);
403             }
404         }
405     }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410     DWORD i, j;
411
412     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413     {
414         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415         {
416             BOOL ret;
417             DWORD bufSize = sizeof(int);
418             int val;
419
420             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422              &val, &bufSize);
423             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424             ok(bufSize == sizeof(int),
425              "Got unexpected size %d for enumerated\n", bufSize);
426             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427              val, enums[j].val);
428         }
429     }
430 }
431
432 struct encodedFiletime
433 {
434     SYSTEMTIME sysTime;
435     const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439  const struct encodedFiletime *time)
440 {
441     FILETIME ft = { 0 };
442     BYTE *buf = NULL;
443     DWORD bufSize = 0;
444     BOOL ret;
445
446     ret = SystemTimeToFileTime(&time->sysTime, &ft);
447     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450     /* years other than 1950-2050 are not allowed for encodings other than
451      * X509_CHOICE_OF_TIME.
452      */
453     if (structType == X509_CHOICE_OF_TIME ||
454      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455     {
456         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457          GetLastError());
458         ok(buf != NULL, "Expected an allocated buffer\n");
459         if (ret)
460         {
461             ok(buf[0] == time->encodedTime[0],
462              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463              buf[0]);
464             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465              time->encodedTime[1], bufSize);
466             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467              "Got unexpected value for time encoding\n");
468             LocalFree(buf);
469         }
470     }
471     else
472         ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473          broken(GetLastError() == ERROR_SUCCESS),
474          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479     static char buf[25];
480
481     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483     return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488     static char buf[25];
489     SYSTEMTIME st;
490
491     FileTimeToSystemTime(ft, &st);
492     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494     return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499     SYSTEMTIME st;
500
501     FileTimeToSystemTime(got, &st);
502     ok((expected->wYear == st.wYear &&
503      expected->wMonth == st.wMonth &&
504      expected->wDay == st.wDay &&
505      expected->wHour == st.wHour &&
506      expected->wMinute == st.wMinute &&
507      expected->wSecond == st.wSecond &&
508      abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509      /* Some Windows systems only seem to be accurate in their time decoding to
510       * within about an hour.
511       */
512      broken(expected->wYear == st.wYear &&
513      expected->wMonth == st.wMonth &&
514      expected->wDay == st.wDay &&
515      abs(expected->wHour - st.wHour) <= 1),
516      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517      printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521  const struct encodedFiletime *time)
522 {
523     FILETIME ft = { 0 };
524     DWORD size = sizeof(ft);
525     BOOL ret;
526
527     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529     /* years other than 1950-2050 are not allowed for encodings other than
530      * X509_CHOICE_OF_TIME.
531      */
532     if (structType == X509_CHOICE_OF_TIME ||
533      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534     {
535         ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536          "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537          GetLastError());
538         if (ret)
539             compareTime(&time->sysTime, &ft);
540     }
541     else
542         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545          GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563     DWORD i;
564
565     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566     {
567         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570     }
571 }
572
573 static const BYTE bin23[] = {
574     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598     0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602     0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604     0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608     static const struct encodedFiletime otherTimes[] = {
609      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
610      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
612      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
613      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
614      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
615      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
616      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
617      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
618      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
619      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
620      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
621     };
622     /* An oddball case that succeeds in Windows, but doesn't seem correct
623      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
624      */
625     static const unsigned char *bogusTimes[] = {
626      /* oddly, this succeeds on Windows, with year 2765
627      "\x18" "\x0f" "21r50606161000Z",
628       */
629      bin35,
630      bin36,
631      bin37,
632      bin38,
633     };
634     DWORD i, size;
635     FILETIME ft1 = { 0 }, ft2 = { 0 };
636     BOOL ret;
637
638     /* Check bogus length with non-NULL buffer */
639     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641     size = 1;
642     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644     ok(!ret && GetLastError() == ERROR_MORE_DATA,
645      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646     /* Normal tests */
647     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648     {
649         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652     }
653     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654     {
655         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658     }
659     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660     {
661         size = sizeof(ft1);
662         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664         ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665                      GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666            broken(ret), /* Win9x and NT4 for bin38 */
667          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668          GetLastError());
669     }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
686 };
687
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690  0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692  0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694  0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698  0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
701
702 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
704
705 static CHAR oid_us[]            = "2.5.4.6",
706             oid_minnesota[]     = "2.5.4.8",
707             oid_minneapolis[]   = "2.5.4.7",
708             oid_codeweavers[]   = "2.5.4.10",
709             oid_wine[]          = "2.5.4.11",
710             oid_localhostAttr[] = "2.5.4.3",
711             oid_aric[]          = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713                                     { RDNA(minnesota) },
714                                     { RDNA(minneapolis) },
715                                     { RDNA(codeweavers) },
716                                     { RDNA(wine) },
717                                     { RDNA(localhostAttr) },
718                                     { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720                                            { RDNA(localhostAttr) },
721                                            { RDNA(minnesota) },
722                                            { RDNA(minneapolis) },
723                                            { RDNA(codeweavers) },
724                                            { RDNA(wine) },
725                                            { RDNIA5(aric) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
745     CERT_RDN_ATTR attrs[2];
746     CERT_RDN rdn;
747     CERT_NAME_INFO info;
748     static CHAR oid_common_name[] = szOID_COMMON_NAME,
749                 oid_sur_name[]    = szOID_SUR_NAME;
750     BYTE *buf = NULL;
751     DWORD size = 0;
752     BOOL ret;
753
754     if (0)
755     {
756         /* Test with NULL pvStructInfo (crashes on win9x) */
757         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
761     }
762     /* Test with empty CERT_NAME_INFO */
763     info.cRDN = 0;
764     info.rgRDN = NULL;
765     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
767     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768     if (ret)
769     {
770         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771          "Got unexpected encoding for empty name\n");
772         LocalFree(buf);
773     }
774     if (0)
775     {
776         /* Test with bogus CERT_RDN (crashes on win9x) */
777         info.cRDN = 1;
778         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
780         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
782     }
783     /* Test with empty CERT_RDN */
784     rdn.cRDNAttr = 0;
785     rdn.rgRDNAttr = NULL;
786     info.cRDN = 1;
787     info.rgRDN = &rdn;
788     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
790     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791     if (ret)
792     {
793         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794          "Got unexpected encoding for empty RDN array\n");
795         LocalFree(buf);
796     }
797     if (0)
798     {
799         /* Test with bogus attr array (crashes on win9x) */
800         rdn.cRDNAttr = 1;
801         rdn.rgRDNAttr = NULL;
802         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
804         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
806     }
807     /* oddly, a bogus OID is accepted by Windows XP; not testing.
808     attrs[0].pszObjId = "bogus";
809     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810     attrs[0].Value.cbData = sizeof(commonName);
811     attrs[0].Value.pbData = commonName;
812     rdn.cRDNAttr = 1;
813     rdn.rgRDNAttr = attrs;
814     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
816     ok(!ret, "Expected failure, got success\n");
817      */
818     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
819      * the encoded attributes to be swapped.
820      */
821     attrs[0].pszObjId = oid_common_name;
822     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823     attrs[0].Value.cbData = sizeof(commonName);
824     attrs[0].Value.pbData = (BYTE *)commonName;
825     attrs[1].pszObjId = oid_sur_name;
826     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827     attrs[1].Value.cbData = sizeof(surName);
828     attrs[1].Value.pbData = (BYTE *)surName;
829     rdn.cRDNAttr = 2;
830     rdn.rgRDNAttr = attrs;
831     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
833     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834     if (ret)
835     {
836         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837          "Got unexpected encoding for two RDN array\n");
838         LocalFree(buf);
839     }
840     /* A name can be "encoded" with previously encoded RDN attrs. */
841     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843     attrs[0].Value.cbData = sizeof(twoRDNs);
844     rdn.cRDNAttr = 1;
845     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848     if (ret)
849     {
850         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851         ok(!memcmp(buf, encodedTwoRDNs, size),
852          "Unexpected value for re-endoded two RDN array\n");
853         LocalFree(buf);
854     }
855     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856     rdn.cRDNAttr = 1;
857     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
860     ok(!ret && GetLastError() == E_INVALIDARG,
861      "Expected E_INVALIDARG, got %08x\n", GetLastError());
862     /* Test a more complex name */
863     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
864     rdn.rgRDNAttr = rdnAttrs;
865     info.cRDN = 1;
866     info.rgRDN = &rdn;
867     buf = NULL;
868     size = 0;
869     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
870      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
871     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
872     if (ret)
873     {
874         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876         LocalFree(buf);
877     }
878 }
879
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
882
883 static const BYTE twoRDNsNoNull[] = {
884  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886  0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891  0x61,0x4c,0x67,0x6e };
892
893 static void test_encodeUnicodeName(DWORD dwEncoding)
894 {
895     CERT_RDN_ATTR attrs[2];
896     CERT_RDN rdn;
897     CERT_NAME_INFO info;
898     static CHAR oid_common_name[] = szOID_COMMON_NAME,
899                 oid_sur_name[]    = szOID_SUR_NAME;
900     BYTE *buf = NULL;
901     DWORD size = 0;
902     BOOL ret;
903
904     if (0)
905     {
906         /* Test with NULL pvStructInfo (crashes on win9x) */
907         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
909         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
911     }
912     /* Test with empty CERT_NAME_INFO */
913     info.cRDN = 0;
914     info.rgRDN = NULL;
915     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
917     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918     if (ret)
919     {
920         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921          "Got unexpected encoding for empty name\n");
922         LocalFree(buf);
923     }
924     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925      * encoding (the NULL).
926      */
927     attrs[0].pszObjId = oid_common_name;
928     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929     attrs[0].Value.cbData = sizeof(commonNameW);
930     attrs[0].Value.pbData = (BYTE *)commonNameW;
931     rdn.cRDNAttr = 1;
932     rdn.rgRDNAttr = attrs;
933     info.cRDN = 1;
934     info.rgRDN = &rdn;
935     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
937     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939     ok(size == 9, "Unexpected error index %08x\n", size);
940     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
941      * forces the order of the encoded attributes to be swapped.
942      */
943     attrs[0].pszObjId = oid_common_name;
944     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945     attrs[0].Value.cbData = 0;
946     attrs[0].Value.pbData = (BYTE *)commonNameW;
947     attrs[1].pszObjId = oid_sur_name;
948     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949     attrs[1].Value.cbData = 0;
950     attrs[1].Value.pbData = (BYTE *)surNameW;
951     rdn.cRDNAttr = 2;
952     rdn.rgRDNAttr = attrs;
953     info.cRDN = 1;
954     info.rgRDN = &rdn;
955     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
957     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958     if (ret)
959     {
960         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961          "Got unexpected encoding for two RDN array\n");
962         LocalFree(buf);
963     }
964     /* A name can be "encoded" with previously encoded RDN attrs. */
965     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967     attrs[0].Value.cbData = sizeof(twoRDNs);
968     rdn.cRDNAttr = 1;
969     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972     if (ret)
973     {
974         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975         ok(!memcmp(buf, encodedTwoRDNs, size),
976          "Unexpected value for re-endoded two RDN array\n");
977         LocalFree(buf);
978     }
979     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980     rdn.cRDNAttr = 1;
981     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985     if (ret)
986     {
987         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989         LocalFree(buf);
990     }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994  const CERT_NAME_VALUE *got)
995 {
996     if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997         got->dwValueType == CERT_RDN_ENCODED_BLOB)
998     {
999         win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000         return;
1001     }
1002
1003     ok(got->dwValueType == expected->dwValueType,
1004      "Expected string type %d, got %d\n", expected->dwValueType,
1005      got->dwValueType);
1006     ok(got->Value.cbData == expected->Value.cbData,
1007      "String type %d: unexpected data size, got %d, expected %d\n",
1008      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1009     if (got->Value.cbData && got->Value.pbData)
1010         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1011          min(got->Value.cbData, expected->Value.cbData)),
1012          "String type %d: unexpected value\n", expected->dwValueType);
1013 }
1014
1015 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1016  const CERT_RDN_ATTR *got)
1017 {
1018     if (expected->pszObjId && strlen(expected->pszObjId))
1019     {
1020         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1021          expected->pszObjId);
1022         if (got->pszObjId)
1023         {
1024             ok(!strcmp(got->pszObjId, expected->pszObjId),
1025              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1026              expected->pszObjId);
1027         }
1028     }
1029     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1030      (const CERT_NAME_VALUE *)&got->dwValueType);
1031 }
1032
1033 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1034 {
1035     ok(got->cRDNAttr == expected->cRDNAttr,
1036      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1037     if (got->cRDNAttr)
1038     {
1039         DWORD i;
1040
1041         for (i = 0; i < got->cRDNAttr; i++)
1042             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1043     }
1044 }
1045
1046 static void compareNames(const CERT_NAME_INFO *expected,
1047  const CERT_NAME_INFO *got)
1048 {
1049     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1050      expected->cRDN, got->cRDN);
1051     if (got->cRDN)
1052     {
1053         DWORD i;
1054
1055         for (i = 0; i < got->cRDN; i++)
1056             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1057     }
1058 }
1059
1060 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1061 static const BYTE twoRDNsExtraBytes[] = {
1062     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1063     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1064     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1065
1066 static void test_decodeName(DWORD dwEncoding)
1067 {
1068     BYTE *buf = NULL;
1069     DWORD bufSize = 0;
1070     BOOL ret;
1071     CERT_RDN rdn;
1072     CERT_NAME_INFO info = { 1, &rdn };
1073
1074     /* test empty name */
1075     bufSize = 0;
1076     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1077      emptySequence[1] + 2,
1078      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1079      &buf, &bufSize);
1080     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1081     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1082      * decoder works the same way, so only test the count.
1083      */
1084     if (ret)
1085     {
1086         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1087         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1088          "Expected 0 RDNs in empty info, got %d\n",
1089          ((CERT_NAME_INFO *)buf)->cRDN);
1090         LocalFree(buf);
1091     }
1092     /* test empty name with indefinite-length encoding */
1093     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1094      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1095      &buf, &bufSize);
1096     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1097     if (ret)
1098     {
1099         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1100         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1101          "Expected 0 RDNs in empty info, got %d\n",
1102          ((CERT_NAME_INFO *)buf)->cRDN);
1103         LocalFree(buf);
1104     }
1105     /* test empty RDN */
1106     bufSize = 0;
1107     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1108      emptyRDNs[1] + 2,
1109      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1110      &buf, &bufSize);
1111     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1112     if (ret)
1113     {
1114         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1115
1116         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1117          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1118          "Got unexpected value for empty RDN\n");
1119         LocalFree(buf);
1120     }
1121     /* test two RDN attrs */
1122     bufSize = 0;
1123     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1124      twoRDNs[1] + 2,
1125      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1126      &buf, &bufSize);
1127     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1128     if (ret)
1129     {
1130         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1131                     oid_common_name[] = szOID_COMMON_NAME;
1132
1133         CERT_RDN_ATTR attrs[] = {
1134          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1135           (BYTE *)surName } },
1136          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1137           (BYTE *)commonName } },
1138         };
1139
1140         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1141         rdn.rgRDNAttr = attrs;
1142         compareNames(&info, (CERT_NAME_INFO *)buf);
1143         LocalFree(buf);
1144     }
1145     /* test that two RDN attrs with extra bytes succeeds */
1146     bufSize = 0;
1147     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1148      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1149     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1150     /* And, a slightly more complicated name */
1151     buf = NULL;
1152     bufSize = 0;
1153     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1154      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1155     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1156     if (ret)
1157     {
1158         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1159         rdn.rgRDNAttr = decodedRdnAttrs;
1160         compareNames(&info, (CERT_NAME_INFO *)buf);
1161         LocalFree(buf);
1162     }
1163 }
1164
1165 static void test_decodeUnicodeName(DWORD dwEncoding)
1166 {
1167     BYTE *buf = NULL;
1168     DWORD bufSize = 0;
1169     BOOL ret;
1170     CERT_RDN rdn;
1171     CERT_NAME_INFO info = { 1, &rdn };
1172
1173     /* test empty name */
1174     bufSize = 0;
1175     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1176      emptySequence[1] + 2,
1177      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1178      &buf, &bufSize);
1179     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1180     if (ret)
1181     {
1182         ok(bufSize == sizeof(CERT_NAME_INFO),
1183          "Got wrong bufSize %d\n", bufSize);
1184         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1185          "Expected 0 RDNs in empty info, got %d\n",
1186          ((CERT_NAME_INFO *)buf)->cRDN);
1187         LocalFree(buf);
1188     }
1189     /* test empty RDN */
1190     bufSize = 0;
1191     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1192      emptyRDNs[1] + 2,
1193      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1194      &buf, &bufSize);
1195     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1196     if (ret)
1197     {
1198         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1199
1200         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1201          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1202          "Got unexpected value for empty RDN\n");
1203         LocalFree(buf);
1204     }
1205     /* test two RDN attrs */
1206     bufSize = 0;
1207     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1208      sizeof(twoRDNsNoNull),
1209      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1210      &buf, &bufSize);
1211     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1212     if (ret)
1213     {
1214         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1215                     oid_common_name[] = szOID_COMMON_NAME;
1216
1217         CERT_RDN_ATTR attrs[] = {
1218          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1219          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1220          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1221          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1222         };
1223
1224         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1225         rdn.rgRDNAttr = attrs;
1226         compareNames(&info, (CERT_NAME_INFO *)buf);
1227         LocalFree(buf);
1228     }
1229 }
1230
1231 struct EncodedNameValue
1232 {
1233     CERT_NAME_VALUE value;
1234     const BYTE *encoded;
1235     DWORD encodedSize;
1236 };
1237
1238 static const char bogusIA5[] = "\x80";
1239 static const char bogusPrintable[] = "~";
1240 static const char bogusNumeric[] = "A";
1241 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1242 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1243 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1244 static BYTE octetCommonNameValue[] = {
1245  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE numericCommonNameValue[] = {
1247  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE printableCommonNameValue[] = {
1249  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE t61CommonNameValue[] = {
1251  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE videotexCommonNameValue[] = {
1253  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE ia5CommonNameValue[] = {
1255  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1256 static BYTE graphicCommonNameValue[] = {
1257  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1258 static BYTE visibleCommonNameValue[] = {
1259  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1260 static BYTE generalCommonNameValue[] = {
1261  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1262 static BYTE bmpCommonNameValue[] = {
1263  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1264  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1265 static BYTE utf8CommonNameValue[] = {
1266  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1267 static char embedded_null[] = "foo\0com";
1268 static BYTE ia5EmbeddedNull[] = {
1269  0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1270
1271 static struct EncodedNameValue nameValues[] = {
1272  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1273      octetCommonNameValue, sizeof(octetCommonNameValue) },
1274  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1275      numericCommonNameValue, sizeof(numericCommonNameValue) },
1276  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1277      printableCommonNameValue, sizeof(printableCommonNameValue) },
1278  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1279      t61CommonNameValue, sizeof(t61CommonNameValue) },
1280  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1281      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1282  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1283      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1284  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1285      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1286  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1287      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1288  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1289      generalCommonNameValue, sizeof(generalCommonNameValue) },
1290  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1291      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1292  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1293      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1294  /* The following tests succeed under Windows, but really should fail,
1295   * they contain characters that are illegal for the encoding.  I'm
1296   * including them to justify my lazy encoding.
1297   */
1298  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1299      sizeof(bin42) },
1300  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1301      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1302  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1303      bin44, sizeof(bin44) },
1304 };
1305 /* This is kept separate, because the decoding doesn't return to the original
1306  * value.
1307  */
1308 static struct EncodedNameValue embeddedNullNameValue = {
1309  { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1310    ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1311
1312 static void test_encodeNameValue(DWORD dwEncoding)
1313 {
1314     BYTE *buf = NULL;
1315     DWORD size = 0, i;
1316     BOOL ret;
1317     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1318
1319     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1320     value.Value.pbData = printableCommonNameValue;
1321     value.Value.cbData = sizeof(printableCommonNameValue);
1322     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1323      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1324     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1325     if (ret)
1326     {
1327         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1328          size);
1329         ok(!memcmp(buf, printableCommonNameValue, size),
1330          "Unexpected encoding\n");
1331         LocalFree(buf);
1332     }
1333     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1334     {
1335         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1336          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1337         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1338          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1339          nameValues[i].value.dwValueType, GetLastError());
1340         if (ret)
1341         {
1342             ok(size == nameValues[i].encodedSize,
1343              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1344             ok(!memcmp(buf, nameValues[i].encoded, size),
1345              "Got unexpected encoding\n");
1346             LocalFree(buf);
1347         }
1348     }
1349     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1350      &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1351     ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1352      "Type %d: CryptEncodeObjectEx failed: %08x\n",
1353      embeddedNullNameValue.value.dwValueType, GetLastError());
1354     if (ret)
1355     {
1356         ok(size == embeddedNullNameValue.encodedSize,
1357          "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1358         ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1359          "Got unexpected encoding\n");
1360         LocalFree(buf);
1361     }
1362 }
1363
1364 static void test_decodeNameValue(DWORD dwEncoding)
1365 {
1366     int i;
1367     BYTE *buf = NULL;
1368     DWORD bufSize = 0;
1369     BOOL ret;
1370
1371     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1372     {
1373         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1374          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1375          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1376          &buf, &bufSize);
1377         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1378          nameValues[i].value.dwValueType, GetLastError());
1379         if (ret)
1380         {
1381             compareNameValues(&nameValues[i].value,
1382              (const CERT_NAME_VALUE *)buf);
1383             LocalFree(buf);
1384         }
1385     }
1386     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1387      embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1388      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1389      &buf, &bufSize);
1390     /* Some Windows versions disallow name values with embedded NULLs, so
1391      * either success or failure is acceptable.
1392      */
1393     if (ret)
1394     {
1395         CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1396          { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1397         CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1398          { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1399         const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1400          *expected = NULL;
1401
1402         /* Some Windows versions decode name values with embedded NULLs,
1403          * others leave them encoded, even with the same version of crypt32.
1404          * Accept either.
1405          */
1406         ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1407          got->dwValueType == CERT_RDN_IA5_STRING,
1408          "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1409          got->dwValueType);
1410         if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1411             expected = &rdnEncodedValue;
1412         else if (got->dwValueType == CERT_RDN_IA5_STRING)
1413             expected = &embeddedNullValue;
1414         if (expected)
1415         {
1416             ok(got->Value.cbData == expected->Value.cbData,
1417              "String type %d: unexpected data size, got %d, expected %d\n",
1418              got->dwValueType, got->Value.cbData, expected->Value.cbData);
1419             if (got->Value.cbData && got->Value.pbData)
1420                 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1421                  min(got->Value.cbData, expected->Value.cbData)),
1422                  "String type %d: unexpected value\n", expected->dwValueType);
1423         }
1424         LocalFree(buf);
1425     }
1426 }
1427
1428 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1429 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1430 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1431  'h','q','.','o','r','g',0 };
1432 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1433  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1434  0x6f, 0x72, 0x67 };
1435 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1436  0x575b, 0 };
1437 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1438 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1439  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1440 static const BYTE localhost[] = { 127, 0, 0, 1 };
1441 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1442  0x01 };
1443 static const unsigned char encodedCommonName[] = {
1444     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1445 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1446 static const BYTE encodedDirectoryName[] = {
1447 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1448 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1449
1450 static void test_encodeAltName(DWORD dwEncoding)
1451 {
1452     CERT_ALT_NAME_INFO info = { 0 };
1453     CERT_ALT_NAME_ENTRY entry = { 0 };
1454     BYTE *buf = NULL;
1455     DWORD size = 0;
1456     BOOL ret;
1457     char oid[] = "1.2.3";
1458
1459     /* Test with empty info */
1460     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1461      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1462     if (ret)
1463     {
1464         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1465         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1466         LocalFree(buf);
1467     }
1468     /* Test with an empty entry */
1469     info.cAltEntry = 1;
1470     info.rgAltEntry = &entry;
1471     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1472      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1473     ok(!ret && GetLastError() == E_INVALIDARG,
1474      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1475     /* Test with an empty pointer */
1476     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1477     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1478      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1479     if (ret)
1480     {
1481         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1482         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1483         LocalFree(buf);
1484     }
1485     /* Test with a real URL */
1486     U(entry).pwszURL = (LPWSTR)url;
1487     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1488      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1489     if (ret)
1490     {
1491         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1492         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1493         LocalFree(buf);
1494     }
1495     /* Now with the URL containing an invalid IA5 char */
1496     U(entry).pwszURL = (LPWSTR)nihongoURL;
1497     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1498      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1499     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1500      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1501     /* The first invalid character is at index 7 */
1502     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1503      "Expected invalid char at index 7, got %d\n",
1504      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1505     /* Now with the URL missing a scheme */
1506     U(entry).pwszURL = (LPWSTR)dnsName;
1507     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1508      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1509     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1510     if (ret)
1511     {
1512         /* This succeeds, but it shouldn't, so don't worry about conforming */
1513         LocalFree(buf);
1514     }
1515     /* Now with a DNS name */
1516     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1517     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1518      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1519     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1520     if (ret)
1521     {
1522         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1523         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1524         LocalFree(buf);
1525     }
1526     /* Test with an IP address */
1527     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1528     U(entry).IPAddress.cbData = sizeof(localhost);
1529     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1530     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1531      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1532     if (ret)
1533     {
1534         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1535         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1536         LocalFree(buf);
1537     }
1538     /* Test with OID */
1539     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1540     U(entry).pszRegisteredID = oid;
1541     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1542      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1543     if (ret)
1544     {
1545         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1546         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1547         LocalFree(buf);
1548     }
1549     /* Test with directory name */
1550     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1551     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1552     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1553     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1554      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1555     if (ret)
1556     {
1557         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1558         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1559         LocalFree(buf);
1560     }
1561 }
1562
1563 static void test_decodeAltName(DWORD dwEncoding)
1564 {
1565     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1566      0x00, 0x00, 0x01 };
1567     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1568      0x01 };
1569     static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1570      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1571     static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1572      0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1573     static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1574      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1575     BOOL ret;
1576     BYTE *buf = NULL;
1577     DWORD bufSize = 0;
1578     CERT_ALT_NAME_INFO *info;
1579
1580     /* Test some bogus ones first */
1581     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1582      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1583      NULL, &buf, &bufSize);
1584     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1585      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1586      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1587      GetLastError());
1588     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1589      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1590      &bufSize);
1591     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1592      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1593      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1594      GetLastError());
1595     /* Now expected cases */
1596     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1597      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1598     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1599     if (ret)
1600     {
1601         info = (CERT_ALT_NAME_INFO *)buf;
1602
1603         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1604          info->cAltEntry);
1605         LocalFree(buf);
1606     }
1607     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1608      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1609     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1610     if (ret)
1611     {
1612         info = (CERT_ALT_NAME_INFO *)buf;
1613
1614         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1615          info->cAltEntry);
1616         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1617          "Expected CERT_ALT_NAME_URL, got %d\n",
1618          info->rgAltEntry[0].dwAltNameChoice);
1619         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1620          "Expected empty URL\n");
1621         LocalFree(buf);
1622     }
1623     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1624      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1625     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1626     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1627      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1628     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1629     if (ret)
1630     {
1631         info = (CERT_ALT_NAME_INFO *)buf;
1632
1633         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1634          info->cAltEntry);
1635         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1636          "Expected CERT_ALT_NAME_URL, got %d\n",
1637          info->rgAltEntry[0].dwAltNameChoice);
1638         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1639         LocalFree(buf);
1640     }
1641     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1642      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1643     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1644     if (ret)
1645     {
1646         info = (CERT_ALT_NAME_INFO *)buf;
1647
1648         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1649          info->cAltEntry);
1650         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1651          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1652          info->rgAltEntry[0].dwAltNameChoice);
1653         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1654          "Unexpected DNS name\n");
1655         LocalFree(buf);
1656     }
1657     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1658      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1659     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1660     if (ret)
1661     {
1662         info = (CERT_ALT_NAME_INFO *)buf;
1663
1664         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1665          info->cAltEntry);
1666         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1667          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1668          info->rgAltEntry[0].dwAltNameChoice);
1669         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1670          "Unexpected IP address length %d\n",
1671           U(info->rgAltEntry[0]).IPAddress.cbData);
1672         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1673          sizeof(localhost)), "Unexpected IP address value\n");
1674         LocalFree(buf);
1675     }
1676     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1677      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1678     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1679     if (ret)
1680     {
1681         info = (CERT_ALT_NAME_INFO *)buf;
1682
1683         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1684          info->cAltEntry);
1685         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1686          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1687          info->rgAltEntry[0].dwAltNameChoice);
1688         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1689            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1690         LocalFree(buf);
1691     }
1692     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1693      encodedDirectoryName, sizeof(encodedDirectoryName),
1694      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1695     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1696     if (ret)
1697     {
1698         info = (CERT_ALT_NAME_INFO *)buf;
1699
1700         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1701          info->cAltEntry);
1702         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1703          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1704          info->rgAltEntry[0].dwAltNameChoice);
1705         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1706          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1707           U(info->rgAltEntry[0]).DirectoryName.cbData);
1708         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1709          encodedCommonName, sizeof(encodedCommonName)),
1710          "Unexpected directory name value\n");
1711         LocalFree(buf);
1712     }
1713     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1714      dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1715      NULL, &buf, &bufSize);
1716     /* Fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned about the
1717      * particular failure, just that it doesn't decode.
1718      * It succeeds on (broken) Windows versions that haven't addressed
1719      * embedded NULLs in alternate names.
1720      */
1721     ok(!ret || broken(ret), "expected failure\n");
1722     /* An embedded bell character is allowed, however. */
1723     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1724      dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1725      NULL, &buf, &bufSize);
1726     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1727     if (ret)
1728     {
1729         info = (CERT_ALT_NAME_INFO *)buf;
1730
1731         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1732          info->cAltEntry);
1733         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1734          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1735          info->rgAltEntry[0].dwAltNameChoice);
1736         LocalFree(buf);
1737     }
1738     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1739      url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1740      NULL, &buf, &bufSize);
1741     /* Again, fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned
1742      * about the particular failure, just that it doesn't decode.
1743      * It succeeds on (broken) Windows versions that haven't addressed
1744      * embedded NULLs in alternate names.
1745      */
1746     ok(!ret || broken(ret), "expected failure\n");
1747 }
1748
1749 struct UnicodeExpectedError
1750 {
1751     DWORD   valueType;
1752     LPCWSTR str;
1753     DWORD   errorIndex;
1754     DWORD   error;
1755 };
1756
1757 static const WCHAR oneW[] = { '1',0 };
1758 static const WCHAR aW[] = { 'a',0 };
1759 static const WCHAR quoteW[] = { '"', 0 };
1760
1761 static struct UnicodeExpectedError unicodeErrors[] = {
1762  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1763  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1764  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1765  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1766  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1767  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1768 };
1769
1770 struct UnicodeExpectedResult
1771 {
1772     DWORD           valueType;
1773     LPCWSTR         str;
1774     CRYPT_DATA_BLOB encoded;
1775 };
1776
1777 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1778 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1779 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1780 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1781 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1782 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1783 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1784 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1785 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1786 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1787 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1788 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1789  0x5b };
1790 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1791  0x6f,0x5b };
1792 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1793  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1794 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1795  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1796
1797 static struct UnicodeExpectedResult unicodeResults[] = {
1798  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1799  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1800  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1801  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1802  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1803  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1804  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1805  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1806  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1807  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1808  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1809  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1810  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1811 };
1812
1813 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1814  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1815  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1816 };
1817
1818 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1819 {
1820     BYTE *buf = NULL;
1821     DWORD size = 0, i;
1822     BOOL ret;
1823     CERT_NAME_VALUE value;
1824
1825     if (0)
1826     {
1827         /* Crashes on win9x */
1828         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1829          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1830         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1831          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1832     }
1833     /* Have to have a string of some sort */
1834     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1835     value.Value.pbData = NULL;
1836     value.Value.cbData = 0;
1837     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1838      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1839     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1840      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1841     value.dwValueType = CERT_RDN_ENCODED_BLOB;
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.dwValueType = CERT_RDN_ANY_TYPE;
1847     value.Value.pbData = (LPBYTE)oneW;
1848     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1849      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1850     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1851      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1852     value.Value.cbData = sizeof(oneW);
1853     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1854      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1855     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1856      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1857     /* An encoded string with specified length isn't good enough either */
1858     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1859     value.Value.pbData = oneUniversal;
1860     value.Value.cbData = sizeof(oneUniversal);
1861     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1862      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1863     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1864      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1865     /* More failure checking */
1866     value.Value.cbData = 0;
1867     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1868     {
1869         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1870         value.dwValueType = unicodeErrors[i].valueType;
1871         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1872          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1873         ok(!ret && GetLastError() == unicodeErrors[i].error,
1874          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1875          unicodeErrors[i].error, GetLastError());
1876         ok(size == unicodeErrors[i].errorIndex,
1877          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1878          size);
1879     }
1880     /* cbData can be zero if the string is NULL-terminated */
1881     value.Value.cbData = 0;
1882     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1883     {
1884         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1885         value.dwValueType = unicodeResults[i].valueType;
1886         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1887          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1888         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1889          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1890         if (ret)
1891         {
1892             ok(size == unicodeResults[i].encoded.cbData,
1893              "Value type %d: expected size %d, got %d\n",
1894              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1895             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1896              "Value type %d: unexpected value\n", value.dwValueType);
1897             LocalFree(buf);
1898         }
1899     }
1900     /* These "encode," but they do so by truncating each unicode character
1901      * rather than properly encoding it.  Kept separate from the proper results,
1902      * because the encoded forms won't decode to their original strings.
1903      */
1904     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1905     {
1906         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1907         value.dwValueType = unicodeWeirdness[i].valueType;
1908         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1909          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1910         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1911         if (ret)
1912         {
1913             ok(size == unicodeWeirdness[i].encoded.cbData,
1914              "Value type %d: expected size %d, got %d\n",
1915              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1916             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1917              "Value type %d: unexpected value\n", value.dwValueType);
1918             LocalFree(buf);
1919         }
1920     }
1921 }
1922
1923 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1924 {
1925     if (n <= 0) return 0;
1926     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1927     return *str1 - *str2;
1928 }
1929
1930 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1931 {
1932     DWORD i;
1933
1934     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1935     {
1936         BYTE *buf = NULL;
1937         BOOL ret;
1938         DWORD size = 0;
1939
1940         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1941          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1942          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1943         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1944          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1945         if (ret && buf)
1946         {
1947             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1948
1949             ok(value->dwValueType == unicodeResults[i].valueType,
1950              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1951              value->dwValueType);
1952             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1953              value->Value.cbData / sizeof(WCHAR)),
1954              "Unexpected decoded value for index %d (value type %d)\n", i,
1955              unicodeResults[i].valueType);
1956             LocalFree(buf);
1957         }
1958     }
1959 }
1960
1961 struct encodedOctets
1962 {
1963     const BYTE *val;
1964     const BYTE *encoded;
1965 };
1966
1967 static const unsigned char bin46[] = { 'h','i',0 };
1968 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1969 static const unsigned char bin48[] = {
1970      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1971 static const unsigned char bin49[] = {
1972      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1973 static const unsigned char bin50[] = { 0 };
1974 static const unsigned char bin51[] = { 0x04,0x00,0 };
1975
1976 static const struct encodedOctets octets[] = {
1977     { bin46, bin47 },
1978     { bin48, bin49 },
1979     { bin50, bin51 },
1980 };
1981
1982 static void test_encodeOctets(DWORD dwEncoding)
1983 {
1984     CRYPT_DATA_BLOB blob;
1985     DWORD i;
1986
1987     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1988     {
1989         BYTE *buf = NULL;
1990         BOOL ret;
1991         DWORD bufSize = 0;
1992
1993         blob.cbData = strlen((const char*)octets[i].val);
1994         blob.pbData = (BYTE*)octets[i].val;
1995         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1996          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1997         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1998         if (ret)
1999         {
2000             ok(buf[0] == 4,
2001              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
2002             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
2003              buf[1], octets[i].encoded[1]);
2004             ok(!memcmp(buf + 1, octets[i].encoded + 1,
2005              octets[i].encoded[1] + 1), "Got unexpected value\n");
2006             LocalFree(buf);
2007         }
2008     }
2009 }
2010
2011 static void test_decodeOctets(DWORD dwEncoding)
2012 {
2013     DWORD i;
2014
2015     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
2016     {
2017         BYTE *buf = NULL;
2018         BOOL ret;
2019         DWORD bufSize = 0;
2020
2021         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2022          octets[i].encoded, octets[i].encoded[1] + 2,
2023          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2024         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2025         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
2026          "Expected size >= %d, got %d\n",
2027            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2028         ok(buf != NULL, "Expected allocated buffer\n");
2029         if (ret)
2030         {
2031             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2032
2033             if (blob->cbData)
2034                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2035                  "Unexpected value\n");
2036             LocalFree(buf);
2037         }
2038     }
2039 }
2040
2041 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2042
2043 struct encodedBits
2044 {
2045     DWORD cUnusedBits;
2046     const BYTE *encoded;
2047     DWORD cbDecoded;
2048     const BYTE *decoded;
2049 };
2050
2051 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2052 static const unsigned char bin53[] = { 0xff,0xff };
2053 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2054 static const unsigned char bin55[] = { 0xff,0xfe };
2055 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2056 static const unsigned char bin57[] = { 0xfe };
2057 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
2058
2059 static const struct encodedBits bits[] = {
2060     /* normal test cases */
2061     { 0, bin52, 2, bin53 },
2062     { 1, bin54, 2, bin55 },
2063     /* strange test case, showing cUnusedBits >= 8 is allowed */
2064     { 9, bin56, 1, bin57 },
2065 };
2066
2067 static void test_encodeBits(DWORD dwEncoding)
2068 {
2069     DWORD i;
2070
2071     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2072     {
2073         CRYPT_BIT_BLOB blob;
2074         BOOL ret;
2075         BYTE *buf = NULL;
2076         DWORD bufSize = 0;
2077
2078         blob.cbData = sizeof(bytesToEncode);
2079         blob.pbData = (BYTE *)bytesToEncode;
2080         blob.cUnusedBits = bits[i].cUnusedBits;
2081         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2082          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2083         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2084         if (ret)
2085         {
2086             ok(bufSize == bits[i].encoded[1] + 2,
2087              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2088              bits[i].encoded[1] + 2);
2089             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2090              "%d: Unexpected value\n", i);
2091             LocalFree(buf);
2092         }
2093     }
2094 }
2095
2096 static void test_decodeBits(DWORD dwEncoding)
2097 {
2098     static const BYTE ber[] = "\x03\x02\x01\xff";
2099     static const BYTE berDecoded = 0xfe;
2100     DWORD i;
2101     BOOL ret;
2102     BYTE *buf = NULL;
2103     DWORD bufSize = 0;
2104
2105     /* normal cases */
2106     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2107     {
2108         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2109          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2110          &bufSize);
2111         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2112         if (ret)
2113         {
2114             CRYPT_BIT_BLOB *blob;
2115
2116             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2117                "Got unexpected size %d\n", bufSize);
2118             blob = (CRYPT_BIT_BLOB *)buf;
2119             ok(blob->cbData == bits[i].cbDecoded,
2120              "Got unexpected length %d, expected %d\n", blob->cbData,
2121              bits[i].cbDecoded);
2122             if (blob->cbData && bits[i].cbDecoded)
2123                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2124                  "Unexpected value\n");
2125             LocalFree(buf);
2126         }
2127     }
2128     /* special case: check that something that's valid in BER but not in DER
2129      * decodes successfully
2130      */
2131     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2132      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2133     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2134     if (ret)
2135     {
2136         CRYPT_BIT_BLOB *blob;
2137
2138         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2139            "Got unexpected size %d\n", bufSize);
2140         blob = (CRYPT_BIT_BLOB *)buf;
2141         ok(blob->cbData == sizeof(berDecoded),
2142            "Got unexpected length %d\n", blob->cbData);
2143         if (blob->cbData)
2144             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2145         LocalFree(buf);
2146     }
2147 }
2148
2149 struct Constraints2
2150 {
2151     CERT_BASIC_CONSTRAINTS2_INFO info;
2152     const BYTE *encoded;
2153 };
2154
2155 static const unsigned char bin59[] = { 0x30,0x00 };
2156 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2157 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2158 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2159 static const struct Constraints2 constraints2[] = {
2160  /* empty constraints */
2161  { { FALSE, FALSE, 0}, bin59 },
2162  /* can be a CA */
2163  { { TRUE,  FALSE, 0}, bin60 },
2164  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2165   * but that's not the case
2166   */
2167  { { FALSE, TRUE,  0}, bin61 },
2168  /* can be a CA and has path length constraints set */
2169  { { TRUE,  TRUE,  1}, bin62 },
2170 };
2171
2172 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2173 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2174  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2175  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2176  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2177 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2178  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2179  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2180  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2181  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2182
2183 static void test_encodeBasicConstraints(DWORD dwEncoding)
2184 {
2185     DWORD i, bufSize = 0;
2186     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2187     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2188      (LPBYTE)encodedDomainName };
2189     BOOL ret;
2190     BYTE *buf = NULL;
2191
2192     /* First test with the simpler info2 */
2193     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2194     {
2195         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2197          &bufSize);
2198         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2199         if (ret)
2200         {
2201             ok(bufSize == constraints2[i].encoded[1] + 2,
2202              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2203              bufSize);
2204             ok(!memcmp(buf, constraints2[i].encoded,
2205              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2206             LocalFree(buf);
2207         }
2208     }
2209     /* Now test with more complex basic constraints */
2210     info.SubjectType.cbData = 0;
2211     info.fPathLenConstraint = FALSE;
2212     info.cSubtreesConstraint = 0;
2213     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2214      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2215     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2216      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2217     if (ret)
2218     {
2219         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2220         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2221          "Unexpected value\n");
2222         LocalFree(buf);
2223     }
2224     /* None of the certs I examined had any subtree constraint, but I test one
2225      * anyway just in case.
2226      */
2227     info.cSubtreesConstraint = 1;
2228     info.rgSubtreesConstraint = &nameBlob;
2229     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2230      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2231     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2232      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2233     if (ret)
2234     {
2235         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2236         ok(!memcmp(buf, constraintWithDomainName,
2237          sizeof(constraintWithDomainName)), "Unexpected value\n");
2238         LocalFree(buf);
2239     }
2240     /* FIXME: test encoding with subject type. */
2241 }
2242
2243 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2244
2245 static void test_decodeBasicConstraints(DWORD dwEncoding)
2246 {
2247     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2248      0xff };
2249     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2250     DWORD i;
2251     BOOL ret;
2252     BYTE *buf = NULL;
2253     DWORD bufSize = 0;
2254
2255     /* First test with simpler info2 */
2256     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2257     {
2258         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2259          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2260          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2261         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2262          GetLastError());
2263         if (ret)
2264         {
2265             CERT_BASIC_CONSTRAINTS2_INFO *info =
2266              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2267
2268             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2269              "Unexpected value for item %d\n", i);
2270             LocalFree(buf);
2271         }
2272     }
2273     /* Check with the order of encoded elements inverted */
2274     buf = (PBYTE)1;
2275     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2276      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2277      &bufSize);
2278     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2279      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2280      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2281      GetLastError());
2282     ok(!buf, "Expected buf to be set to NULL\n");
2283     /* Check with a non-DER bool */
2284     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2285      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2286      &buf, &bufSize);
2287     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2288     if (ret)
2289     {
2290         CERT_BASIC_CONSTRAINTS2_INFO *info =
2291          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2292
2293         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2294         LocalFree(buf);
2295     }
2296     /* Check with a non-basic constraints value */
2297     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2298      encodedCommonName, encodedCommonName[1] + 2,
2299      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2300     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2301      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2302      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2303      GetLastError());
2304     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2305     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2306      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2307      &buf, &bufSize);
2308     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2309     if (ret)
2310     {
2311         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2312
2313         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2314         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2315         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2316         LocalFree(buf);
2317     }
2318     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2319      constraintWithDomainName, sizeof(constraintWithDomainName),
2320      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2321     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2322     if (ret)
2323     {
2324         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2325
2326         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2327         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2328         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2329         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2330         {
2331             ok(info->rgSubtreesConstraint[0].cbData ==
2332              sizeof(encodedDomainName), "Wrong size %d\n",
2333              info->rgSubtreesConstraint[0].cbData);
2334             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2335              sizeof(encodedDomainName)), "Unexpected value\n");
2336         }
2337         LocalFree(buf);
2338     }
2339 }
2340
2341 /* These are terrible public keys of course, I'm just testing encoding */
2342 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2343 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2344 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2345 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2346 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2347 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2348 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2349 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2350
2351 struct EncodedRSAPubKey
2352 {
2353     const BYTE *modulus;
2354     size_t modulusLen;
2355     const BYTE *encoded;
2356     size_t decodedModulusLen;
2357 };
2358
2359 static const struct EncodedRSAPubKey rsaPubKeys[] = {
2360     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2361     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2362     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2363     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2364 };
2365
2366 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2367 {
2368     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2369     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2370     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2371     BOOL ret;
2372     BYTE *buf = NULL;
2373     DWORD bufSize = 0, i;
2374
2375     /* Try with a bogus blob type */
2376     hdr->bType = 2;
2377     hdr->bVersion = CUR_BLOB_VERSION;
2378     hdr->reserved = 0;
2379     hdr->aiKeyAlg = CALG_RSA_KEYX;
2380     rsaPubKey->magic = 0x31415352;
2381     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2382     rsaPubKey->pubexp = 65537;
2383     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2384      sizeof(modulus1));
2385
2386     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2387      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388     ok(!ret && GetLastError() == E_INVALIDARG,
2389      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2390     /* Now with a bogus reserved field */
2391     hdr->bType = PUBLICKEYBLOB;
2392     hdr->reserved = 1;
2393     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2394      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2395     if (ret)
2396     {
2397         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2398          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2399         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2400         LocalFree(buf);
2401     }
2402     /* Now with a bogus blob version */
2403     hdr->reserved = 0;
2404     hdr->bVersion = 0;
2405     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2406      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2407     if (ret)
2408     {
2409         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2410          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2411         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2412         LocalFree(buf);
2413     }
2414     /* And with a bogus alg ID */
2415     hdr->bVersion = CUR_BLOB_VERSION;
2416     hdr->aiKeyAlg = CALG_DES;
2417     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2418      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2419     if (ret)
2420     {
2421         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2422          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2423         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2424         LocalFree(buf);
2425     }
2426     /* Check a couple of RSA-related OIDs */
2427     hdr->aiKeyAlg = CALG_RSA_KEYX;
2428     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2429      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2430     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2431      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2432     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2433      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2434     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2435      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2436     /* Finally, all valid */
2437     hdr->aiKeyAlg = CALG_RSA_KEYX;
2438     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2439     {
2440         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2441          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2442         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2443          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2444         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2445         if (ret)
2446         {
2447             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2448              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2449              bufSize);
2450             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2451              "Unexpected value\n");
2452             LocalFree(buf);
2453         }
2454     }
2455 }
2456
2457 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2458 {
2459     DWORD i;
2460     LPBYTE buf = NULL;
2461     DWORD bufSize = 0;
2462     BOOL ret;
2463
2464     /* Try with a bad length */
2465     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2466      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2467      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2468     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2469      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2470      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2471      GetLastError());
2472     /* Try with a couple of RSA-related OIDs */
2473     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2474      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2475      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2476     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2477      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2478     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2479      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2480      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2481     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2482      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2483     /* Now try success cases */
2484     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2485     {
2486         bufSize = 0;
2487         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2488          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2489          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2490         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2491         if (ret)
2492         {
2493             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2494             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2495
2496             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2497              rsaPubKeys[i].decodedModulusLen,
2498              "Wrong size %d\n", bufSize);
2499             ok(hdr->bType == PUBLICKEYBLOB,
2500              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2501              hdr->bType);
2502             ok(hdr->bVersion == CUR_BLOB_VERSION,
2503              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2504              CUR_BLOB_VERSION, hdr->bVersion);
2505             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2506              hdr->reserved);
2507             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2508              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2509             ok(rsaPubKey->magic == 0x31415352,
2510              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2511             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2512              "Wrong bit len %d\n", rsaPubKey->bitlen);
2513             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2514              rsaPubKey->pubexp);
2515             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2516              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2517              "Unexpected modulus\n");
2518             LocalFree(buf);
2519         }
2520     }
2521 }
2522
2523 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2524  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2525  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2526
2527 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2528  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2529  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2530  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2531
2532 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2533 {
2534     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2535     CRYPT_SEQUENCE_OF_ANY seq;
2536     DWORD i;
2537     BOOL ret;
2538     BYTE *buf = NULL;
2539     DWORD bufSize = 0;
2540
2541     /* Encode a homogeneous sequence */
2542     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2543     {
2544         blobs[i].cbData = ints[i].encoded[1] + 2;
2545         blobs[i].pbData = (BYTE *)ints[i].encoded;
2546     }
2547     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2548     seq.rgValue = blobs;
2549
2550     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2551      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2552     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2553     if (ret)
2554     {
2555         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2556         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2557         LocalFree(buf);
2558     }
2559     /* Change the type of the first element in the sequence, and give it
2560      * another go
2561      */
2562     blobs[0].cbData = times[0].encodedTime[1] + 2;
2563     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2564     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2565      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2566     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2567     if (ret)
2568     {
2569         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2570         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2571          "Unexpected value\n");
2572         LocalFree(buf);
2573     }
2574 }
2575
2576 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2577 {
2578     BOOL ret;
2579     BYTE *buf = NULL;
2580     DWORD bufSize = 0;
2581
2582     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2583      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2584     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2585     if (ret)
2586     {
2587         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2588         DWORD i;
2589
2590         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2591          "Wrong elements %d\n", seq->cValue);
2592         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2593         {
2594             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2595              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2596              seq->rgValue[i].cbData);
2597             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2598              ints[i].encoded[1] + 2), "Unexpected value\n");
2599         }
2600         LocalFree(buf);
2601     }
2602     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2603      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2604      &bufSize);
2605     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2606     if (ret)
2607     {
2608         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2609
2610         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2611          "Wrong elements %d\n", seq->cValue);
2612         /* Just check the first element since it's all that changed */
2613         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2614          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2615          seq->rgValue[0].cbData);
2616         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2617          times[0].encodedTime[1] + 2), "Unexpected value\n");
2618         LocalFree(buf);
2619     }
2620 }
2621
2622 struct encodedExtensions
2623 {
2624     CERT_EXTENSIONS exts;
2625     const BYTE *encoded;
2626 };
2627
2628 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2629 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2630 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2631 static CERT_EXTENSION criticalExt =
2632  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2633 static CERT_EXTENSION nonCriticalExt =
2634  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2635 static CHAR oid_short[] = "1.1";
2636 static CERT_EXTENSION extWithShortOid =
2637  { oid_short, FALSE, { 0, NULL } };
2638
2639 static const BYTE ext0[] = { 0x30,0x00 };
2640 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2641                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2642 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2643                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2644 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2645
2646 static const struct encodedExtensions exts[] = {
2647  { { 0, NULL }, ext0 },
2648  { { 1, &criticalExt }, ext1 },
2649  { { 1, &nonCriticalExt }, ext2 },
2650  { { 1, &extWithShortOid }, ext3 }
2651 };
2652
2653 static void test_encodeExtensions(DWORD dwEncoding)
2654 {
2655     DWORD i;
2656
2657     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2658     {
2659         BOOL ret;
2660         BYTE *buf = NULL;
2661         DWORD bufSize = 0;
2662
2663         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2664          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2665         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2666         if (ret)
2667         {
2668             ok(bufSize == exts[i].encoded[1] + 2,
2669              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2670             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2671              "Unexpected value\n");
2672             LocalFree(buf);
2673         }
2674     }
2675 }
2676
2677 static void test_decodeExtensions(DWORD dwEncoding)
2678 {
2679     DWORD i;
2680
2681     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2682     {
2683         BOOL ret;
2684         BYTE *buf = NULL;
2685         DWORD bufSize = 0;
2686
2687         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2688          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2689          NULL, &buf, &bufSize);
2690         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2691         if (ret)
2692         {
2693             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2694             DWORD j;
2695
2696             ok(ext->cExtension == exts[i].exts.cExtension,
2697              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2698              ext->cExtension);
2699             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2700             {
2701                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2702                  exts[i].exts.rgExtension[j].pszObjId),
2703                  "Expected OID %s, got %s\n",
2704                  exts[i].exts.rgExtension[j].pszObjId,
2705                  ext->rgExtension[j].pszObjId);
2706                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2707                  exts[i].exts.rgExtension[j].Value.pbData,
2708                  exts[i].exts.rgExtension[j].Value.cbData),
2709                  "Unexpected value\n");
2710             }
2711             LocalFree(buf);
2712         }
2713         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2714          exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
2715         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2716         buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);
2717         if (buf)
2718         {
2719             ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2720              exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, buf, &bufSize);
2721             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2722             HeapFree(GetProcessHeap(), 0, buf);
2723         }
2724     }
2725 }
2726
2727 /* MS encodes public key info with a NULL if the algorithm identifier's
2728  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2729  * it encodes them by omitting the algorithm parameters.  It accepts either
2730  * form for decoding.
2731  */
2732 struct encodedPublicKey
2733 {
2734     CERT_PUBLIC_KEY_INFO info;
2735     const BYTE *encoded;
2736     const BYTE *encodedNoNull;
2737     CERT_PUBLIC_KEY_INFO decoded;
2738 };
2739
2740 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2741  0xe, 0xf };
2742 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2743
2744 static const unsigned char bin64[] = {
2745     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2746 static const unsigned char bin65[] = {
2747     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2748 static const unsigned char bin66[] = {
2749     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2750 static const unsigned char bin67[] = {
2751     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2752 static const unsigned char bin68[] = {
2753     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2754     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2755 static const unsigned char bin69[] = {
2756     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2757     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2758 static const unsigned char bin70[] = {
2759     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2760     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2761     0x0f};
2762 static const unsigned char bin71[] = {
2763     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2764     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2765     0x0f};
2766 static unsigned char bin72[] = { 0x05,0x00};
2767
2768 static CHAR oid_bogus[] = "1.2.3",
2769             oid_rsa[]   = szOID_RSA;
2770
2771 static const struct encodedPublicKey pubKeys[] = {
2772  /* with a bogus OID */
2773  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2774   bin64, bin65,
2775   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2776  /* some normal keys */
2777  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2778   bin66, bin67,
2779   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2780  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2781   bin68, bin69,
2782   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2783  /* with add'l parameters--note they must be DER-encoded */
2784  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2785   (BYTE *)aKey, 0 } },
2786   bin70, bin71,
2787   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2788   (BYTE *)aKey, 0 } } },
2789 };
2790
2791 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2792 {
2793     DWORD i;
2794
2795     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2796     {
2797         BOOL ret;
2798         BYTE *buf = NULL;
2799         DWORD bufSize = 0;
2800
2801         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2802          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2803          &bufSize);
2804         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2805          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2806         if (ret)
2807         {
2808             ok(bufSize == pubKeys[i].encoded[1] + 2,
2809              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2810             if (bufSize == pubKeys[i].encoded[1] + 2)
2811                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2812                  "Unexpected value\n");
2813             LocalFree(buf);
2814         }
2815     }
2816 }
2817
2818 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2819  const CERT_PUBLIC_KEY_INFO *got)
2820 {
2821     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2822      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2823      got->Algorithm.pszObjId);
2824     ok(expected->Algorithm.Parameters.cbData ==
2825      got->Algorithm.Parameters.cbData,
2826      "Expected parameters of %d bytes, got %d\n",
2827      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2828     if (expected->Algorithm.Parameters.cbData)
2829         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2830          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2831          "Unexpected algorithm parameters\n");
2832     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2833      "Expected public key of %d bytes, got %d\n",
2834      expected->PublicKey.cbData, got->PublicKey.cbData);
2835     if (expected->PublicKey.cbData)
2836         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2837          got->PublicKey.cbData), "Unexpected public key value\n");
2838 }
2839
2840 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2841 {
2842     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2843      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2844      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2845      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2846     DWORD i;
2847     BOOL ret;
2848     BYTE *buf = NULL;
2849     DWORD bufSize = 0;
2850
2851     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2852     {
2853         /* The NULL form decodes to the decoded member */
2854         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2855          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2856          NULL, &buf, &bufSize);
2857         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2858         if (ret)
2859         {
2860             comparePublicKeyInfo(&pubKeys[i].decoded,
2861              (CERT_PUBLIC_KEY_INFO *)buf);
2862             LocalFree(buf);
2863         }
2864         /* The non-NULL form decodes to the original */
2865         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2866          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2867          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2868         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2869         if (ret)
2870         {
2871             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2872             LocalFree(buf);
2873         }
2874     }
2875     /* Test with bogus (not valid DER) parameters */
2876     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2877      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2878      NULL, &buf, &bufSize);
2879     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2880      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2881      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2882      GetLastError());
2883 }
2884
2885 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2886  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2887  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2888  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2889  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2890 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2891  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2892  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2893  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2894  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2895 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2896  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2897  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2898  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2899  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2900 static const BYTE v4Cert[] = {
2901 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2902 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2903 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2904 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2905 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 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 v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2913  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2914  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2915  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2916  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2917  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2918  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2919 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2920  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2921  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2922  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2923  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2924  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2925  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2926  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2927  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2928  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2929 static const BYTE v1CertWithPubKey[] = {
2930 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2931 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2932 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2933 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2934 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2935 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2936 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2937 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2938 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2939 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2940 0x01,0x01 };
2941 static const BYTE v1CertWithPubKeyNoNull[] = {
2942 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2943 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2944 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2945 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2946 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,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,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2949 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2950 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2951 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2952 static const BYTE v1CertWithSubjectKeyId[] = {
2953 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2954 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2955 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2956 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2957 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2958 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2959 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2960 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2961 0x4c,0x61,0x6e,0x67,0x00 };
2962 static const BYTE v1CertWithIssuerUniqueId[] = {
2963 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2964 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2965 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2966 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2967 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2968 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2969 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2970 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2971 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2972 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2973 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2974 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2975 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2976 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2977 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2978 0x01,0x01,0xff,0x02,0x01,0x01 };
2979 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2980 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2981 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2982 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2983 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2984 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2985 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2986 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2987 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2988 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2989 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2990 0xff,0x02,0x01,0x01 };
2991
2992 static const BYTE serialNum[] = { 0x01 };
2993
2994 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2995 {
2996     BOOL ret;
2997     BYTE *buf = NULL;
2998     DWORD size = 0;
2999     CERT_INFO info = { 0 };
3000     static char oid_rsa_rsa[] = szOID_RSA_RSA;
3001     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
3002     CERT_EXTENSION ext;
3003
3004     if (0)
3005     {
3006         /* Test with NULL pvStructInfo (crashes on win9x) */
3007         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
3008          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3009         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3010          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3011     }
3012     /* Test with a V1 cert */
3013     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3014      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3015     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3016      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3017     if (ret)
3018     {
3019         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3020          v1Cert[1] + 2, size);
3021         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3022         LocalFree(buf);
3023     }
3024     /* Test v2 cert */
3025     info.dwVersion = CERT_V2;
3026     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3027      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3028     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3029      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3030     if (ret)
3031     {
3032         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3033         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3034         LocalFree(buf);
3035     }
3036     /* Test v3 cert */
3037     info.dwVersion = CERT_V3;
3038     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3039      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3040     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3041      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3042     if (ret)
3043     {
3044         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3045         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3046         LocalFree(buf);
3047     }
3048     /* A v4 cert? */
3049     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3050     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3051      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3052     if (ret)
3053     {
3054         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3055         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3056         LocalFree(buf);
3057     }
3058     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3059      * API doesn't prevent it)
3060      */
3061     info.dwVersion = CERT_V1;
3062     info.cExtension = 1;
3063     info.rgExtension = &criticalExt;
3064     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3065      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3066     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3067      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3068     if (ret)
3069     {
3070         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3071         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3072         LocalFree(buf);
3073     }
3074     /* test v1 cert with a serial number */
3075     info.SerialNumber.cbData = sizeof(serialNum);
3076     info.SerialNumber.pbData = (BYTE *)serialNum;
3077     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3078      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3079     if (ret)
3080     {
3081         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3082         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3083         LocalFree(buf);
3084     }
3085     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3086     info.dwVersion = CERT_V1;
3087     info.cExtension = 0;
3088     info.IssuerUniqueId.cbData = sizeof(serialNum);
3089     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3090     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3091      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3092     ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3093      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3094     if (ret)
3095     {
3096         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3097         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3098          "Got unexpected value\n");
3099         LocalFree(buf);
3100     }
3101     /* Test v1 cert with an issuer name, a subject name, and a serial number */
3102     info.IssuerUniqueId.cbData = 0;
3103     info.IssuerUniqueId.pbData = NULL;
3104     info.cExtension = 1;
3105     info.rgExtension = &criticalExt;
3106     info.Issuer.cbData = sizeof(encodedCommonName);
3107     info.Issuer.pbData = (BYTE *)encodedCommonName;
3108     info.Subject.cbData = sizeof(encodedCommonName);
3109     info.Subject.pbData = (BYTE *)encodedCommonName;
3110     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3111      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3112     if (ret)
3113     {
3114         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3115         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3116         LocalFree(buf);
3117     }
3118     /* Add a public key */
3119     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3120     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3121     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3122     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3123      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3124     if (ret)
3125     {
3126         ok(size == sizeof(v1CertWithPubKey) ||
3127          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3128         if (size == sizeof(v1CertWithPubKey))
3129             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3130         else if (size == sizeof(v1CertWithPubKeyNoNull))
3131             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3132              "Got unexpected value\n");
3133         LocalFree(buf);
3134     }
3135     /* Again add an issuer unique id */
3136     info.IssuerUniqueId.cbData = sizeof(serialNum);
3137     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3138     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3139      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3140     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3141     if (ret)
3142     {
3143         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3144          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3145          "Wrong size %d\n", size);
3146         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3147             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3148              size), "unexpected value\n");
3149         else if (size ==
3150          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3151             ok(!memcmp(buf,
3152              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3153              "unexpected value\n");
3154         LocalFree(buf);
3155     }
3156     /* Remove the public key, and add a subject key identifier extension */
3157     info.IssuerUniqueId.cbData = 0;
3158     info.IssuerUniqueId.pbData = NULL;
3159     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3160     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3161     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3162     ext.pszObjId = oid_subject_key_identifier;
3163     ext.fCritical = FALSE;
3164     ext.Value.cbData = sizeof(octetCommonNameValue);
3165     ext.Value.pbData = octetCommonNameValue;
3166     info.cExtension = 1;
3167     info.rgExtension = &ext;
3168     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3169      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3170     if (ret)
3171     {
3172         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3173         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3174         LocalFree(buf);
3175     }
3176 }
3177
3178 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3179 {
3180     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3181      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3182     BOOL ret;
3183     BYTE *buf = NULL;
3184     DWORD size = 0, i;
3185
3186     /* Test with NULL pbEncoded */
3187     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3188      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3189     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3190      GetLastError() == OSS_BAD_ARG /* Win9x */),
3191      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3192     if (0)
3193     {
3194         /* Crashes on win9x */
3195         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3196          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3197         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3198          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3199     }
3200     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3201      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3202      * serial number, an issuer, a subject, and a public key.
3203      */
3204     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3205     {
3206         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3207          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3208          &buf, &size);
3209         ok(!ret, "Expected failure\n");
3210     }
3211     /* The following succeeds, even though v1 certs are not allowed to have
3212      * extensions.
3213      */
3214     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3215      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3216      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3217     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3218     if (ret)
3219     {
3220         CERT_INFO *info = (CERT_INFO *)buf;
3221
3222         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3223         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3224          info->dwVersion);
3225         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3226          info->cExtension);
3227         LocalFree(buf);
3228     }
3229     /* The following also succeeds, even though V1 certs are not allowed to
3230      * have issuer unique ids.
3231      */
3232     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3233      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3234      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3235      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3236     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3237     if (ret)
3238     {
3239         CERT_INFO *info = (CERT_INFO *)buf;
3240
3241         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3242         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3243          info->dwVersion);
3244         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3245          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3246         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3247          "unexpected issuer unique id value\n");
3248         LocalFree(buf);
3249     }
3250     /* Now check with serial number, subject and issuer specified */
3251     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3252      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3253     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3254     if (ret)
3255     {
3256         CERT_INFO *info = (CERT_INFO *)buf;
3257
3258         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3259         ok(info->SerialNumber.cbData == 1,
3260          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3261         ok(*info->SerialNumber.pbData == *serialNum,
3262          "Expected serial number %d, got %d\n", *serialNum,
3263          *info->SerialNumber.pbData);
3264         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3265          "Wrong size %d\n", info->Issuer.cbData);
3266         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3267          "Unexpected issuer\n");
3268         ok(info->Subject.cbData == sizeof(encodedCommonName),
3269          "Wrong size %d\n", info->Subject.cbData);
3270         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3271          info->Subject.cbData), "Unexpected subject\n");
3272         LocalFree(buf);
3273     }
3274     /* Check again with pub key specified */
3275     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3276      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3277      &buf, &size);
3278     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3279     if (ret)
3280     {
3281         CERT_INFO *info = (CERT_INFO *)buf;
3282
3283         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3284         ok(info->SerialNumber.cbData == 1,
3285          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3286         ok(*info->SerialNumber.pbData == *serialNum,
3287          "Expected serial number %d, got %d\n", *serialNum,
3288          *info->SerialNumber.pbData);
3289         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3290          "Wrong size %d\n", info->Issuer.cbData);
3291         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3292          "Unexpected issuer\n");
3293         ok(info->Subject.cbData == sizeof(encodedCommonName),
3294          "Wrong size %d\n", info->Subject.cbData);
3295         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3296          info->Subject.cbData), "Unexpected subject\n");
3297         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3298          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3299          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3300         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3301          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3302         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3303          sizeof(aKey)), "Unexpected public key\n");
3304         LocalFree(buf);
3305     }
3306 }
3307
3308 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3309  0xe, 0xf };
3310
3311 static const BYTE signedBigCert[] = {
3312  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3313  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3314  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3315  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3316  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3317  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3318  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3319  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3320  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3321  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3322  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3323  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3324
3325 static void test_encodeCert(DWORD dwEncoding)
3326 {
3327     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3328      * also that bigCert is a NULL-terminated string, so don't count its
3329      * last byte (otherwise the signed cert won't decode.)
3330      */
3331     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3332      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3333     BOOL ret;
3334     BYTE *buf = NULL;
3335     DWORD bufSize = 0;
3336
3337     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3338      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3339     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3340     if (ret)
3341     {
3342         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3343         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3344         LocalFree(buf);
3345     }
3346 }
3347
3348 static void test_decodeCert(DWORD dwEncoding)
3349 {
3350     BOOL ret;
3351     BYTE *buf = NULL;
3352     DWORD size = 0;
3353
3354     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3355      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3356     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3357     if (ret)
3358     {
3359         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3360
3361         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3362          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3363         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3364          "Unexpected cert\n");
3365         ok(info->Signature.cbData == sizeof(hash),
3366          "Wrong signature size %d\n", info->Signature.cbData);
3367         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3368          "Unexpected signature\n");
3369         LocalFree(buf);
3370     }
3371     /* A signed cert decodes as a CERT_INFO too */
3372     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3373      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3374     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3375     if (ret)
3376     {
3377         CERT_INFO *info = (CERT_INFO *)buf;
3378
3379         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3380         ok(info->SerialNumber.cbData == 1,
3381          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3382         ok(*info->SerialNumber.pbData == *serialNum,
3383          "Expected serial number %d, got %d\n", *serialNum,
3384          *info->SerialNumber.pbData);
3385         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3386          "Wrong size %d\n", info->Issuer.cbData);
3387         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3388          "Unexpected issuer\n");
3389         ok(info->Subject.cbData == sizeof(encodedCommonName),
3390          "Wrong size %d\n", info->Subject.cbData);
3391         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3392          info->Subject.cbData), "Unexpected subject\n");
3393         LocalFree(buf);
3394     }
3395 }
3396
3397 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3398 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3399  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3400  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3401 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3402  0x00, 0x03 };
3403 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3404  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3405  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3406 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3407  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3408  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3409  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3410  0x2e, 0x6f, 0x72, 0x67 };
3411 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3412  CRL_REASON_AFFILIATION_CHANGED;
3413
3414 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3415 {
3416     CRL_DIST_POINTS_INFO info = { 0 };
3417     CRL_DIST_POINT point = { { 0 } };
3418     CERT_ALT_NAME_ENTRY entry = { 0 };
3419     BOOL ret;
3420     BYTE *buf = NULL;
3421     DWORD size = 0;
3422
3423     /* Test with an empty info */
3424     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3425      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3426     ok(!ret && GetLastError() == E_INVALIDARG,
3427      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3428     /* Test with one empty dist point */
3429     info.cDistPoint = 1;
3430     info.rgDistPoint = &point;
3431     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3432      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3433     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3434     if (ret)
3435     {
3436         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3437         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3438         LocalFree(buf);
3439     }
3440     /* A dist point with an invalid name */
3441     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3442     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3443     U(entry).pwszURL = (LPWSTR)nihongoURL;
3444     U(point.DistPointName).FullName.cAltEntry = 1;
3445     U(point.DistPointName).FullName.rgAltEntry = &entry;
3446     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3447      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3448     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3449      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3450     /* The first invalid character is at index 7 */
3451     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3452      "Expected invalid char at index 7, got %d\n",
3453      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3454     /* A dist point with (just) a valid name */
3455     U(entry).pwszURL = (LPWSTR)url;
3456     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3457      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3458     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3459     if (ret)
3460     {
3461         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3462         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3463         LocalFree(buf);
3464     }
3465     /* A dist point with (just) reason flags */
3466     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3467     point.ReasonFlags.cbData = sizeof(crlReason);
3468     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3469     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3470      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3471     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3472     if (ret)
3473     {
3474         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3475         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3476         LocalFree(buf);
3477     }
3478     /* A dist point with just an issuer */
3479     point.ReasonFlags.cbData = 0;
3480     point.CRLIssuer.cAltEntry = 1;
3481     point.CRLIssuer.rgAltEntry = &entry;
3482     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3483      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3484     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3485     if (ret)
3486     {
3487         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3488         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3489         LocalFree(buf);
3490     }
3491     /* A dist point with both a name and an issuer */
3492     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3493     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3494      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3495     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3496     if (ret)
3497     {
3498         ok(size == sizeof(distPointWithUrlAndIssuer),
3499          "Wrong size %d\n", size);
3500         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3501         LocalFree(buf);
3502     }
3503 }
3504
3505 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3506 {
3507     BOOL ret;
3508     BYTE *buf = NULL;
3509     DWORD size = 0;
3510     PCRL_DIST_POINTS_INFO info;
3511     PCRL_DIST_POINT point;
3512     PCERT_ALT_NAME_ENTRY entry;
3513
3514     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3515      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3516      &buf, &size);
3517     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3518     if (ret)
3519     {
3520         info = (PCRL_DIST_POINTS_INFO)buf;
3521         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3522          "Wrong size %d\n", size);
3523         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3524          info->cDistPoint);
3525         point = info->rgDistPoint;
3526         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3527          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3528          point->DistPointName.dwDistPointNameChoice);
3529         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3530         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3531         LocalFree(buf);
3532     }
3533     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3534      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3535      &buf, &size);
3536     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3537     if (ret)
3538     {
3539         info = (PCRL_DIST_POINTS_INFO)buf;
3540         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3541          "Wrong size %d\n", size);
3542         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3543          info->cDistPoint);
3544         point = info->rgDistPoint;
3545         ok(point->DistPointName.dwDistPointNameChoice ==
3546          CRL_DIST_POINT_FULL_NAME,
3547          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3548          point->DistPointName.dwDistPointNameChoice);
3549         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3550          "Expected 1 name entry, got %d\n",
3551          U(point->DistPointName).FullName.cAltEntry);
3552         entry = U(point->DistPointName).FullName.rgAltEntry;
3553         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3554          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3555         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3556         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3557         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3558         LocalFree(buf);
3559     }
3560     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3561      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3562      NULL, &buf, &size);
3563     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3564     if (ret)
3565     {
3566         info = (PCRL_DIST_POINTS_INFO)buf;
3567         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3568          "Wrong size %d\n", size);
3569         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3570          info->cDistPoint);
3571         point = info->rgDistPoint;
3572         ok(point->DistPointName.dwDistPointNameChoice ==
3573          CRL_DIST_POINT_NO_NAME,
3574          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3575          point->DistPointName.dwDistPointNameChoice);
3576         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3577          "Expected reason length\n");
3578         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3579          "Unexpected reason\n");
3580         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3581         LocalFree(buf);
3582     }
3583     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3584      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3585      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3586     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3587     if (ret)
3588     {
3589         info = (PCRL_DIST_POINTS_INFO)buf;
3590         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3591          "Wrong size %d\n", size);
3592         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3593          info->cDistPoint);
3594         point = info->rgDistPoint;
3595         ok(point->DistPointName.dwDistPointNameChoice ==
3596          CRL_DIST_POINT_FULL_NAME,
3597          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3598          point->DistPointName.dwDistPointNameChoice);
3599         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3600          "Expected 1 name entry, got %d\n",
3601          U(point->DistPointName).FullName.cAltEntry);
3602         entry = U(point->DistPointName).FullName.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         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3607         ok(point->CRLIssuer.cAltEntry == 1,
3608          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3609         entry = point->CRLIssuer.rgAltEntry;
3610         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3611          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3612         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3613         LocalFree(buf);
3614     }
3615     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3616      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3617      NULL, NULL, &size);
3618     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3619     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3620     if (buf)
3621     {
3622         ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3623          distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3624          NULL, buf, &size);
3625         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3626         HeapFree(GetProcessHeap(), 0, buf);
3627     }
3628 }
3629
3630 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3631 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3632 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3633  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3634  0x67 };
3635
3636 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3637 {
3638     BOOL ret;
3639     BYTE *buf = NULL;
3640     DWORD size = 0;
3641     CRL_ISSUING_DIST_POINT point = { { 0 } };
3642     CERT_ALT_NAME_ENTRY entry;
3643
3644     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3645      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3646     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3647     {
3648         skip("no X509_ISSUING_DIST_POINT encode support\n");
3649         return;
3650     }
3651     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3652      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3653     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3654      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3655     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3656     if (ret)
3657     {
3658         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3659         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3660         LocalFree(buf);
3661     }
3662     /* nonsensical flags */
3663     point.fOnlyContainsUserCerts = TRUE;
3664     point.fOnlyContainsCACerts = TRUE;
3665     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3666      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3667     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3668     if (ret)
3669     {
3670         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3671         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3672         LocalFree(buf);
3673     }
3674     /* unimplemented name type */
3675     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3676     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3677     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3678      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3679     ok(!ret && GetLastError() == E_INVALIDARG,
3680      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3681     /* empty name */
3682     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3683     U(point.DistPointName).FullName.cAltEntry = 0;
3684     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3685      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3686     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3687     if (ret)
3688     {
3689         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3690         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3691         LocalFree(buf);
3692     }
3693     /* name with URL entry */
3694     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3695     U(entry).pwszURL = (LPWSTR)url;
3696     U(point.DistPointName).FullName.cAltEntry = 1;
3697     U(point.DistPointName).FullName.rgAltEntry = &entry;
3698     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3699      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3700     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3701     if (ret)
3702     {
3703         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3704         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3705         LocalFree(buf);
3706     }
3707 }
3708
3709 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3710  const CERT_ALT_NAME_ENTRY *got)
3711 {
3712     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3713      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3714      got->dwAltNameChoice);
3715     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3716     {
3717         switch (got->dwAltNameChoice)
3718         {
3719         case CERT_ALT_NAME_RFC822_NAME:
3720         case CERT_ALT_NAME_DNS_NAME:
3721         case CERT_ALT_NAME_EDI_PARTY_NAME:
3722         case CERT_ALT_NAME_URL:
3723         case CERT_ALT_NAME_REGISTERED_ID:
3724             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3725              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3726              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3727              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3728              "Unexpected name\n");
3729             break;
3730         case CERT_ALT_NAME_X400_ADDRESS:
3731         case CERT_ALT_NAME_DIRECTORY_NAME:
3732         case CERT_ALT_NAME_IP_ADDRESS:
3733             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3734                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3735             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3736                        U(*got).IPAddress.cbData), "Unexpected value\n");
3737             break;
3738         }
3739     }
3740 }
3741
3742 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3743  const CERT_ALT_NAME_INFO *got)
3744 {
3745     DWORD i;
3746
3747     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3748      expected->cAltEntry, got->cAltEntry);
3749     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3750         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3751 }
3752
3753 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3754  const CRL_DIST_POINT_NAME *got)
3755 {
3756     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3757      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3758     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3759         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3760 }
3761
3762 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3763  const CRL_ISSUING_DIST_POINT *got)
3764 {
3765     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3766     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3767      "Unexpected fOnlyContainsUserCerts\n");
3768     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3769      "Unexpected fOnlyContainsCACerts\n");
3770     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3771      "Unexpected reason flags\n");
3772     ok(got->fIndirectCRL == expected->fIndirectCRL,
3773      "Unexpected fIndirectCRL\n");
3774 }
3775
3776 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3777 {
3778     BOOL ret;
3779     BYTE *buf = NULL;
3780     DWORD size = 0;
3781     CRL_ISSUING_DIST_POINT point = { { 0 } };
3782
3783     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3784      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3785      &buf, &size);
3786     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3787     {
3788         skip("no X509_ISSUING_DIST_POINT decode support\n");
3789         return;
3790     }
3791     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3792     if (ret)
3793     {
3794         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3795         LocalFree(buf);
3796     }
3797     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3798      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3799      &buf, &size);
3800     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3801     if (ret)
3802     {
3803         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3804         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3805         LocalFree(buf);
3806     }
3807     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3808      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3809      &buf, &size);
3810     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3811     if (ret)
3812     {
3813         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3814         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3815         U(point.DistPointName).FullName.cAltEntry = 0;
3816         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3817         LocalFree(buf);
3818     }
3819     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3820      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3821     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3822     if (ret)
3823     {
3824         CERT_ALT_NAME_ENTRY entry;
3825
3826         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3827         U(entry).pwszURL = (LPWSTR)url;
3828         U(point.DistPointName).FullName.cAltEntry = 1;
3829         U(point.DistPointName).FullName.rgAltEntry = &entry;
3830         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3831         LocalFree(buf);
3832     }
3833 }
3834
3835 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3836  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3837  0x30, 0x5a };
3838 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3839  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3840  0x30, 0x30, 0x30, 0x30, 0x5a };
3841 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3842  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3843  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3844  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3845  0x5a };
3846 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3847  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3848  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3849  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3850  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3851  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3852 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3853  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3854  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3855  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3856  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3857  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3858 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3859  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3860  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3861  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3862  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3863  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3864  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3865 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3866  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3867  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3868  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3869  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3870  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3871  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3872 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3873  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3874  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3875  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3876  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3877  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3878  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3879
3880 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3881 {
3882     BOOL ret;
3883     BYTE *buf = NULL;
3884     DWORD size = 0;
3885     CRL_INFO info = { 0 };
3886     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3887
3888     /* Test with a V1 CRL */
3889     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3890      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3891     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3892      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3893     if (ret)
3894     {
3895         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3896         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3897         LocalFree(buf);
3898     }
3899     /* Test v2 CRL */
3900     info.dwVersion = CRL_V2;
3901     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3902      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3903     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3904      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3905     if (ret)
3906     {
3907         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3908          v2CRL[1] + 2, size);
3909         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3910         LocalFree(buf);
3911     }
3912     /* v1 CRL with a name */
3913     info.dwVersion = CRL_V1;
3914     info.Issuer.cbData = sizeof(encodedCommonName);
3915     info.Issuer.pbData = (BYTE *)encodedCommonName;
3916     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3917      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3918     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3919     if (ret)
3920     {
3921         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3922         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3923         LocalFree(buf);
3924     }
3925     if (0)
3926     {
3927         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3928         info.cCRLEntry = 1;
3929         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3930          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3931         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3932          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3933     }
3934     /* now set an empty entry */
3935     info.cCRLEntry = 1;
3936     info.rgCRLEntry = &entry;
3937     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3938      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3939     if (ret)
3940     {
3941         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3942          "Wrong size %d\n", size);
3943         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3944          "Got unexpected value\n");
3945         LocalFree(buf);
3946     }
3947     /* an entry with a serial number */
3948     entry.SerialNumber.cbData = sizeof(serialNum);
3949     entry.SerialNumber.pbData = (BYTE *)serialNum;
3950     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3951      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3952     if (ret)
3953     {
3954         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3955          "Wrong size %d\n", size);
3956         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3957          "Got unexpected value\n");
3958         LocalFree(buf);
3959     }
3960     /* an entry with an extension */
3961     entry.cExtension = 1;
3962     entry.rgExtension = &criticalExt;
3963     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3964      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3965     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3966     if (ret)
3967     {
3968         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3969         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3970         LocalFree(buf);
3971     }
3972     /* a CRL with an extension */
3973     entry.cExtension = 0;
3974     info.cExtension = 1;
3975     info.rgExtension = &criticalExt;
3976     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3977      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3978     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3979     if (ret)
3980     {
3981         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3982         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3983         LocalFree(buf);
3984     }
3985     /* a v2 CRL with an extension, this time non-critical */
3986     info.dwVersion = CRL_V2;
3987     info.rgExtension = &nonCriticalExt;
3988     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3989      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3990     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3991     if (ret)
3992     {
3993         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3994         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3995         LocalFree(buf);
3996     }
3997 }
3998
3999 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
4000  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4001  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
4002  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
4003  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
4004  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
4005  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
4006  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
4007  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
4008  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
4009  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
4010  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
4011  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
4012  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
4013  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
4014  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
4015  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
4016  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
4017  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
4018  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
4019  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
4020  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
4021  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
4022  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
4023  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4024  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4025  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4026  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4027  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4028  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4029  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4030  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4031  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4032  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4033  0xcd };
4034 static const BYTE verisignCRLWithLotsOfEntries[] = {
4035 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4036 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4037 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4038 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4039 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4040 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4041 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4042 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4043 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4044 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4045 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4046 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4047 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4048 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4049 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4050 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4051 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4052 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4053 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4054 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4055 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4056 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4057 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4058 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4059 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4060 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4061 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4062 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4063 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4064 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4065 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4066 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4067 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4068 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4069 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4070 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4071 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4072 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4073 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4074 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4075 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4076 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4077 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4078 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4079 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4080 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4081 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4082 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4083 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4084 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4085 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4086 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4087 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4088 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4089 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4090 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4091 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4092 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4093 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4094 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4095 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4096 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4097 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4098 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4099 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4100 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4101 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4102 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4103 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4104 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4105 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4106 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4107 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4108 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4109 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4110 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4111 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4112 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4113 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4114 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4115 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4116 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4117 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4118 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4119 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4120 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4121 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4122 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4123 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4124 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4125 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4126 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4127 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4128 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4129 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4130 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4131 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4132 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4133 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4134 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4135 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4136 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4137 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4138 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4139 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4140 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4141 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4142 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4143 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4144 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4145 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4146 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4147 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4148 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4149 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4150 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4151 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4152 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4153 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4154 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4155 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4156 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4157 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4158 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4159 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4160 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4161 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4162 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4163 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4164 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4165 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4166 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4167 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4168 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4169 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4170 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4171 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4172 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4173 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4174 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4175 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4176 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4177 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4178 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4179 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4180 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4181 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4182 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4183 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4184 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4185 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4186 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4187 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4188 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4189 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4190 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4191 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4192 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4193 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4194 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4195 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4196 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4197 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4198 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4199 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4200 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4201 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4202 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4203 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4204 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4205 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4206 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4207 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4208 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4209 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4210 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4211 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4212 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4213 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4214 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4215 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4216 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4217 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4218 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4219 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4220 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4221 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4222 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4223 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4224 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4225 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4226 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4227 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4228 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4229 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4230 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4231 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4232 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4233 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4234 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4235 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4236 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4237 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4238 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4239 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4240 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4241 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4242 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4243 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4244 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4245 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4246 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4247 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4248 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4249 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4250 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4251 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4252 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4253 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4254 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4255 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4256 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4257 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4258 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4259 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4260 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4261 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4262 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4263 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4264 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4265 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4266 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4267 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4268 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4269 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4270 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4271 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4272 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4273 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4274 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4275 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4276 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4277 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4278 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4279 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4280 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4281 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4282 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4283 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4284 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4285 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4286 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4287 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4288 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4289 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4290 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4291 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4292 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4293 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4294 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4295 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4296 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4297 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4298 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4299 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4300 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4301 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4302 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4303 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4304 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4305 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4306 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4307 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4308 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4309 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4310 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4311 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4312 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4313 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4314 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4315 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4316 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4317 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4318 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4319 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4320 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4321 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4322 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4323 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4324 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4325 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4326 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4327 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4328 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4329 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4330 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4331 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4332 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4333 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4334 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4335 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4336 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4337 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4338 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4339 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4340 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4341 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4342 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4343 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4344 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4345 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4346 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4347 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4348 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4349 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4350 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4351 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4352 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4353 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4354 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4355 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4356 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4357 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4358 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4359 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4360 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4361 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4362 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4363 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4364 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4365 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4366 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4367 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4368 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4369 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4370 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4371 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4372 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4373 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4374 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4375 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4376 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4377 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4378 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4379 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4380 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4381 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4382 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4383 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4384 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4385 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4386 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4387 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4388 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4389 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4390 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4391 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4392 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4393 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4394 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4395 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4396 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4397 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4398 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4399 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4400 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4401 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4402 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4403 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4404 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4405 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4406 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4407 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4408 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4409 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4410 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4411 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4412 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4413 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4414 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4415 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4416 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4417 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4418 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4419 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4420 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4421 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4422 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4423 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4424 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4425 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4426 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4427 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4428 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4429 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4430 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4431 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4432 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4433 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4434 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4435 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4436 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4437 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4438 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4439 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4440 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4441 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4442 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4443 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4444 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4445 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4446 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4447 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4448 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4449 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4450 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4451 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4452 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4453 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4454 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4455 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4456 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4457 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4458 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4459 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4460 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4461 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4462 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4463 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4464 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4465 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4466 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4467 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4468 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4469 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4470 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4471 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4472 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4473 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4474 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4475 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4476 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4477 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4478 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4479 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4480 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4481 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4482 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4483 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4484 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4485 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4486 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4487 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4488 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4489 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4490 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4491 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4492 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4493 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4494 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4495 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4496 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4497 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4498 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4499 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4500 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4501 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4502 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4503 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4504 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4505 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4506 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4507 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4508 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4509 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4510 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4511 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4512 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4513 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4514 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4515 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4516 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4517 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4518 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4519 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4520 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4521 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4522 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4523 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4524 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4525 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4526 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4527 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4528 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4529 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4530 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4531 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4532 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4533 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4534 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4535 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4536 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4537 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4538 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4539 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4540 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4541 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4542 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4543
4544 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4545 {
4546     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4547     BOOL ret;
4548     BYTE *buf = NULL;
4549     DWORD size = 0, i;
4550
4551     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4552     {
4553         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4554          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4555          &buf, &size);
4556         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4557          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4558          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4559          GetLastError());
4560     }
4561     /* at a minimum, a CRL must contain an issuer: */
4562     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4563      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4564      &buf, &size);
4565     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4566     if (ret)
4567     {
4568         CRL_INFO *info = (CRL_INFO *)buf;
4569
4570         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4571         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4572          info->cCRLEntry);
4573         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4574          "Wrong issuer size %d\n", info->Issuer.cbData);
4575         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4576          "Unexpected issuer\n");
4577         LocalFree(buf);
4578     }
4579     /* check decoding with an empty CRL entry */
4580     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4581      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4582      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4583     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4584      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4585      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4586      GetLastError());
4587     /* with a real CRL entry */
4588     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4589      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4590      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4591     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4592     if (ret)
4593     {
4594         CRL_INFO *info = (CRL_INFO *)buf;
4595         CRL_ENTRY *entry;
4596
4597         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4598         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4599          info->cCRLEntry);
4600         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4601         entry = info->rgCRLEntry;
4602         ok(entry->SerialNumber.cbData == 1,
4603          "Expected serial number size 1, got %d\n",
4604          entry->SerialNumber.cbData);
4605         ok(*entry->SerialNumber.pbData == *serialNum,
4606          "Expected serial number %d, got %d\n", *serialNum,
4607          *entry->SerialNumber.pbData);
4608         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4609          "Wrong issuer size %d\n", info->Issuer.cbData);
4610         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4611          "Unexpected issuer\n");
4612         LocalFree(buf);
4613     }
4614     /* a real CRL from verisign that has extensions */
4615     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4616      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4617      NULL, &buf, &size);
4618     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4619     if (ret)
4620     {
4621         CRL_INFO *info = (CRL_INFO *)buf;
4622
4623         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4624         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4625          info->cCRLEntry);
4626         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4627         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4628          info->cExtension);
4629         LocalFree(buf);
4630     }
4631     /* another real CRL from verisign that has lots of entries */
4632     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4633      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4634      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4635     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4636     if (ret)
4637     {
4638         CRL_INFO *info = (CRL_INFO *)buf;
4639
4640         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4641         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4642          info->cCRLEntry);
4643         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4644          info->cExtension);
4645         LocalFree(buf);
4646     }
4647     /* and finally, with an extension */
4648     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4649      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4650      NULL, &buf, &size);
4651     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4652     if (ret)
4653     {
4654         CRL_INFO *info = (CRL_INFO *)buf;
4655         CRL_ENTRY *entry;
4656
4657         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4658         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4659          info->cCRLEntry);
4660         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4661         entry = info->rgCRLEntry;
4662         ok(entry->SerialNumber.cbData == 1,
4663          "Expected serial number size 1, got %d\n",
4664          entry->SerialNumber.cbData);
4665         ok(*entry->SerialNumber.pbData == *serialNum,
4666          "Expected serial number %d, got %d\n", *serialNum,
4667          *entry->SerialNumber.pbData);
4668         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4669          "Wrong issuer size %d\n", info->Issuer.cbData);
4670         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4671          "Unexpected issuer\n");
4672         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4673          info->cExtension);
4674         LocalFree(buf);
4675     }
4676     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4677      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4678      NULL, &buf, &size);
4679     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4680     if (ret)
4681     {
4682         CRL_INFO *info = (CRL_INFO *)buf;
4683
4684         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4685          info->cExtension);
4686         LocalFree(buf);
4687     }
4688 }
4689
4690 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4691  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4692 static const BYTE encodedUsage[] = {
4693  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4694  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4695  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4696
4697 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4698 {
4699     BOOL ret;
4700     BYTE *buf = NULL;
4701     DWORD size = 0;
4702     CERT_ENHKEY_USAGE usage;
4703
4704     /* Test with empty usage */
4705     usage.cUsageIdentifier = 0;
4706     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4707      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4708     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4709     if (ret)
4710     {
4711         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4712         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4713         LocalFree(buf);
4714     }
4715     /* Test with a few usages */
4716     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4717     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4718     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4719      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4720     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4721     if (ret)
4722     {
4723         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4724         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4725         LocalFree(buf);
4726     }
4727 }
4728
4729 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4730 {
4731     BOOL ret;
4732     LPBYTE buf = NULL;
4733     DWORD size = 0;
4734
4735     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4736      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4737      &buf, &size);
4738     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4739     if (ret)
4740     {
4741         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4742
4743         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4744          "Wrong size %d\n", size);
4745         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4746          usage->cUsageIdentifier);
4747         LocalFree(buf);
4748     }
4749     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4750      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4751      &buf, &size);
4752     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4753     if (ret)
4754     {
4755         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4756         DWORD i;
4757
4758         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4759          "Wrong size %d\n", size);
4760         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4761          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4762         for (i = 0; i < usage->cUsageIdentifier; i++)
4763             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4764              "Expected OID %s, got %s\n", keyUsages[i],
4765              usage->rgpszUsageIdentifier[i]);
4766         LocalFree(buf);
4767     }
4768     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4769      encodedUsage, sizeof(encodedUsage), 0, NULL, NULL, &size);
4770     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4771     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4772     if (buf)
4773     {
4774         ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4775          encodedUsage, sizeof(encodedUsage), 0, NULL, buf, &size);
4776         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4777         HeapFree(GetProcessHeap(), 0, buf);
4778     }
4779 }
4780
4781 static BYTE keyId[] = { 1,2,3,4 };
4782 static const BYTE authorityKeyIdWithId[] = {
4783  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4784 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4785  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4786  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4787 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4788
4789 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4790 {
4791     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4792     BOOL ret;
4793     BYTE *buf = NULL;
4794     DWORD size = 0;
4795
4796     /* Test with empty id */
4797     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4798      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4799     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4800     if (ret)
4801     {
4802         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4803         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4804         LocalFree(buf);
4805     }
4806     /* With just a key id */
4807     info.KeyId.cbData = sizeof(keyId);
4808     info.KeyId.pbData = keyId;
4809     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4810      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4811     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4812     if (ret)
4813     {
4814         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4815         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4816         LocalFree(buf);
4817     }
4818     /* With just an issuer */
4819     info.KeyId.cbData = 0;
4820     info.CertIssuer.cbData = sizeof(encodedCommonName);
4821     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4822     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4823      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4824     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4825     if (ret)
4826     {
4827         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4828          size);
4829         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4830         LocalFree(buf);
4831     }
4832     /* With just a serial number */
4833     info.CertIssuer.cbData = 0;
4834     info.CertSerialNumber.cbData = sizeof(serialNum);
4835     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4836     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4837      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4838     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4839     if (ret)
4840     {
4841         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4842          size);
4843         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4844         LocalFree(buf);
4845     }
4846 }
4847
4848 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4849 {
4850     BOOL ret;
4851     LPBYTE buf = NULL;
4852     DWORD size = 0;
4853
4854     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4855      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4856      &buf, &size);
4857     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4858     if (ret)
4859     {
4860         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4861
4862         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4863          size);
4864         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4865         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4866         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4867         LocalFree(buf);
4868     }
4869     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4870      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4871      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4872     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4873     if (ret)
4874     {
4875         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4876
4877         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4878          size);
4879         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4880         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4881          "Unexpected key id\n");
4882         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4883         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4884         LocalFree(buf);
4885     }
4886     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4887      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4888      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4889     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4890     if (ret)
4891     {
4892         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4893
4894         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4895          size);
4896         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4897         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4898          "Unexpected issuer len\n");
4899         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4900          sizeof(encodedCommonName)), "Unexpected issuer\n");
4901         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4902         LocalFree(buf);
4903     }
4904     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4905      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4906      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4907     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4908     if (ret)
4909     {
4910         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4911
4912         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4913          size);
4914         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4915         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4916         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4917          "Unexpected serial number len\n");
4918         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4919          "Unexpected serial number\n");
4920         LocalFree(buf);
4921     }
4922 }
4923
4924 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4925  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4926  0x6f,0x72,0x67 };
4927
4928 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4929 {
4930     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4931     CERT_ALT_NAME_ENTRY entry = { 0 };
4932     BOOL ret;
4933     BYTE *buf = NULL;
4934     DWORD size = 0;
4935
4936     /* Test with empty id */
4937     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4938      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4939     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4940     if (ret)
4941     {
4942         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4943         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4944         LocalFree(buf);
4945     }
4946     /* With just a key id */
4947     info.KeyId.cbData = sizeof(keyId);
4948     info.KeyId.pbData = keyId;
4949     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4950      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4951     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4952     if (ret)
4953     {
4954         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4955          size);
4956         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4957         LocalFree(buf);
4958     }
4959     /* With a bogus issuer name */
4960     info.KeyId.cbData = 0;
4961     info.AuthorityCertIssuer.cAltEntry = 1;
4962     info.AuthorityCertIssuer.rgAltEntry = &entry;
4963     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4964      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4965     ok(!ret && GetLastError() == E_INVALIDARG,
4966      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4967     /* With an issuer name */
4968     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4969     U(entry).pwszURL = (LPWSTR)url;
4970     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4971      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4972     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4973     if (ret)
4974     {
4975         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4976          size);
4977         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4978          "Unexpected value\n");
4979         LocalFree(buf);
4980     }
4981     /* With just a serial number */
4982     info.AuthorityCertIssuer.cAltEntry = 0;
4983     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4984     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4985     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4986      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4987     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4988     if (ret)
4989     {
4990         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4991          size);
4992         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4993         LocalFree(buf);
4994     }
4995 }
4996
4997 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4998 {
4999     BOOL ret;
5000     LPBYTE buf = NULL;
5001     DWORD size = 0;
5002
5003     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5004      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5005      &buf, &size);
5006     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5007     if (ret)
5008     {
5009         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5010
5011         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5012          size);
5013         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5014         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5015          "Expected no issuer name entries\n");
5016         ok(info->AuthorityCertSerialNumber.cbData == 0,
5017          "Expected no serial number\n");
5018         LocalFree(buf);
5019     }
5020     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5021      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5022      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5023     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5024     if (ret)
5025     {
5026         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5027
5028         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5029          size);
5030         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5031         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5032          "Unexpected key id\n");
5033         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5034          "Expected no issuer name entries\n");
5035         ok(info->AuthorityCertSerialNumber.cbData == 0,
5036          "Expected no serial number\n");
5037         LocalFree(buf);
5038     }
5039     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5040      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5041      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5042     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5043     if (ret)
5044     {
5045         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5046
5047         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5048          size);
5049         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5050         ok(info->AuthorityCertIssuer.cAltEntry == 1,
5051          "Expected 1 issuer entry, got %d\n",
5052          info->AuthorityCertIssuer.cAltEntry);
5053         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5054          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5055          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5056         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5057          url), "Unexpected URL\n");
5058         ok(info->AuthorityCertSerialNumber.cbData == 0,
5059          "Expected no serial number\n");
5060         LocalFree(buf);
5061     }
5062     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5063      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5064      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5065     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5066     if (ret)
5067     {
5068         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5069
5070         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5071          size);
5072         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5073         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5074          "Expected no issuer name entries\n");
5075         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5076          "Unexpected serial number len\n");
5077         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5078          sizeof(serialNum)), "Unexpected serial number\n");
5079         LocalFree(buf);
5080     }
5081 }
5082
5083 static const BYTE authorityInfoAccessWithUrl[] = {
5084 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5085 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5086 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5087 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5088 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5089 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5090
5091 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5092 {
5093     static char oid1[] = "1.2.3";
5094     static char oid2[] = "1.5.6";
5095     BOOL ret;
5096     BYTE *buf = NULL;
5097     DWORD size = 0;
5098     CERT_ACCESS_DESCRIPTION accessDescription[2];
5099     CERT_AUTHORITY_INFO_ACCESS aia;
5100
5101     memset(accessDescription, 0, sizeof(accessDescription));
5102     aia.cAccDescr = 0;
5103     aia.rgAccDescr = NULL;
5104     /* Having no access descriptions is allowed */
5105     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5106      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5107     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5108     if (ret)
5109     {
5110         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5111         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5112         LocalFree(buf);
5113         buf = NULL;
5114     }
5115     /* It can't have an empty access method */
5116     aia.cAccDescr = 1;
5117     aia.rgAccDescr = accessDescription;
5118     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5119      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5120     ok(!ret && (GetLastError() == E_INVALIDARG ||
5121      GetLastError() == OSS_LIMITED /* Win9x */),
5122      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5123     /* It can't have an empty location */
5124     accessDescription[0].pszAccessMethod = oid1;
5125     SetLastError(0xdeadbeef);
5126     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5127      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5128     ok(!ret && GetLastError() == E_INVALIDARG,
5129      "expected E_INVALIDARG, got %08x\n", GetLastError());
5130     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5131     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5132     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5133      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5134     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5135     if (ret)
5136     {
5137         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5138          size);
5139         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5140          "unexpected value\n");
5141         LocalFree(buf);
5142         buf = NULL;
5143     }
5144     accessDescription[1].pszAccessMethod = oid2;
5145     accessDescription[1].AccessLocation.dwAltNameChoice =
5146      CERT_ALT_NAME_IP_ADDRESS;
5147     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5148      sizeof(encodedIPAddr);
5149     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5150      (LPBYTE)encodedIPAddr;
5151     aia.cAccDescr = 2;
5152     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5153      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5154     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5155     if (ret)
5156     {
5157         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5158          "unexpected size %d\n", size);
5159         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5160          "unexpected value\n");
5161         LocalFree(buf);
5162         buf = NULL;
5163     }
5164 }
5165
5166 static void compareAuthorityInfoAccess(LPCSTR header,
5167  const CERT_AUTHORITY_INFO_ACCESS *expected,
5168  const CERT_AUTHORITY_INFO_ACCESS *got)
5169 {
5170     DWORD i;
5171
5172     ok(expected->cAccDescr == got->cAccDescr,
5173      "%s: expected %d access descriptions, got %d\n", header,
5174      expected->cAccDescr, got->cAccDescr);
5175     for (i = 0; i < expected->cAccDescr; i++)
5176     {
5177         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5178          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5179          header, i, expected->rgAccDescr[i].pszAccessMethod,
5180          got->rgAccDescr[i].pszAccessMethod);
5181         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5182          &got->rgAccDescr[i].AccessLocation);
5183     }
5184 }
5185
5186 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5187 {
5188     static char oid1[] = "1.2.3";
5189     static char oid2[] = "1.5.6";
5190     BOOL ret;
5191     LPBYTE buf = NULL;
5192     DWORD size = 0;
5193
5194     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5195      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5196      &buf, &size);
5197     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5198     if (ret)
5199     {
5200         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5201
5202         compareAuthorityInfoAccess("empty AIA", &aia,
5203          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5204         LocalFree(buf);
5205         buf = NULL;
5206     }
5207     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5208      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5209      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5210     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5211     if (ret)
5212     {
5213         CERT_ACCESS_DESCRIPTION accessDescription;
5214         CERT_AUTHORITY_INFO_ACCESS aia;
5215
5216         accessDescription.pszAccessMethod = oid1;
5217         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5218         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5219         aia.cAccDescr = 1;
5220         aia.rgAccDescr = &accessDescription;
5221         compareAuthorityInfoAccess("AIA with URL", &aia,
5222          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5223         LocalFree(buf);
5224         buf = NULL;
5225     }
5226     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5227      authorityInfoAccessWithUrlAndIPAddr,
5228      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5229      NULL, &buf, &size);
5230     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5231     if (ret)
5232     {
5233         CERT_ACCESS_DESCRIPTION accessDescription[2];
5234         CERT_AUTHORITY_INFO_ACCESS aia;
5235
5236         accessDescription[0].pszAccessMethod = oid1;
5237         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5238         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5239         accessDescription[1].pszAccessMethod = oid2;
5240         accessDescription[1].AccessLocation.dwAltNameChoice =
5241          CERT_ALT_NAME_IP_ADDRESS;
5242         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5243          sizeof(encodedIPAddr);
5244         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5245          (LPBYTE)encodedIPAddr;
5246         aia.cAccDescr = 2;
5247         aia.rgAccDescr = accessDescription;
5248         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5249          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5250         LocalFree(buf);
5251         buf = NULL;
5252     }
5253     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5254      authorityInfoAccessWithUrlAndIPAddr,
5255      sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, NULL, &size);
5256     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5257     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
5258     if (buf)
5259     {
5260         ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5261          authorityInfoAccessWithUrlAndIPAddr,
5262          sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, buf, &size);
5263         ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5264         HeapFree(GetProcessHeap(), 0, buf);
5265     }
5266 }
5267
5268 static const BYTE emptyCTL[] = {
5269 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5270 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5271 static const BYTE emptyCTLWithVersion1[] = {
5272 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,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 ctlWithUsageIdentifier[] = {
5275 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5276 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5277 static const BYTE ctlWithListIdentifier[] = {
5278 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5279 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5280 static const BYTE ctlWithSequenceNumber[] = {
5281 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5282 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5283 static const BYTE ctlWithThisUpdate[] = {
5284 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5285 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5286 static const BYTE ctlWithThisAndNextUpdate[] = {
5287 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5288 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5289 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5290 static const BYTE ctlWithAlgId[] = {
5291 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5292 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5293 static const BYTE ctlWithBogusEntry[] = {
5294 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5295 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5296 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5297 static const BYTE ctlWithOneEntry[] = {
5298 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5299 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5300 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5301 static const BYTE ctlWithTwoEntries[] = {
5302 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5303 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5304 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5305 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5306 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5307
5308 static void test_encodeCTL(DWORD dwEncoding)
5309 {
5310     static char oid1[] = "1.2.3";
5311     static char oid2[] = "1.5.6";
5312     char *pOid1 = oid1;
5313     BOOL ret;
5314     BYTE *buf = NULL;
5315     DWORD size = 0;
5316     CTL_INFO info;
5317     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5318     CTL_ENTRY ctlEntry[2];
5319     CRYPT_ATTRIBUTE attr1, attr2;
5320     CRYPT_ATTR_BLOB value1, value2;
5321
5322     memset(&info, 0, sizeof(info));
5323     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5324      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5325     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5326     if (ret)
5327     {
5328         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5329         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5330         LocalFree(buf);
5331         buf = NULL;
5332     }
5333     info.dwVersion = 1;
5334     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5335      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5336     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5337     if (ret)
5338     {
5339         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5340         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5341         LocalFree(buf);
5342         buf = NULL;
5343     }
5344     info.dwVersion = 0;
5345     info.SubjectUsage.cUsageIdentifier = 1;
5346     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5347     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5348      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5349     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5350     if (ret)
5351     {
5352         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5353          size);
5354         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5355         LocalFree(buf);
5356         buf = NULL;
5357     }
5358     info.SubjectUsage.cUsageIdentifier = 0;
5359     info.ListIdentifier.cbData = sizeof(serialNum);
5360     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5361     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5362      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5363     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5364     if (ret)
5365     {
5366         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5367         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5368         LocalFree(buf);
5369         buf = NULL;
5370     }
5371     info.ListIdentifier.cbData = 0;
5372     info.SequenceNumber.cbData = sizeof(serialNum);
5373     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5374     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5375      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5376     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5377     if (ret)
5378     {
5379         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5380          size);
5381         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5382         LocalFree(buf);
5383         buf = NULL;
5384     }
5385     info.SequenceNumber.cbData = 0;
5386     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5387     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5388      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5389     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5390     if (ret)
5391     {
5392         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5393         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5394         LocalFree(buf);
5395         buf = NULL;
5396     }
5397     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5398     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5399      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5400     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5401     if (ret)
5402     {
5403         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5404          size);
5405         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5406         LocalFree(buf);
5407         buf = NULL;
5408     }
5409     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5410     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5411     info.SubjectAlgorithm.pszObjId = oid2;
5412     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5413      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5414     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5415     if (ret)
5416     {
5417         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5418         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5419         LocalFree(buf);
5420         buf = NULL;
5421     }
5422     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5423      * (see tests below) but it'll encode fine.
5424      */
5425     info.SubjectAlgorithm.pszObjId = NULL;
5426     value1.cbData = sizeof(serialNum);
5427     value1.pbData = (LPBYTE)serialNum;
5428     attr1.pszObjId = oid1;
5429     attr1.cValue = 1;
5430     attr1.rgValue = &value1;
5431     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5432     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5433     ctlEntry[0].cAttribute = 1;
5434     ctlEntry[0].rgAttribute = &attr1;
5435     info.cCTLEntry = 1;
5436     info.rgCTLEntry = ctlEntry;
5437     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5438      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5439     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5440     if (ret)
5441     {
5442         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5443         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5444         LocalFree(buf);
5445         buf = NULL;
5446     }
5447     value1.cbData = sizeof(emptySequence);
5448     value1.pbData = (LPBYTE)emptySequence;
5449     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5450      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5451     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5452     if (ret)
5453     {
5454         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5455         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5456         LocalFree(buf);
5457         buf = NULL;
5458     }
5459     value2.cbData = sizeof(encodedIPAddr);
5460     value2.pbData = (LPBYTE)encodedIPAddr;
5461     attr2.pszObjId = oid2;
5462     attr2.cValue = 1;
5463     attr2.rgValue = &value2;
5464     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5465     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5466     ctlEntry[1].cAttribute = 1;
5467     ctlEntry[1].rgAttribute = &attr2;
5468     info.cCTLEntry = 2;
5469     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5470      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5471     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5472     if (ret)
5473     {
5474         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5475         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5476         LocalFree(buf);
5477         buf = NULL;
5478     }
5479 }
5480
5481 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5482  const CTL_INFO *got)
5483 {
5484     DWORD i, j, k;
5485
5486     ok(expected->dwVersion == got->dwVersion,
5487      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5488      got->dwVersion);
5489     ok(expected->SubjectUsage.cUsageIdentifier ==
5490      got->SubjectUsage.cUsageIdentifier,
5491      "%s: expected %d usage identifiers, got %d\n", header,
5492      expected->SubjectUsage.cUsageIdentifier,
5493      got->SubjectUsage.cUsageIdentifier);
5494     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5495         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5496          got->SubjectUsage.rgpszUsageIdentifier[i]),
5497          "%s[%d]: expected %s, got %s\n", header, i,
5498          expected->SubjectUsage.rgpszUsageIdentifier[i],
5499          got->SubjectUsage.rgpszUsageIdentifier[i]);
5500     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5501      "%s: expected list identifier of %d bytes, got %d\n", header,
5502      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5503     if (expected->ListIdentifier.cbData)
5504         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5505          expected->ListIdentifier.cbData),
5506          "%s: unexpected list identifier value\n", header);
5507     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5508      "%s: expected sequence number of %d bytes, got %d\n", header,
5509      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5510     if (expected->SequenceNumber.cbData)
5511         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5512          expected->SequenceNumber.cbData),
5513          "%s: unexpected sequence number value\n", header);
5514     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5515      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5516      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5517      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5518     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5519      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5520      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5521      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5522     if (expected->SubjectAlgorithm.pszObjId &&
5523      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5524         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5525          expected->SubjectAlgorithm.pszObjId);
5526     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5527         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5528          got->SubjectAlgorithm.pszObjId),
5529          "%s: expected subject algorithm %s, got %s\n", header,
5530          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5531     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5532      got->SubjectAlgorithm.Parameters.cbData,
5533      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5534      expected->SubjectAlgorithm.Parameters.cbData,
5535      got->SubjectAlgorithm.Parameters.cbData);
5536     if (expected->SubjectAlgorithm.Parameters.cbData)
5537         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5538          got->SubjectAlgorithm.Parameters.pbData,
5539          expected->SubjectAlgorithm.Parameters.cbData),
5540          "%s: unexpected subject algorithm parameter value\n", header);
5541     ok(expected->cCTLEntry == got->cCTLEntry,
5542      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5543      got->cCTLEntry);
5544     for (i = 0; i < expected->cCTLEntry; i++)
5545     {
5546         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5547          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5548          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5549          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5550          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5551         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5552             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5553              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5554              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5555              "%s[%d]: unexpected subject identifier value\n",
5556              header, i);
5557         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5558         {
5559             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5560              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5561              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5562              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5563              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5564             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5565             {
5566                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5567                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5568                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5569                  header, i, j, k,
5570                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5571                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5572                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5573                     ok(!memcmp(
5574                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5575                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5576                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5577                      "%s[%d][%d][%d]: unexpected value\n",
5578                      header, i, j, k);
5579             }
5580         }
5581     }
5582     ok(expected->cExtension == got->cExtension,
5583      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5584      got->cExtension);
5585     for (i = 0; i < expected->cExtension; i++)
5586     {
5587         ok(!strcmp(expected->rgExtension[i].pszObjId,
5588          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5589          header, i, expected->rgExtension[i].pszObjId,
5590          got->rgExtension[i].pszObjId);
5591         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5592          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5593          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5594         ok(expected->rgExtension[i].Value.cbData ==
5595          got->rgExtension[i].Value.cbData,
5596          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5597          header, i, expected->rgExtension[i].Value.cbData,
5598          got->rgExtension[i].Value.cbData);
5599         if (expected->rgExtension[i].Value.cbData)
5600             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5601              got->rgExtension[i].Value.pbData,
5602              expected->rgExtension[i].Value.cbData),
5603              "%s[%d]: unexpected extension value\n", header, i);
5604     }
5605 }
5606
5607 static const BYTE signedCTL[] = {
5608 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5609 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5610 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5611 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5612 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5613 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5614 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5615 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5616 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5617 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5618 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5619 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5620 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5621 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5622 static const BYTE signedCTLWithCTLInnerContent[] = {
5623 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5624 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5625 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5626 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5627 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5628 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5629 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5630 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5631 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5632 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5633 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5634 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5635 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5636 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5637 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5638 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5639 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5640 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5641 0x57,0x6c,0x0b,0x47,0xb8 };
5642
5643 static void test_decodeCTL(DWORD dwEncoding)
5644 {
5645     static char oid1[] = "1.2.3";
5646     static char oid2[] = "1.5.6";
5647     static BYTE nullData[] = { 5,0 };
5648     char *pOid1 = oid1;
5649     BOOL ret;
5650     BYTE *buf = NULL;
5651     DWORD size = 0;
5652     CTL_INFO info;
5653     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5654     CTL_ENTRY ctlEntry[2];
5655     CRYPT_ATTRIBUTE attr1, attr2;
5656     CRYPT_ATTR_BLOB value1, value2;
5657
5658     memset(&info, 0, sizeof(info));
5659     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5660      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5661     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5662     if (ret)
5663     {
5664         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5665         LocalFree(buf);
5666         buf = NULL;
5667     }
5668     info.dwVersion = 1;
5669     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5670      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5671      &size);
5672     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5673     if (ret)
5674     {
5675         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5676         LocalFree(buf);
5677         buf = NULL;
5678     }
5679     info.dwVersion = 0;
5680     info.SubjectUsage.cUsageIdentifier = 1;
5681     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5682     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5683      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5684      &buf, &size);
5685     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5686     if (ret)
5687     {
5688         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5689         LocalFree(buf);
5690         buf = NULL;
5691     }
5692     info.SubjectUsage.cUsageIdentifier = 0;
5693     info.ListIdentifier.cbData = sizeof(serialNum);
5694     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5695     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5696      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5697     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5698     if (ret)
5699     {
5700         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5701         LocalFree(buf);
5702         buf = NULL;
5703     }
5704     info.ListIdentifier.cbData = 0;
5705     info.SequenceNumber.cbData = sizeof(serialNum);
5706     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5707     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5708      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5709     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5710     if (ret)
5711     {
5712         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5713         LocalFree(buf);
5714         buf = NULL;
5715     }
5716     info.SequenceNumber.cbData = 0;
5717     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5718     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5719      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5720     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5721     if (ret)
5722     {
5723         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5724         LocalFree(buf);
5725         buf = NULL;
5726     }
5727     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5728     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5729      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5730      &buf, &size);
5731     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5732     if (ret)
5733     {
5734         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5735         LocalFree(buf);
5736         buf = NULL;
5737     }
5738     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5739     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5740     info.SubjectAlgorithm.pszObjId = oid2;
5741     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5742     info.SubjectAlgorithm.Parameters.pbData = nullData;
5743     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5744      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5745     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5746     if (ret)
5747     {
5748         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5749         LocalFree(buf);
5750         buf = NULL;
5751     }
5752     SetLastError(0xdeadbeef);
5753     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5754      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5755     ok(!ret &&
5756      (GetLastError() == CRYPT_E_ASN1_EOD ||
5757       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5758       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5759      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5760      GetLastError());
5761     info.SubjectAlgorithm.Parameters.cbData = 0;
5762     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5763     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5764     info.SubjectAlgorithm.pszObjId = oid2;
5765     info.SubjectAlgorithm.pszObjId = NULL;
5766     value1.cbData = sizeof(emptySequence);
5767     value1.pbData = (LPBYTE)emptySequence;
5768     attr1.pszObjId = oid1;
5769     attr1.cValue = 1;
5770     attr1.rgValue = &value1;
5771     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5772     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5773     ctlEntry[0].cAttribute = 1;
5774     ctlEntry[0].rgAttribute = &attr1;
5775     info.cCTLEntry = 1;
5776     info.rgCTLEntry = ctlEntry;
5777     SetLastError(0xdeadbeef);
5778     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5779      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5780     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5781     if (ret)
5782     {
5783         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5784         LocalFree(buf);
5785         buf = NULL;
5786     }
5787     value2.cbData = sizeof(encodedIPAddr);
5788     value2.pbData = (LPBYTE)encodedIPAddr;
5789     attr2.pszObjId = oid2;
5790     attr2.cValue = 1;
5791     attr2.rgValue = &value2;
5792     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5793     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5794     ctlEntry[1].cAttribute = 1;
5795     ctlEntry[1].rgAttribute = &attr2;
5796     info.cCTLEntry = 2;
5797     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5798      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5799     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5800     if (ret)
5801     {
5802         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5803         LocalFree(buf);
5804         buf = NULL;
5805     }
5806     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5807     SetLastError(0xdeadbeef);
5808     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5809      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5810     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5811      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5812      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5813      GetLastError());
5814     SetLastError(0xdeadbeef);
5815     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5816      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5817      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5818     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5819      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5820      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5821      GetLastError());
5822 }
5823
5824 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5825 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5826  0x03,0,0,0,0,0,0 };
5827 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5828  0xa0,0x01,0x01 };
5829 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5830  0x03,0x02,0x01,0x01 };
5831 static BYTE bogusDER[] = { 1 };
5832
5833 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5834 {
5835     BOOL ret;
5836     BYTE *buf = NULL;
5837     DWORD size = 0;
5838     CRYPT_CONTENT_INFO info = { 0 };
5839     char oid1[] = "1.2.3";
5840
5841     if (0)
5842     {
5843         /* Crashes on win9x */
5844         SetLastError(0xdeadbeef);
5845         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5846          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5847         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5848          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5849     }
5850     SetLastError(0xdeadbeef);
5851     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5852      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5853     ok(!ret && (GetLastError() == E_INVALIDARG ||
5854      GetLastError() == OSS_LIMITED /* Win9x */),
5855      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5856     info.pszObjId = oid1;
5857     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5858      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5859     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5860     if (ret)
5861     {
5862         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5863         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5864         LocalFree(buf);
5865     }
5866     info.Content.pbData = bogusDER;
5867     info.Content.cbData = sizeof(bogusDER);
5868     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5869      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5870     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5871     if (ret)
5872     {
5873         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5874         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5875         LocalFree(buf);
5876     }
5877     info.Content.pbData = (BYTE *)ints[0].encoded;
5878     info.Content.cbData = ints[0].encoded[1] + 2;
5879     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5880      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5881     if (ret)
5882     {
5883         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5884         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5885         LocalFree(buf);
5886     }
5887 }
5888
5889 static const BYTE indefiniteSignedPKCSContent[] = {
5890 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5891 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5892 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5893 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5894 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5895 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5896 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5897 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5898 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5899 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5900 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5901 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5902 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5903 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5904 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5905 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5906 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5907 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5908 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5909 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5910 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5911 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5912 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5913 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5914 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5915 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5916 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5917 0x00,0x00,0x00,0x00,0x00,0x00 };
5918
5919 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5920 {
5921     BOOL ret;
5922     LPBYTE buf = NULL;
5923     DWORD size = 0;
5924     CRYPT_CONTENT_INFO *info;
5925
5926     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5927      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5928      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5929     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5930     if (ret)
5931     {
5932         info = (CRYPT_CONTENT_INFO *)buf;
5933
5934         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5935          info->pszObjId);
5936         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5937          info->Content.cbData);
5938         LocalFree(buf);
5939     }
5940     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5941      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5942      0, NULL, NULL, &size);
5943     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5944     SetLastError(0xdeadbeef);
5945     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5946      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5947      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5948     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5949      * I doubt an app depends on that.
5950      */
5951     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5952      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5953      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5954      GetLastError());
5955     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5956      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5957      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5958     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5959     if (ret)
5960     {
5961         info = (CRYPT_CONTENT_INFO *)buf;
5962
5963         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5964          info->pszObjId);
5965         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5966          "Unexpected size %d\n", info->Content.cbData);
5967         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5968          info->Content.cbData), "Unexpected value\n");
5969         LocalFree(buf);
5970     }
5971     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5972      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5973      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5974     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5975     if (ret)
5976     {
5977         info = (CRYPT_CONTENT_INFO *)buf;
5978
5979         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5980          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5981         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5982          info->Content.cbData);
5983         LocalFree(buf);
5984     }
5985 }
5986
5987 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5988  0x00 };
5989 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5990  0x01 };
5991 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5992  0x02,0x01,0x01 };
5993
5994 static void test_encodePKCSAttribute(DWORD dwEncoding)
5995 {
5996     CRYPT_ATTRIBUTE attr = { 0 };
5997     BOOL ret;
5998     LPBYTE buf = NULL;
5999     DWORD size = 0;
6000     CRYPT_ATTR_BLOB blob;
6001     char oid[] = "1.2.3";
6002
6003     if (0)
6004     {
6005         /* Crashes on win9x */
6006         SetLastError(0xdeadbeef);
6007         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
6008          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6009         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
6010          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
6011     }
6012     SetLastError(0xdeadbeef);
6013     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6014      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6015     ok(!ret && (GetLastError() == E_INVALIDARG ||
6016      GetLastError() == OSS_LIMITED /* Win9x */),
6017      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
6018     attr.pszObjId = oid;
6019     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6020      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6021     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6022     if (ret)
6023     {
6024         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
6025         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
6026         LocalFree(buf);
6027     }
6028     blob.cbData = sizeof(bogusDER);
6029     blob.pbData = bogusDER;
6030     attr.cValue = 1;
6031     attr.rgValue = &blob;
6032     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6033      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6034     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6035     if (ret)
6036     {
6037         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
6038         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6039         LocalFree(buf);
6040     }
6041     blob.pbData = (BYTE *)ints[0].encoded;
6042     blob.cbData = ints[0].encoded[1] + 2;
6043     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6044      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6045     if (ret)
6046     {
6047         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6048         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6049         LocalFree(buf);
6050     }
6051 }
6052
6053 static void test_decodePKCSAttribute(DWORD dwEncoding)
6054 {
6055     BOOL ret;
6056     LPBYTE buf = NULL;
6057     DWORD size = 0;
6058     CRYPT_ATTRIBUTE *attr;
6059
6060     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6061      emptyPKCSAttr, sizeof(emptyPKCSAttr),
6062      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6063     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6064     if (ret)
6065     {
6066         attr = (CRYPT_ATTRIBUTE *)buf;
6067
6068         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6069          attr->pszObjId);
6070         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6071         LocalFree(buf);
6072     }
6073     SetLastError(0xdeadbeef);
6074     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6075      bogusPKCSAttr, sizeof(bogusPKCSAttr),
6076      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6077     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6078      * I doubt an app depends on that.
6079      */
6080     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6081      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6082      GetLastError() == OSS_MORE_INPUT /* Win9x */),
6083      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6084      GetLastError());
6085     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6086      intPKCSAttr, sizeof(intPKCSAttr),
6087      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6088     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6089     if (ret)
6090     {
6091         attr = (CRYPT_ATTRIBUTE *)buf;
6092
6093         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6094          attr->pszObjId);
6095         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6096         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6097          "Unexpected size %d\n", attr->rgValue[0].cbData);
6098         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6099          attr->rgValue[0].cbData), "Unexpected value\n");
6100         LocalFree(buf);
6101     }
6102 }
6103
6104 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6105 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6106  0x2a,0x03,0x31,0x00 };
6107 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6108  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6109
6110 static void test_encodePKCSAttributes(DWORD dwEncoding)
6111 {
6112     CRYPT_ATTRIBUTES attributes = { 0 };
6113     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6114     CRYPT_ATTR_BLOB blob;
6115     BOOL ret;
6116     LPBYTE buf = NULL;
6117     DWORD size = 0;
6118     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6119
6120     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6121      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6122     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6123     if (ret)
6124     {
6125         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6126         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6127         LocalFree(buf);
6128     }
6129     attributes.cAttr = 1;
6130     attributes.rgAttr = attr;
6131     SetLastError(0xdeadbeef);
6132     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6133      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6134     ok(!ret && (GetLastError() == E_INVALIDARG ||
6135      GetLastError() == OSS_LIMITED /* Win9x */),
6136      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6137     attr[0].pszObjId = oid1;
6138     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6139      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6140     if (ret)
6141     {
6142         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6143         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6144         LocalFree(buf);
6145     }
6146     attr[1].pszObjId = oid2;
6147     attr[1].cValue = 1;
6148     attr[1].rgValue = &blob;
6149     blob.pbData = (BYTE *)ints[0].encoded;
6150     blob.cbData = ints[0].encoded[1] + 2;
6151     attributes.cAttr = 2;
6152     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6153      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6154     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6155     if (ret)
6156     {
6157         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6158         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6159         LocalFree(buf);
6160     }
6161 }
6162
6163 static void test_decodePKCSAttributes(DWORD dwEncoding)
6164 {
6165     BOOL ret;
6166     LPBYTE buf = NULL;
6167     DWORD size = 0;
6168     CRYPT_ATTRIBUTES *attributes;
6169
6170     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6171      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6172      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6173     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6174     if (ret)
6175     {
6176         attributes = (CRYPT_ATTRIBUTES *)buf;
6177         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6178          attributes->cAttr);
6179         LocalFree(buf);
6180     }
6181     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6182      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6183      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6184     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6185     if (ret)
6186     {
6187         attributes = (CRYPT_ATTRIBUTES *)buf;
6188         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6189          attributes->cAttr);
6190         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6191          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6192         ok(attributes->rgAttr[0].cValue == 0,
6193          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6194         LocalFree(buf);
6195     }
6196     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6197      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6198      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6199     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6200     if (ret)
6201     {
6202         attributes = (CRYPT_ATTRIBUTES *)buf;
6203         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6204          attributes->cAttr);
6205         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6206          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6207         ok(attributes->rgAttr[0].cValue == 0,
6208          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6209         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6210          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6211         ok(attributes->rgAttr[1].cValue == 1,
6212          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6213         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6214          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6215         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6216          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6217         LocalFree(buf);
6218     }
6219     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6220      doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, NULL, &size);
6221     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6222     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6223     if (buf)
6224     {
6225         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6226          doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, buf, &size);
6227         ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6228         HeapFree(GetProcessHeap(), 0, buf);
6229     }
6230 }
6231
6232 static const BYTE singleCapability[] = {
6233 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6234 static const BYTE twoCapabilities[] = {
6235 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6236 static const BYTE singleCapabilitywithNULL[] = {
6237 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6238
6239 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6240 {
6241     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6242     BOOL ret;
6243     LPBYTE buf = NULL;
6244     DWORD size = 0;
6245     CRYPT_SMIME_CAPABILITY capability[2];
6246     CRYPT_SMIME_CAPABILITIES capabilities;
6247
6248     /* An empty capabilities is allowed */
6249     capabilities.cCapability = 0;
6250     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6251      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6252     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6253     if (ret)
6254     {
6255         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6256         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6257         LocalFree(buf);
6258     }
6259     /* A non-empty capabilities with an empty capability (lacking an OID) is
6260      * not allowed
6261      */
6262     capability[0].pszObjId = NULL;
6263     capability[0].Parameters.cbData = 0;
6264     capabilities.cCapability = 1;
6265     capabilities.rgCapability = capability;
6266     SetLastError(0xdeadbeef);
6267     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6268      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6269     ok(!ret && (GetLastError() == E_INVALIDARG ||
6270      GetLastError() == OSS_LIMITED /* Win9x */),
6271      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6272     capability[0].pszObjId = oid1;
6273     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6274      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6275     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6276     if (ret)
6277     {
6278         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6279         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6280         LocalFree(buf);
6281     }
6282     capability[1].pszObjId = oid2;
6283     capability[1].Parameters.cbData = 0;
6284     capabilities.cCapability = 2;
6285     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6286      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6287     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6288     if (ret)
6289     {
6290         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6291         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6292         LocalFree(buf);
6293     }
6294 }
6295
6296 static void compareSMimeCapabilities(LPCSTR header,
6297  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6298 {
6299     DWORD i;
6300
6301     ok(got->cCapability == expected->cCapability,
6302      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6303      got->cCapability);
6304     for (i = 0; i < expected->cCapability; i++)
6305     {
6306         ok(!strcmp(expected->rgCapability[i].pszObjId,
6307          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6308          header, i, expected->rgCapability[i].pszObjId,
6309          got->rgCapability[i].pszObjId);
6310         ok(expected->rgCapability[i].Parameters.cbData ==
6311          got->rgCapability[i].Parameters.cbData,
6312          "%s[%d]: expected %d bytes, got %d\n", header, i,
6313          expected->rgCapability[i].Parameters.cbData,
6314          got->rgCapability[i].Parameters.cbData);
6315         if (expected->rgCapability[i].Parameters.cbData)
6316             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6317              got->rgCapability[i].Parameters.pbData,
6318              expected->rgCapability[i].Parameters.cbData),
6319              "%s[%d]: unexpected value\n", header, i);
6320     }
6321 }
6322
6323 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6324 {
6325     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6326     BOOL ret;
6327     DWORD size = 0;
6328     CRYPT_SMIME_CAPABILITY capability[2];
6329     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6330
6331     SetLastError(0xdeadbeef);
6332     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6333      emptySequence, sizeof(emptySequence),
6334      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6335     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6336     if (ret)
6337     {
6338         capabilities.cCapability = 0;
6339         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6340         LocalFree(ptr);
6341     }
6342     SetLastError(0xdeadbeef);
6343     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6344      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6345      &ptr, &size);
6346     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6347     if (ret)
6348     {
6349         capability[0].pszObjId = oid1;
6350         capability[0].Parameters.cbData = 0;
6351         capabilities.cCapability = 1;
6352         capabilities.rgCapability = capability;
6353         compareSMimeCapabilities("single capability", &capabilities, ptr);
6354         LocalFree(ptr);
6355     }
6356     SetLastError(0xdeadbeef);
6357     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6358      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6359      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6360     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6361     if (ret)
6362     {
6363         BYTE NULLparam[] = {0x05, 0x00};
6364         capability[0].pszObjId = oid1;
6365         capability[0].Parameters.cbData = 2;
6366         capability[0].Parameters.pbData = NULLparam;
6367         capabilities.cCapability = 1;
6368         capabilities.rgCapability = capability;
6369         compareSMimeCapabilities("single capability with NULL", &capabilities,
6370          ptr);
6371         LocalFree(ptr);
6372     }
6373     SetLastError(0xdeadbeef);
6374     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6375     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6376     &ptr, &size);
6377     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6378     if (ret)
6379     {
6380         capability[0].Parameters.cbData = 0;
6381         capability[1].pszObjId = oid2;
6382         capability[1].Parameters.cbData = 0;
6383         capabilities.cCapability = 2;
6384         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6385         LocalFree(ptr);
6386     }
6387     SetLastError(0xdeadbeef);
6388     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6389      twoCapabilities, sizeof(twoCapabilities), 0, NULL, NULL, &size);
6390     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6391     ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6392     if (ptr)
6393     {
6394         SetLastError(0xdeadbeef);
6395         ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6396          twoCapabilities, sizeof(twoCapabilities), 0, NULL, ptr, &size);
6397         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6398         HeapFree(GetProcessHeap(), 0, ptr);
6399     }
6400 }
6401
6402 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6403  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6404  0x67 };
6405 static const BYTE minimalPKCSSigner[] = {
6406  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6407  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6408  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6409 static const BYTE PKCSSignerWithSerial[] = {
6410  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6411  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6412  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6413  0x00 };
6414 static const BYTE PKCSSignerWithHashAlgo[] = {
6415  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6416  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6417  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6418  0x00,0x04,0x00 };
6419 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6420  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6421  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6422  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6423  0x06,0x05,0x00,0x04,0x00 };
6424 static const BYTE PKCSSignerWithHash[] = {
6425  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6426  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6427  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6428  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6429  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6430 static const BYTE PKCSSignerWithAuthAttr[] = {
6431 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6432 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6433 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6434 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6435 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6436 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6437 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6438
6439 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6440 {
6441     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6442     BOOL ret;
6443     LPBYTE buf = NULL;
6444     DWORD size = 0;
6445     CMSG_SIGNER_INFO info = { 0 };
6446     char oid_common_name[] = szOID_COMMON_NAME;
6447     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6448      (LPBYTE)encodedCommonName };
6449     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6450
6451     SetLastError(0xdeadbeef);
6452     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6453      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6454     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6455     {
6456         skip("no PKCS7_SIGNER_INFO encode support\n");
6457         return;
6458     }
6459     ok(!ret && (GetLastError() == E_INVALIDARG ||
6460      GetLastError() == OSS_LIMITED /* Win9x */),
6461      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6462     /* To be encoded, a signer must have an issuer at least, and the encoding
6463      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6464      * see decoding tests.)
6465      */
6466     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6467     info.Issuer.pbData = encodedCommonNameNoNull;
6468     SetLastError(0xdeadbeef);
6469     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6470      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6471     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6472         ok(!ret && GetLastError() == E_INVALIDARG,
6473          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6474     else
6475     {
6476         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6477          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6478         if (ret)
6479         {
6480             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6481             if (size == sizeof(minimalPKCSSigner))
6482                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6483             else
6484                 ok(0, "Unexpected value\n");
6485             LocalFree(buf);
6486         }
6487     }
6488     info.SerialNumber.cbData = sizeof(serialNum);
6489     info.SerialNumber.pbData = (BYTE *)serialNum;
6490     SetLastError(0xdeadbeef);
6491     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6492      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6493     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6494         ok(!ret && GetLastError() == E_INVALIDARG,
6495          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6496     else
6497     {
6498         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6499          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6500         if (ret)
6501         {
6502             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6503              size);
6504             if (size == sizeof(PKCSSignerWithSerial))
6505                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6506                  "Unexpected value\n");
6507             else
6508                 ok(0, "Unexpected value\n");
6509             LocalFree(buf);
6510         }
6511     }
6512     info.HashAlgorithm.pszObjId = oid1;
6513     SetLastError(0xdeadbeef);
6514     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6515      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6516     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6517         ok(!ret && GetLastError() == E_INVALIDARG,
6518          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6519     else
6520     {
6521         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6522          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6523         if (ret)
6524         {
6525             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6526              size);
6527             if (size == sizeof(PKCSSignerWithHashAlgo))
6528                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6529                  "Unexpected value\n");
6530             else
6531                 ok(0, "Unexpected value\n");
6532             LocalFree(buf);
6533         }
6534     }
6535     info.HashEncryptionAlgorithm.pszObjId = oid2;
6536     SetLastError(0xdeadbeef);
6537     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6538      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6539     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6540         ok(!ret && GetLastError() == E_INVALIDARG,
6541          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6542     else
6543     {
6544         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6545         if (ret)
6546         {
6547             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6548              "Unexpected size %d\n", size);
6549             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6550                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6551                  "Unexpected value\n");
6552             else
6553                 ok(0, "Unexpected value\n");
6554             LocalFree(buf);
6555         }
6556     }
6557     info.EncryptedHash.cbData = sizeof(hash);
6558     info.EncryptedHash.pbData = (BYTE *)hash;
6559     SetLastError(0xdeadbeef);
6560     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6561      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6562     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6563         ok(!ret && GetLastError() == E_INVALIDARG,
6564          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6565     else
6566     {
6567         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6568         if (ret)
6569         {
6570             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6571              size);
6572             if (size == sizeof(PKCSSignerWithHash))
6573                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6574                  "Unexpected value\n");
6575             else
6576                 ok(0, "Unexpected value\n");
6577             LocalFree(buf);
6578         }
6579     }
6580     info.AuthAttrs.cAttr = 1;
6581     info.AuthAttrs.rgAttr = &attr;
6582     SetLastError(0xdeadbeef);
6583     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6584      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6585     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6586         ok(!ret && GetLastError() == E_INVALIDARG,
6587          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6588     else
6589     {
6590         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6591         if (ret)
6592         {
6593             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6594              size);
6595             if (size == sizeof(PKCSSignerWithAuthAttr))
6596                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6597                  "Unexpected value\n");
6598             else
6599                 ok(0, "Unexpected value\n");
6600             LocalFree(buf);
6601         }
6602     }
6603 }
6604
6605 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6606 {
6607     BOOL ret;
6608     LPBYTE buf = NULL;
6609     DWORD size = 0;
6610     CMSG_SIGNER_INFO *info;
6611
6612     /* A PKCS signer can't be decoded without a serial number. */
6613     SetLastError(0xdeadbeef);
6614     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6615      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6616      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6617     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6618      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6619      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6620      GetLastError());
6621     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6622      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6623      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6624     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6625      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6626     if (ret)
6627     {
6628         info = (CMSG_SIGNER_INFO *)buf;
6629         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6630          info->dwVersion);
6631         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6632          "Unexpected size %d\n", info->Issuer.cbData);
6633         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6634          info->Issuer.cbData), "Unexpected value\n");
6635         ok(info->SerialNumber.cbData == sizeof(serialNum),
6636          "Unexpected size %d\n", info->SerialNumber.cbData);
6637         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6638          "Unexpected value\n");
6639         LocalFree(buf);
6640     }
6641     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6642      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6643      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6644     if (ret)
6645     {
6646         info = (CMSG_SIGNER_INFO *)buf;
6647         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6648          info->dwVersion);
6649         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6650          "Unexpected size %d\n", info->Issuer.cbData);
6651         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6652          info->Issuer.cbData), "Unexpected value\n");
6653         ok(info->SerialNumber.cbData == sizeof(serialNum),
6654          "Unexpected size %d\n", info->SerialNumber.cbData);
6655         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6656          "Unexpected value\n");
6657         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6658          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6659         LocalFree(buf);
6660     }
6661     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6662      PKCSSignerWithHashAndEncryptionAlgo,
6663      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6664      NULL, &buf, &size);
6665     if (ret)
6666     {
6667         info = (CMSG_SIGNER_INFO *)buf;
6668         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6669          info->dwVersion);
6670         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6671          "Unexpected size %d\n", info->Issuer.cbData);
6672         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6673          info->Issuer.cbData), "Unexpected value\n");
6674         ok(info->SerialNumber.cbData == sizeof(serialNum),
6675          "Unexpected size %d\n", info->SerialNumber.cbData);
6676         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6677          "Unexpected value\n");
6678         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6679          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6680         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6681          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6682         LocalFree(buf);
6683     }
6684     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6685      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6686      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6687     if (ret)
6688     {
6689         info = (CMSG_SIGNER_INFO *)buf;
6690         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6691          info->dwVersion);
6692         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6693          "Unexpected size %d\n", info->Issuer.cbData);
6694         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6695          info->Issuer.cbData), "Unexpected value\n");
6696         ok(info->SerialNumber.cbData == sizeof(serialNum),
6697          "Unexpected size %d\n", info->SerialNumber.cbData);
6698         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6699          "Unexpected value\n");
6700         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6701          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6702         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6703          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6704         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6705          info->EncryptedHash.cbData);
6706         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6707          "Unexpected value\n");
6708         LocalFree(buf);
6709     }
6710     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6711      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6712      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6713     if (ret)
6714     {
6715         info = (CMSG_SIGNER_INFO *)buf;
6716         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6717          info->AuthAttrs.cAttr);
6718         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6719          "Expected %s, got %s\n", szOID_COMMON_NAME,
6720          info->AuthAttrs.rgAttr[0].pszObjId);
6721         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6722          info->AuthAttrs.rgAttr[0].cValue);
6723         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6724          sizeof(encodedCommonName), "Unexpected size %d\n",
6725          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6726         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6727          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6728         LocalFree(buf);
6729     }
6730 }
6731
6732 static const BYTE CMSSignerWithKeyId[] = {
6733 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6734 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6735
6736 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6737 {
6738     BOOL ret;
6739     LPBYTE buf = NULL;
6740     DWORD size = 0;
6741     CMSG_CMS_SIGNER_INFO info = { 0 };
6742     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6743
6744     SetLastError(0xdeadbeef);
6745     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6746      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6747     ok(!ret, "Expected failure, got %d\n", ret);
6748     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6749     {
6750         skip("no CMS_SIGNER_INFO encode support\n");
6751         return;
6752     }
6753     ok(GetLastError() == E_INVALIDARG,
6754        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6755     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6756     SetLastError(0xdeadbeef);
6757     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6758      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6759     ok(!ret, "Expected failure, got %d\n", ret);
6760     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6761     {
6762         skip("no CMS_SIGNER_INFO encode support\n");
6763         return;
6764     }
6765     ok(GetLastError() == E_INVALIDARG,
6766        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6767     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6768      * be a key id or a issuer serial number with at least the issuer set, and
6769      * the encoding must include PKCS_7_ASN_ENCODING.
6770      * (That isn't enough to be decoded, see decoding tests.)
6771      */
6772     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6773      sizeof(encodedCommonNameNoNull);
6774     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6775     SetLastError(0xdeadbeef);
6776     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6777      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6778     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6779         ok(!ret && GetLastError() == E_INVALIDARG,
6780          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6781     else
6782     {
6783         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6784         if (ret)
6785         {
6786             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6787             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6788             LocalFree(buf);
6789         }
6790     }
6791     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6792     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6793     SetLastError(0xdeadbeef);
6794     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6795      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6796     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6797         ok(!ret && GetLastError() == E_INVALIDARG,
6798          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6799     else
6800     {
6801         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6802         if (ret)
6803         {
6804             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6805              size);
6806             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6807             LocalFree(buf);
6808         }
6809     }
6810     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6811     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6812     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6813     SetLastError(0xdeadbeef);
6814     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6815      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6816     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6817         ok(!ret && GetLastError() == E_INVALIDARG,
6818          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6819     else
6820     {
6821         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6822         if (ret)
6823         {
6824             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6825              size);
6826             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6827             LocalFree(buf);
6828         }
6829     }
6830     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6831      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6832      * (see RFC 3852, section 5.3.)
6833      */
6834     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6835     U(info.SignerId).HashId.cbData = sizeof(hash);
6836     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6837     SetLastError(0xdeadbeef);
6838     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6839      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6840     ok(!ret && GetLastError() == E_INVALIDARG,
6841      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6842     /* Now with a hash algo */
6843     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6844     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6845      sizeof(encodedCommonNameNoNull);
6846     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6847     info.HashAlgorithm.pszObjId = oid1;
6848     SetLastError(0xdeadbeef);
6849     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6850      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6851     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6852         ok(!ret && GetLastError() == E_INVALIDARG,
6853          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6854     else
6855     {
6856         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6857         if (ret)
6858         {
6859             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6860              size);
6861             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6862              "Unexpected value\n");
6863             LocalFree(buf);
6864         }
6865     }
6866     info.HashEncryptionAlgorithm.pszObjId = oid2;
6867     SetLastError(0xdeadbeef);
6868     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6869      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6870     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6871         ok(!ret && GetLastError() == E_INVALIDARG,
6872          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6873     else
6874     {
6875         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6876         if (ret)
6877         {
6878             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6879              "Unexpected size %d\n", size);
6880             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6881              "Unexpected value\n");
6882             LocalFree(buf);
6883         }
6884     }
6885     info.EncryptedHash.cbData = sizeof(hash);
6886     info.EncryptedHash.pbData = (BYTE *)hash;
6887     SetLastError(0xdeadbeef);
6888     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6889      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6890     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6891         ok(!ret && GetLastError() == E_INVALIDARG,
6892          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6893     else
6894     {
6895         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6896         if (ret)
6897         {
6898             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6899              size);
6900             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6901             LocalFree(buf);
6902         }
6903     }
6904 }
6905
6906 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6907 {
6908     BOOL ret;
6909     LPBYTE buf = NULL;
6910     DWORD size = 0;
6911     CMSG_CMS_SIGNER_INFO *info;
6912     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6913
6914     /* A CMS signer can't be decoded without a serial number. */
6915     SetLastError(0xdeadbeef);
6916     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6917      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6918      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6919     ok(!ret, "expected failure\n");
6920     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6921     {
6922         skip("no CMS_SIGNER_INFO decode support\n");
6923         return;
6924     }
6925     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6926      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6927     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6928      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6929      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6930     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6931     if (ret)
6932     {
6933         info = (CMSG_CMS_SIGNER_INFO *)buf;
6934         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6935          info->dwVersion);
6936         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6937          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6938          info->SignerId.dwIdChoice);
6939         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6940          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6941          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6942         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6943          encodedCommonNameNoNull,
6944          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6945          "Unexpected value\n");
6946         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6947          sizeof(serialNum), "Unexpected size %d\n",
6948          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6949         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6950          serialNum, sizeof(serialNum)), "Unexpected value\n");
6951         LocalFree(buf);
6952     }
6953     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6954      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6955      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6956     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6957     if (ret)
6958     {
6959         info = (CMSG_CMS_SIGNER_INFO *)buf;
6960         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6961          info->dwVersion);
6962         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6963          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6964          info->SignerId.dwIdChoice);
6965         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6966          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6967          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6968         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6969          encodedCommonNameNoNull,
6970          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6971          "Unexpected value\n");
6972         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6973          sizeof(serialNum), "Unexpected size %d\n",
6974          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6975         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6976          serialNum, sizeof(serialNum)), "Unexpected value\n");
6977         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6978          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6979         LocalFree(buf);
6980     }
6981     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6982      PKCSSignerWithHashAndEncryptionAlgo,
6983      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6984      NULL, &buf, &size);
6985     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6986     if (ret)
6987     {
6988         info = (CMSG_CMS_SIGNER_INFO *)buf;
6989         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6990          info->dwVersion);
6991         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6992          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6993          info->SignerId.dwIdChoice);
6994         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6995          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6996          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6997         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6998          encodedCommonNameNoNull,
6999          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7000          "Unexpected value\n");
7001         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7002          sizeof(serialNum), "Unexpected size %d\n",
7003          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7004         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7005          serialNum, sizeof(serialNum)), "Unexpected value\n");
7006         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7007          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7008         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7009          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7010         LocalFree(buf);
7011     }
7012     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7013      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
7014      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7015     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7016     if (ret)
7017     {
7018         info = (CMSG_CMS_SIGNER_INFO *)buf;
7019         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7020          info->dwVersion);
7021         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7022          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7023          info->SignerId.dwIdChoice);
7024         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7025          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7026          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7027         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7028          encodedCommonNameNoNull,
7029          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7030          "Unexpected value\n");
7031         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7032          sizeof(serialNum), "Unexpected size %d\n",
7033          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7034         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7035          serialNum, sizeof(serialNum)), "Unexpected value\n");
7036         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7037          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7038         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7039          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7040         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
7041          info->EncryptedHash.cbData);
7042         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
7043          "Unexpected value\n");
7044         LocalFree(buf);
7045     }
7046     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7047      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
7048      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7049     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7050     if (ret)
7051     {
7052         info = (CMSG_CMS_SIGNER_INFO *)buf;
7053         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7054          info->dwVersion);
7055         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
7056          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
7057          info->SignerId.dwIdChoice);
7058         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
7059          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
7060         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
7061          "Unexpected value\n");
7062         LocalFree(buf);
7063     }
7064 }
7065
7066 static BYTE emptyDNSPermittedConstraints[] = {
7067 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7068 static BYTE emptyDNSExcludedConstraints[] = {
7069 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7070 static BYTE DNSExcludedConstraints[] = {
7071 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7072 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7073 static BYTE permittedAndExcludedConstraints[] = {
7074 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7075 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7076 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7077 static BYTE permittedAndExcludedWithMinConstraints[] = {
7078 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7079 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7080 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7081 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7082 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7083 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7084 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7085
7086 static void test_encodeNameConstraints(DWORD dwEncoding)
7087 {
7088     BOOL ret;
7089     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7090     CERT_GENERAL_SUBTREE permitted = { { 0 } };
7091     CERT_GENERAL_SUBTREE excluded = { { 0 } };
7092     LPBYTE buf;
7093     DWORD size;
7094
7095     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7096      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7097     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7098     {
7099         skip("no X509_NAME_CONSTRAINTS encode support\n");
7100         return;
7101     }
7102     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7103     if (ret)
7104     {
7105         ok(size == sizeof(emptySequence), "Unexpected size\n");
7106         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7107         LocalFree(buf);
7108     }
7109     constraints.cPermittedSubtree = 1;
7110     constraints.rgPermittedSubtree = &permitted;
7111     SetLastError(0xdeadbeef);
7112     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7113      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7114     ok(!ret && GetLastError() == E_INVALIDARG,
7115      "Expected E_INVALIDARG, got %08x\n", GetLastError());
7116     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7117     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7118      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7119     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7120     if (ret)
7121     {
7122         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7123         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7124          "Unexpected value\n");
7125         LocalFree(buf);
7126     }
7127     constraints.cPermittedSubtree = 0;
7128     constraints.cExcludedSubtree = 1;
7129     constraints.rgExcludedSubtree = &excluded;
7130     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7131     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7132      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7133     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7134     if (ret)
7135     {
7136         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7137         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7138          "Unexpected value\n");
7139         LocalFree(buf);
7140     }
7141     U(excluded.Base).pwszURL = (LPWSTR)url;
7142     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7143      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7144     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7145     if (ret)
7146     {
7147         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7148         ok(!memcmp(buf, DNSExcludedConstraints, size),
7149          "Unexpected value\n");
7150         LocalFree(buf);
7151     }
7152     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7153     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7154     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7155     constraints.cPermittedSubtree = 1;
7156     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7157      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7158     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7159     if (ret)
7160     {
7161         ok(size == sizeof(permittedAndExcludedConstraints),
7162          "Unexpected size\n");
7163         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7164          "Unexpected value\n");
7165         LocalFree(buf);
7166     }
7167     permitted.dwMinimum = 5;
7168     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7169      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7170     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7171     if (ret)
7172     {
7173         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7174          "Unexpected size\n");
7175         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7176          "Unexpected value\n");
7177         LocalFree(buf);
7178     }
7179     permitted.fMaximum = TRUE;
7180     permitted.dwMaximum = 3;
7181     SetLastError(0xdeadbeef);
7182     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7183      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7184     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7185     if (ret)
7186     {
7187         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7188          "Unexpected size\n");
7189         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7190          "Unexpected value\n");
7191         LocalFree(buf);
7192     }
7193 }
7194
7195 struct EncodedNameConstraints
7196 {
7197     CRYPT_DATA_BLOB            encoded;
7198     CERT_NAME_CONSTRAINTS_INFO constraints;
7199 };
7200
7201 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7202  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7203 static CERT_GENERAL_SUBTREE DNSSubtree = {
7204  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7205 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7206  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7207 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7208  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7209 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7210  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7211
7212 static const struct EncodedNameConstraints encodedNameConstraints[] = {
7213  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7214  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7215    { 1, &emptyDNSSubtree, 0, NULL } },
7216  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7217    { 0, NULL, 1, &emptyDNSSubtree } },
7218  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7219    { 0, NULL, 1, &DNSSubtree } },
7220  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7221    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7222  { { sizeof(permittedAndExcludedWithMinConstraints),
7223      permittedAndExcludedWithMinConstraints },
7224    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7225  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7226      permittedAndExcludedWithMinMaxConstraints },
7227    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7228 };
7229
7230 static void test_decodeNameConstraints(DWORD dwEncoding)
7231 {
7232     BOOL ret;
7233     DWORD i;
7234     CERT_NAME_CONSTRAINTS_INFO *constraints;
7235
7236     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7237     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7238     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7239     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7240     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7241     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7242     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7243     for (i = 0;
7244      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7245      i++)
7246     {
7247         DWORD size;
7248
7249         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7250          encodedNameConstraints[i].encoded.pbData,
7251          encodedNameConstraints[i].encoded.cbData,
7252          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7253         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7254         {
7255             skip("no X509_NAME_CONSTRAINTS decode support\n");
7256             return;
7257         }
7258         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7259         if (ret)
7260         {
7261             DWORD j;
7262
7263             if (constraints->cPermittedSubtree !=
7264              encodedNameConstraints[i].constraints.cPermittedSubtree)
7265                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7266                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7267                  constraints->cPermittedSubtree);
7268             if (constraints->cPermittedSubtree ==
7269              encodedNameConstraints[i].constraints.cPermittedSubtree)
7270             {
7271                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7272                 {
7273                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7274                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7275                 }
7276             }
7277             if (constraints->cExcludedSubtree !=
7278              encodedNameConstraints[i].constraints.cExcludedSubtree)
7279                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7280                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7281                  constraints->cExcludedSubtree);
7282             if (constraints->cExcludedSubtree ==
7283              encodedNameConstraints[i].constraints.cExcludedSubtree)
7284             {
7285                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7286                 {
7287                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7288                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7289                 }
7290             }
7291             LocalFree(constraints);
7292         }
7293     }
7294 }
7295
7296 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7297  'n','o','t','i','c','e',0 };
7298 static const BYTE noticeWithDisplayText[] = {
7299  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7300  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7301  0x00,0x69,0x00,0x63,0x00,0x65
7302 };
7303 static char org[] = "Wine";
7304 static int noticeNumbers[] = { 2,3 };
7305 static BYTE noticeWithReference[] = {
7306  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7307  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7308  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7309  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7310 };
7311
7312 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7313 {
7314     BOOL ret;
7315     LPBYTE buf;
7316     DWORD size;
7317     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7318     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7319
7320     memset(&notice, 0, sizeof(notice));
7321     ret = pCryptEncodeObjectEx(dwEncoding,
7322      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7323      NULL, &buf, &size);
7324     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7325     {
7326         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7327         return;
7328     }
7329     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7330     if (ret)
7331     {
7332         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7333         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7334         LocalFree(buf);
7335     }
7336     notice.pszDisplayText = noticeText;
7337     ret = pCryptEncodeObjectEx(dwEncoding,
7338      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7339      NULL, &buf, &size);
7340     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7341     if (ret)
7342     {
7343         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7344         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7345         LocalFree(buf);
7346     }
7347     reference.pszOrganization = org;
7348     reference.cNoticeNumbers = 2;
7349     reference.rgNoticeNumbers = noticeNumbers;
7350     notice.pNoticeReference = &reference;
7351     ret = pCryptEncodeObjectEx(dwEncoding,
7352      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7353      NULL, &buf, &size);
7354     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7355     if (ret)
7356     {
7357         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7358         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7359         LocalFree(buf);
7360     }
7361 }
7362
7363 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7364 {
7365     BOOL ret;
7366     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7367     DWORD size;
7368
7369     ret = pCryptDecodeObjectEx(dwEncoding,
7370      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7371      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7372      &notice, &size);
7373     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7374     {
7375         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7376         return;
7377     }
7378     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7379     if (ret)
7380     {
7381         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7382         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7383         LocalFree(notice);
7384     }
7385     ret = pCryptDecodeObjectEx(dwEncoding,
7386      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7387      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7388      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7389     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7390     if (ret)
7391     {
7392         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7393          "unexpected display text\n");
7394         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7395         LocalFree(notice);
7396     }
7397     ret = pCryptDecodeObjectEx(dwEncoding,
7398      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7399      noticeWithReference, sizeof(noticeWithReference),
7400      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7401     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7402     if (ret)
7403     {
7404         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7405          "unexpected display text\n");
7406         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7407         if (notice->pNoticeReference)
7408         {
7409             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7410              "unexpected organization %s\n",
7411              notice->pNoticeReference->pszOrganization);
7412             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7413              "expected 2 notice numbers, got %d\n",
7414              notice->pNoticeReference->cNoticeNumbers);
7415             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7416              "unexpected notice number %d\n",
7417              notice->pNoticeReference->rgNoticeNumbers[0]);
7418             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7419              "unexpected notice number %d\n",
7420              notice->pNoticeReference->rgNoticeNumbers[1]);
7421         }
7422         LocalFree(notice);
7423     }
7424 }
7425
7426 static char oid_any_policy[] = "2.5.29.32.0";
7427 static const BYTE policiesWithAnyPolicy[] = {
7428  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7429 };
7430 static char oid1[] = "1.2.3";
7431 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7432 static const BYTE twoPolicies[] = {
7433  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7434  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7435  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7436  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7437  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7438  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7439 };
7440
7441 static void test_encodeCertPolicies(DWORD dwEncoding)
7442 {
7443     BOOL ret;
7444     CERT_POLICIES_INFO info;
7445     CERT_POLICY_INFO policy[2];
7446     CERT_POLICY_QUALIFIER_INFO qualifier;
7447     LPBYTE buf;
7448     DWORD size;
7449
7450     memset(&info, 0, sizeof(info));
7451     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7452      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7453     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7454     if (ret)
7455     {
7456         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7457         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7458         LocalFree(buf);
7459     }
7460     memset(policy, 0, sizeof(policy));
7461     info.cPolicyInfo = 1;
7462     info.rgPolicyInfo = policy;
7463     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7464      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7465     ok(!ret && (GetLastError() == E_INVALIDARG ||
7466      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7467      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7468     policy[0].pszPolicyIdentifier = oid_any_policy;
7469     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7470      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7471     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7472     if (ret)
7473     {
7474         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7475         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7476         LocalFree(buf);
7477     }
7478     policy[1].pszPolicyIdentifier = oid1;
7479     memset(&qualifier, 0, sizeof(qualifier));
7480     qualifier.pszPolicyQualifierId = oid_user_notice;
7481     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7482     qualifier.Qualifier.pbData = noticeWithReference;
7483     policy[1].cPolicyQualifier = 1;
7484     policy[1].rgPolicyQualifier = &qualifier;
7485     info.cPolicyInfo = 2;
7486     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7487      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7488     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7489     if (ret)
7490     {
7491         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7492         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7493         LocalFree(buf);
7494     }
7495 }
7496
7497 static void test_decodeCertPolicies(DWORD dwEncoding)
7498 {
7499     BOOL ret;
7500     CERT_POLICIES_INFO *info;
7501     DWORD size;
7502
7503     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7504      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7505      &info, &size);
7506     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7507     if (ret)
7508     {
7509         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7510          info->cPolicyInfo);
7511         LocalFree(info);
7512     }
7513     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7514      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7515      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7516     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7517     if (ret)
7518     {
7519         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7520          info->cPolicyInfo);
7521         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7522          "unexpected policy id %s\n",
7523          info->rgPolicyInfo[0].pszPolicyIdentifier);
7524         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7525          "unexpected policy qualifier count %d\n",
7526          info->rgPolicyInfo[0].cPolicyQualifier);
7527         LocalFree(info);
7528     }
7529     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7530      twoPolicies, sizeof(twoPolicies),
7531      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7532     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7533     if (ret)
7534     {
7535         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7536          info->cPolicyInfo);
7537         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7538          "unexpected policy id %s\n",
7539          info->rgPolicyInfo[0].pszPolicyIdentifier);
7540         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7541          "unexpected policy qualifier count %d\n",
7542          info->rgPolicyInfo[0].cPolicyQualifier);
7543         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7544          "unexpected policy id %s\n",
7545          info->rgPolicyInfo[1].pszPolicyIdentifier);
7546         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7547          "unexpected policy qualifier count %d\n",
7548          info->rgPolicyInfo[1].cPolicyQualifier);
7549         ok(!strcmp(
7550          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7551          oid_user_notice), "unexpected policy qualifier id %s\n",
7552          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7553         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7554          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7555          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7556         ok(!memcmp(
7557          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7558          noticeWithReference, sizeof(noticeWithReference)),
7559          "unexpected qualifier value\n");
7560         LocalFree(info);
7561     }
7562     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7563      twoPolicies, sizeof(twoPolicies), 0, NULL, NULL, &size);
7564     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7565     info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7566     if (info)
7567     {
7568         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7569          twoPolicies, sizeof(twoPolicies), 0, NULL, info, &size);
7570         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7571         HeapFree(GetProcessHeap(), 0, info);
7572     }
7573 }
7574
7575 static const BYTE policyMappingWithOneMapping[] = {
7576 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7577 static const BYTE policyMappingWithTwoMappings[] = {
7578 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7579 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7580 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7581  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7582
7583 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7584 {
7585     static char oid2[] = "2.3.4";
7586     static char oid3[] = "1.3.4";
7587     static char oid4[] = "2.5.6";
7588     BOOL ret;
7589     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7590     CERT_POLICY_MAPPING mapping[2];
7591     LPBYTE buf;
7592     DWORD size, i;
7593
7594     /* Each of the mapping OIDs is equivalent, so check with all of them */
7595     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7596     {
7597         memset(&info, 0, sizeof(info));
7598         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7599          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7600         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7601          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7602         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7603         {
7604             win_skip("no policy mappings support\n");
7605             return;
7606         }
7607         if (ret)
7608         {
7609             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7610             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7611              "unexpected value\n");
7612             LocalFree(buf);
7613         }
7614         mapping[0].pszIssuerDomainPolicy = NULL;
7615         mapping[0].pszSubjectDomainPolicy = NULL;
7616         info.cPolicyMapping = 1;
7617         info.rgPolicyMapping = mapping;
7618         SetLastError(0xdeadbeef);
7619         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7620          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7621         ok(!ret && GetLastError() == E_INVALIDARG,
7622          "expected E_INVALIDARG, got %08x\n", GetLastError());
7623         mapping[0].pszIssuerDomainPolicy = oid1;
7624         mapping[0].pszSubjectDomainPolicy = oid2;
7625         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7626          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7627         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7628         if (ret)
7629         {
7630             ok(size == sizeof(policyMappingWithOneMapping),
7631              "unexpected size %d\n", size);
7632             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7633              "unexpected value\n");
7634             LocalFree(buf);
7635         }
7636         mapping[1].pszIssuerDomainPolicy = oid3;
7637         mapping[1].pszSubjectDomainPolicy = oid4;
7638         info.cPolicyMapping = 2;
7639         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7640          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7641         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7642         if (ret)
7643         {
7644             ok(size == sizeof(policyMappingWithTwoMappings),
7645              "unexpected size %d\n", size);
7646             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7647              "unexpected value\n");
7648             LocalFree(buf);
7649         }
7650     }
7651 }
7652
7653 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7654 {
7655     DWORD size, i;
7656     CERT_POLICY_MAPPINGS_INFO *info;
7657     BOOL ret;
7658
7659     /* Each of the mapping OIDs is equivalent, so check with all of them */
7660     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7661     {
7662         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7663          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7664          &info, &size);
7665         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7666          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7667         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7668         {
7669             win_skip("no policy mappings support\n");
7670             return;
7671         }
7672         if (ret)
7673         {
7674             ok(info->cPolicyMapping == 0,
7675              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7676             LocalFree(info);
7677         }
7678         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7679          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7680          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7681         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7682         if (ret)
7683         {
7684             ok(info->cPolicyMapping == 1,
7685              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7686             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7687              "unexpected issuer policy %s\n",
7688              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7689             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7690              "2.3.4"), "unexpected subject policy %s\n",
7691              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7692             LocalFree(info);
7693         }
7694         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7695          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7696          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7697         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7698         if (ret)
7699         {
7700             ok(info->cPolicyMapping == 2,
7701              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7702             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7703              "unexpected issuer policy %s\n",
7704              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7705             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7706              "2.3.4"), "unexpected subject policy %s\n",
7707              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7708             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7709              "unexpected issuer policy %s\n",
7710              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7711             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7712              "2.5.6"), "unexpected subject policy %s\n",
7713              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7714             LocalFree(info);
7715         }
7716         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7717          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7718          NULL, NULL, &size);
7719         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7720         info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7721         if (info)
7722         {
7723             ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7724              policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7725              NULL, info, &size);
7726             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7727             HeapFree(GetProcessHeap(), 0, info);
7728         }
7729     }
7730 }
7731
7732 static const BYTE policyConstraintsWithRequireExplicit[] = {
7733 0x30,0x03,0x80,0x01,0x00 };
7734 static const BYTE policyConstraintsWithInhibitMapping[] = {
7735 0x30,0x03,0x81,0x01,0x01 };
7736 static const BYTE policyConstraintsWithBoth[] = {
7737 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7738
7739 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7740 {
7741     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7742     LPBYTE buf;
7743     DWORD size;
7744     BOOL ret;
7745
7746     /* Even though RFC 5280 explicitly states CAs must not issue empty
7747      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7748      */
7749     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7750      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7751     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7752      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7753     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7754     {
7755         win_skip("no policy constraints support\n");
7756         return;
7757     }
7758     if (ret)
7759     {
7760         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7761         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7762          "unexpected value\n");
7763         LocalFree(buf);
7764     }
7765     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7766      * is not, then a skip of 0 is encoded.
7767      */
7768     info.fRequireExplicitPolicy = TRUE;
7769     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7770      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7771     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7772     if (ret)
7773     {
7774         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7775          "unexpected size %d\n", size);
7776         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7777          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7778         LocalFree(buf);
7779     }
7780     /* With inhibit policy mapping */
7781     info.fRequireExplicitPolicy = FALSE;
7782     info.dwRequireExplicitPolicySkipCerts = 0;
7783     info.fInhibitPolicyMapping = TRUE;
7784     info.dwInhibitPolicyMappingSkipCerts = 1;
7785     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7786      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7787     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7788     if (ret)
7789     {
7790         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7791          "unexpected size %d\n", size);
7792         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7793          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7794         LocalFree(buf);
7795     }
7796     /* And with both */
7797     info.fRequireExplicitPolicy = TRUE;
7798     info.dwRequireExplicitPolicySkipCerts = 1;
7799     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7800      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7801     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7802     if (ret)
7803     {
7804         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7805          size);
7806         ok(!memcmp(buf, policyConstraintsWithBoth,
7807          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7808         LocalFree(buf);
7809     }
7810 }
7811
7812 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7813 {
7814     CERT_POLICY_CONSTRAINTS_INFO *info;
7815     DWORD size;
7816     BOOL ret;
7817
7818     /* Again, even though CAs must not issue such constraints, they can be
7819      * decoded.
7820      */
7821     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7822      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7823      &info, &size);
7824     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7825      "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7826     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7827     {
7828         win_skip("no policy mappings support\n");
7829         return;
7830     }
7831     if (ret)
7832     {
7833         ok(!info->fRequireExplicitPolicy,
7834          "expected require explicit = FALSE\n");
7835         ok(!info->fInhibitPolicyMapping,
7836          "expected implicit mapping = FALSE\n");
7837         LocalFree(info);
7838     }
7839     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7840      policyConstraintsWithRequireExplicit,
7841      sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7842      NULL, &info, &size);
7843     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7844     if (ret)
7845     {
7846         ok(info->fRequireExplicitPolicy,
7847          "expected require explicit = TRUE\n");
7848         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7849          info->dwRequireExplicitPolicySkipCerts);
7850         ok(!info->fInhibitPolicyMapping,
7851          "expected implicit mapping = FALSE\n");
7852         LocalFree(info);
7853     }
7854     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7855      policyConstraintsWithInhibitMapping,
7856      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7857      NULL, &info, &size);
7858     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7859     if (ret)
7860     {
7861         ok(!info->fRequireExplicitPolicy,
7862          "expected require explicit = FALSE\n");
7863         ok(info->fInhibitPolicyMapping,
7864          "expected implicit mapping = TRUE\n");
7865         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7866          info->dwInhibitPolicyMappingSkipCerts);
7867         LocalFree(info);
7868     }
7869     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7870      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7871      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7872     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7873     if (ret)
7874     {
7875         ok(info->fRequireExplicitPolicy,
7876          "expected require explicit = TRUE\n");
7877         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7878          info->dwRequireExplicitPolicySkipCerts);
7879         ok(info->fInhibitPolicyMapping,
7880          "expected implicit mapping = TRUE\n");
7881         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7882          info->dwInhibitPolicyMappingSkipCerts);
7883         LocalFree(info);
7884     }
7885 }
7886
7887 /* Free *pInfo with HeapFree */
7888 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7889 {
7890     BOOL ret;
7891     DWORD size = 0;
7892     HCRYPTKEY key;
7893
7894     /* This crashes
7895     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7896      */
7897     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7898     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7899      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7900     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7901      &size);
7902     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7903      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7904     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7905      NULL, &size);
7906     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7907      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7908     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7909      0, NULL, NULL, &size);
7910     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7911      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7912     /* Test with no key */
7913     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7914      0, NULL, NULL, &size);
7915     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7916      GetLastError());
7917     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7918     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7919     if (ret)
7920     {
7921         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7922          NULL, 0, NULL, NULL, &size);
7923         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7924         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7925         if (*pInfo)
7926         {
7927             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7928              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7929             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7930              GetLastError());
7931             if (ret)
7932             {
7933                 /* By default (we passed NULL as the OID) the OID is
7934                  * szOID_RSA_RSA.
7935                  */
7936                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7937                  "Expected %s, got %s\n", szOID_RSA_RSA,
7938                  (*pInfo)->Algorithm.pszObjId);
7939             }
7940         }
7941     }
7942     CryptDestroyKey(key);
7943 }
7944
7945 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7946  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7947  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7948  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7949  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7950  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7951  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7952  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7953  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7954  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7955  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7956  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7957  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7958  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7959  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7960  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7961  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7962  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7963  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7964  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7965  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7966  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7967  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7968  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7969  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7970
7971 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7972 {
7973     BOOL ret;
7974     HCRYPTKEY key;
7975     PCCERT_CONTEXT context;
7976     DWORD dwSize;
7977     ALG_ID ai;
7978
7979     /* These crash
7980     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7981     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7982     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7983     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7984      NULL);
7985      */
7986     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7987     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7988      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7989     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7990     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7991      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7992     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7993      &key);
7994     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7995      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7996
7997     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7998     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7999      &key);
8000     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8001
8002     dwSize = sizeof(ai);
8003     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8004     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8005     if(ret)
8006     {
8007       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8008       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
8009     }
8010
8011     CryptDestroyKey(key);
8012
8013     /* Repeat with forced algorithm */
8014     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
8015      &key);
8016     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8017
8018     dwSize = sizeof(ai);
8019     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8020     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8021     if(ret)
8022     {
8023       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8024       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
8025     }
8026
8027     CryptDestroyKey(key);
8028
8029     /* Test importing a public key from a certificate context */
8030     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
8031      sizeof(expiredCert));
8032     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
8033      GetLastError());
8034     if (context)
8035     {
8036         ok(!strcmp(szOID_RSA_RSA,
8037          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
8038          "Expected %s, got %s\n", szOID_RSA_RSA,
8039          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
8040         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
8041          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
8042         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8043         CryptDestroyKey(key);
8044         CertFreeCertificateContext(context);
8045     }
8046 }
8047
8048 static const char cspName[] = "WineCryptTemp";
8049
8050 static void testPortPublicKeyInfo(void)
8051 {
8052     HCRYPTPROV csp;
8053     BOOL ret;
8054     PCERT_PUBLIC_KEY_INFO info = NULL;
8055
8056     /* Just in case a previous run failed, delete this thing */
8057     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
8058      CRYPT_DELETEKEYSET);
8059     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
8060      CRYPT_NEWKEYSET);
8061     ok(ret,"CryptAcquireContextA failed\n");
8062
8063     testExportPublicKey(csp, &info);
8064     testImportPublicKey(csp, info);
8065
8066     HeapFree(GetProcessHeap(), 0, info);
8067     CryptReleaseContext(csp, 0);
8068     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
8069      CRYPT_DELETEKEYSET);
8070     ok(ret,"CryptAcquireContextA failed\n");
8071 }
8072
8073 START_TEST(encode)
8074 {
8075     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
8076      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
8077     HMODULE hCrypt32;
8078     DWORD i;
8079
8080     hCrypt32 = GetModuleHandleA("crypt32.dll");
8081     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
8082     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
8083     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
8084     {
8085         win_skip("CryptDecodeObjectEx() is not available\n");
8086         return;
8087     }
8088
8089     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
8090     {
8091         test_encodeInt(encodings[i]);
8092         test_decodeInt(encodings[i]);
8093         test_encodeEnumerated(encodings[i]);
8094         test_decodeEnumerated(encodings[i]);
8095         test_encodeFiletime(encodings[i]);
8096         test_decodeFiletime(encodings[i]);
8097         test_encodeName(encodings[i]);
8098         test_decodeName(encodings[i]);
8099         test_encodeUnicodeName(encodings[i]);
8100         test_decodeUnicodeName(encodings[i]);
8101         test_encodeNameValue(encodings[i]);
8102         test_decodeNameValue(encodings[i]);
8103         test_encodeUnicodeNameValue(encodings[i]);
8104         test_decodeUnicodeNameValue(encodings[i]);
8105         test_encodeAltName(encodings[i]);
8106         test_decodeAltName(encodings[i]);
8107         test_encodeOctets(encodings[i]);
8108         test_decodeOctets(encodings[i]);
8109         test_encodeBits(encodings[i]);
8110         test_decodeBits(encodings[i]);
8111         test_encodeBasicConstraints(encodings[i]);
8112         test_decodeBasicConstraints(encodings[i]);
8113         test_encodeRsaPublicKey(encodings[i]);
8114         test_decodeRsaPublicKey(encodings[i]);
8115         test_encodeSequenceOfAny(encodings[i]);
8116         test_decodeSequenceOfAny(encodings[i]);
8117         test_encodeExtensions(encodings[i]);
8118         test_decodeExtensions(encodings[i]);
8119         test_encodePublicKeyInfo(encodings[i]);
8120         test_decodePublicKeyInfo(encodings[i]);
8121         test_encodeCertToBeSigned(encodings[i]);
8122         test_decodeCertToBeSigned(encodings[i]);
8123         test_encodeCert(encodings[i]);
8124         test_decodeCert(encodings[i]);
8125         test_encodeCRLDistPoints(encodings[i]);
8126         test_decodeCRLDistPoints(encodings[i]);
8127         test_encodeCRLIssuingDistPoint(encodings[i]);
8128         test_decodeCRLIssuingDistPoint(encodings[i]);
8129         test_encodeCRLToBeSigned(encodings[i]);
8130         test_decodeCRLToBeSigned(encodings[i]);
8131         test_encodeEnhancedKeyUsage(encodings[i]);
8132         test_decodeEnhancedKeyUsage(encodings[i]);
8133         test_encodeAuthorityKeyId(encodings[i]);
8134         test_decodeAuthorityKeyId(encodings[i]);
8135         test_encodeAuthorityKeyId2(encodings[i]);
8136         test_decodeAuthorityKeyId2(encodings[i]);
8137         test_encodeAuthorityInfoAccess(encodings[i]);
8138         test_decodeAuthorityInfoAccess(encodings[i]);
8139         test_encodeCTL(encodings[i]);
8140         test_decodeCTL(encodings[i]);
8141         test_encodePKCSContentInfo(encodings[i]);
8142         test_decodePKCSContentInfo(encodings[i]);
8143         test_encodePKCSAttribute(encodings[i]);
8144         test_decodePKCSAttribute(encodings[i]);
8145         test_encodePKCSAttributes(encodings[i]);
8146         test_decodePKCSAttributes(encodings[i]);
8147         test_encodePKCSSMimeCapabilities(encodings[i]);
8148         test_decodePKCSSMimeCapabilities(encodings[i]);
8149         test_encodePKCSSignerInfo(encodings[i]);
8150         test_decodePKCSSignerInfo(encodings[i]);
8151         test_encodeCMSSignerInfo(encodings[i]);
8152         test_decodeCMSSignerInfo(encodings[i]);
8153         test_encodeNameConstraints(encodings[i]);
8154         test_decodeNameConstraints(encodings[i]);
8155         test_encodePolicyQualifierUserNotice(encodings[i]);
8156         test_decodePolicyQualifierUserNotice(encodings[i]);
8157         test_encodeCertPolicies(encodings[i]);
8158         test_decodeCertPolicies(encodings[i]);
8159         test_encodeCertPolicyMappings(encodings[i]);
8160         test_decodeCertPolicyMappings(encodings[i]);
8161         test_encodeCertPolicyConstraints(encodings[i]);
8162         test_decodeCertPolicyConstraints(encodings[i]);
8163     }
8164     testPortPublicKeyInfo();
8165 }