crypt32: Test decoding alternate names with embedded NULLs.
[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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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     ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1391      embeddedNullNameValue.value.dwValueType, GetLastError());
1392     if (ret)
1393     {
1394         CERT_NAME_VALUE value = { CERT_RDN_ENCODED_BLOB,
1395          { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1396
1397         todo_wine
1398         compareNameValues(&value, (const CERT_NAME_VALUE *)buf);
1399         LocalFree(buf);
1400     }
1401 }
1402
1403 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1404 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1405 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1406  'h','q','.','o','r','g',0 };
1407 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1408  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1409  0x6f, 0x72, 0x67 };
1410 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1411  0x575b, 0 };
1412 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1413 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1414  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1415 static const BYTE localhost[] = { 127, 0, 0, 1 };
1416 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1417  0x01 };
1418 static const unsigned char encodedCommonName[] = {
1419     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1420 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1421 static const BYTE encodedDirectoryName[] = {
1422 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1423 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1424
1425 static void test_encodeAltName(DWORD dwEncoding)
1426 {
1427     CERT_ALT_NAME_INFO info = { 0 };
1428     CERT_ALT_NAME_ENTRY entry = { 0 };
1429     BYTE *buf = NULL;
1430     DWORD size = 0;
1431     BOOL ret;
1432     char oid[] = "1.2.3";
1433
1434     /* Test with empty info */
1435     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1436      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1437     if (buf)
1438     {
1439         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1440         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1441         LocalFree(buf);
1442     }
1443     /* Test with an empty entry */
1444     info.cAltEntry = 1;
1445     info.rgAltEntry = &entry;
1446     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1447      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1448     ok(!ret && GetLastError() == E_INVALIDARG,
1449      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1450     /* Test with an empty pointer */
1451     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1452     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1453      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1454     if (buf)
1455     {
1456         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1457         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1458         LocalFree(buf);
1459     }
1460     /* Test with a real URL */
1461     U(entry).pwszURL = (LPWSTR)url;
1462     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1463      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1464     if (buf)
1465     {
1466         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1467         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1468         LocalFree(buf);
1469     }
1470     /* Now with the URL containing an invalid IA5 char */
1471     U(entry).pwszURL = (LPWSTR)nihongoURL;
1472     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1473      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1474     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1475      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1476     /* The first invalid character is at index 7 */
1477     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1478      "Expected invalid char at index 7, got %d\n",
1479      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1480     /* Now with the URL missing a scheme */
1481     U(entry).pwszURL = (LPWSTR)dnsName;
1482     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1483      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1484     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1485     if (buf)
1486     {
1487         /* This succeeds, but it shouldn't, so don't worry about conforming */
1488         LocalFree(buf);
1489     }
1490     /* Now with a DNS name */
1491     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1492     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1493      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1494     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1495     if (buf)
1496     {
1497         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1498         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1499         LocalFree(buf);
1500     }
1501     /* Test with an IP address */
1502     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1503     U(entry).IPAddress.cbData = sizeof(localhost);
1504     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1505     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1506      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1507     if (buf)
1508     {
1509         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1510         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1511         LocalFree(buf);
1512     }
1513     /* Test with OID */
1514     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1515     U(entry).pszRegisteredID = oid;
1516     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1517      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1518     if (buf)
1519     {
1520         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1521         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1522         LocalFree(buf);
1523     }
1524     /* Test with directory name */
1525     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1526     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1527     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1528     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1529      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1530     if (buf)
1531     {
1532         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1533         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1534         LocalFree(buf);
1535     }
1536 }
1537
1538 static void test_decodeAltName(DWORD dwEncoding)
1539 {
1540     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1541      0x00, 0x00, 0x01 };
1542     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1543      0x01 };
1544     static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1545      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1546     static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1547      0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1548     static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1549      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1550     BOOL ret;
1551     BYTE *buf = NULL;
1552     DWORD bufSize = 0;
1553     CERT_ALT_NAME_INFO *info;
1554
1555     /* Test some bogus ones first */
1556     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1557      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1558      NULL, &buf, &bufSize);
1559     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1560      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1561      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1562      GetLastError());
1563     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1564      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1565      &bufSize);
1566     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1567      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1568      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1569      GetLastError());
1570     /* Now expected cases */
1571     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1572      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1573     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1574     if (buf)
1575     {
1576         info = (CERT_ALT_NAME_INFO *)buf;
1577
1578         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1579          info->cAltEntry);
1580         LocalFree(buf);
1581     }
1582     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1583      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1584     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1585     if (buf)
1586     {
1587         info = (CERT_ALT_NAME_INFO *)buf;
1588
1589         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1590          info->cAltEntry);
1591         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1592          "Expected CERT_ALT_NAME_URL, got %d\n",
1593          info->rgAltEntry[0].dwAltNameChoice);
1594         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1595          "Expected empty URL\n");
1596         LocalFree(buf);
1597     }
1598     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1599      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1600     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1601     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1602      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1603     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1604     if (buf)
1605     {
1606         info = (CERT_ALT_NAME_INFO *)buf;
1607
1608         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1609          info->cAltEntry);
1610         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1611          "Expected CERT_ALT_NAME_URL, got %d\n",
1612          info->rgAltEntry[0].dwAltNameChoice);
1613         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1614         LocalFree(buf);
1615     }
1616     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1617      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1618     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1619     if (buf)
1620     {
1621         info = (CERT_ALT_NAME_INFO *)buf;
1622
1623         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1624          info->cAltEntry);
1625         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1626          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1627          info->rgAltEntry[0].dwAltNameChoice);
1628         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1629          "Unexpected DNS name\n");
1630         LocalFree(buf);
1631     }
1632     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1633      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1634     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1635     if (buf)
1636     {
1637         info = (CERT_ALT_NAME_INFO *)buf;
1638
1639         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1640          info->cAltEntry);
1641         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1642          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1643          info->rgAltEntry[0].dwAltNameChoice);
1644         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1645          "Unexpected IP address length %d\n",
1646           U(info->rgAltEntry[0]).IPAddress.cbData);
1647         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1648          sizeof(localhost)), "Unexpected IP address value\n");
1649         LocalFree(buf);
1650     }
1651     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1652      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1653     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1654     if (buf)
1655     {
1656         info = (CERT_ALT_NAME_INFO *)buf;
1657
1658         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1659          info->cAltEntry);
1660         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1661          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1662          info->rgAltEntry[0].dwAltNameChoice);
1663         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1664            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1665         LocalFree(buf);
1666     }
1667     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1668      encodedDirectoryName, sizeof(encodedDirectoryName),
1669      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1670     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1671     if (buf)
1672     {
1673         info = (CERT_ALT_NAME_INFO *)buf;
1674
1675         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1676          info->cAltEntry);
1677         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1678          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1679          info->rgAltEntry[0].dwAltNameChoice);
1680         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1681          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1682           U(info->rgAltEntry[0]).DirectoryName.cbData);
1683         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1684          encodedCommonName, sizeof(encodedCommonName)),
1685          "Unexpected directory name value\n");
1686         LocalFree(buf);
1687     }
1688     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1689      dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1690      NULL, &buf, &bufSize);
1691     /* Fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned about the
1692      * particular failure, just that it doesn't decode.
1693      */
1694     todo_wine
1695     ok(!ret, "expected failure\n");
1696     /* An embedded bell character is allowed, however. */
1697     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1698      dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1699      NULL, &buf, &bufSize);
1700     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1701     if (ret)
1702     {
1703         info = (CERT_ALT_NAME_INFO *)buf;
1704
1705         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1706          info->cAltEntry);
1707         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1708          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1709          info->rgAltEntry[0].dwAltNameChoice);
1710         LocalFree(buf);
1711     }
1712     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1713      url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1714      NULL, &buf, &bufSize);
1715     /* Again, fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned
1716      * about the particular failure, just that it doesn't decode.
1717      */
1718     todo_wine
1719     ok(!ret, "expected failure\n");
1720 }
1721
1722 struct UnicodeExpectedError
1723 {
1724     DWORD   valueType;
1725     LPCWSTR str;
1726     DWORD   errorIndex;
1727     DWORD   error;
1728 };
1729
1730 static const WCHAR oneW[] = { '1',0 };
1731 static const WCHAR aW[] = { 'a',0 };
1732 static const WCHAR quoteW[] = { '"', 0 };
1733
1734 static struct UnicodeExpectedError unicodeErrors[] = {
1735  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1736  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1737  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1738  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1739  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1740  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1741 };
1742
1743 struct UnicodeExpectedResult
1744 {
1745     DWORD           valueType;
1746     LPCWSTR         str;
1747     CRYPT_DATA_BLOB encoded;
1748 };
1749
1750 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1751 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1752 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1753 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1754 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1755 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1756 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1757 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1758 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1759 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1760 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1761 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1762  0x5b };
1763 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1764  0x6f,0x5b };
1765 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1766  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1767 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1768  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1769
1770 static struct UnicodeExpectedResult unicodeResults[] = {
1771  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1772  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1773  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1774  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1775  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1776  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1777  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1778  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1779  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1780  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1781  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1782  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1783  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1784 };
1785
1786 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1787  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1788  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1789 };
1790
1791 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1792 {
1793     BYTE *buf = NULL;
1794     DWORD size = 0, i;
1795     BOOL ret;
1796     CERT_NAME_VALUE value;
1797
1798     if (0)
1799     {
1800         /* Crashes on win9x */
1801         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1802          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1803         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1804          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1805     }
1806     /* Have to have a string of some sort */
1807     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1808     value.Value.pbData = NULL;
1809     value.Value.cbData = 0;
1810     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1811      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1812     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1813      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1814     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1815     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1816      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1817     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1818      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1819     value.dwValueType = CERT_RDN_ANY_TYPE;
1820     value.Value.pbData = (LPBYTE)oneW;
1821     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1822      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1823     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1824      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1825     value.Value.cbData = sizeof(oneW);
1826     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1827      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1828     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1829      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1830     /* An encoded string with specified length isn't good enough either */
1831     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1832     value.Value.pbData = oneUniversal;
1833     value.Value.cbData = sizeof(oneUniversal);
1834     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1835      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1836     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1837      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1838     /* More failure checking */
1839     value.Value.cbData = 0;
1840     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1841     {
1842         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1843         value.dwValueType = unicodeErrors[i].valueType;
1844         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1845          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1846         ok(!ret && GetLastError() == unicodeErrors[i].error,
1847          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1848          unicodeErrors[i].error, GetLastError());
1849         ok(size == unicodeErrors[i].errorIndex,
1850          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1851          size);
1852     }
1853     /* cbData can be zero if the string is NULL-terminated */
1854     value.Value.cbData = 0;
1855     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1856     {
1857         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1858         value.dwValueType = unicodeResults[i].valueType;
1859         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1860          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1861         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1862          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1863         if (buf)
1864         {
1865             ok(size == unicodeResults[i].encoded.cbData,
1866              "Value type %d: expected size %d, got %d\n",
1867              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1868             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1869              "Value type %d: unexpected value\n", value.dwValueType);
1870             LocalFree(buf);
1871         }
1872     }
1873     /* These "encode," but they do so by truncating each unicode character
1874      * rather than properly encoding it.  Kept separate from the proper results,
1875      * because the encoded forms won't decode to their original strings.
1876      */
1877     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1878     {
1879         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1880         value.dwValueType = unicodeWeirdness[i].valueType;
1881         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1882          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1883         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1884         if (buf)
1885         {
1886             ok(size == unicodeWeirdness[i].encoded.cbData,
1887              "Value type %d: expected size %d, got %d\n",
1888              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1889             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1890              "Value type %d: unexpected value\n", value.dwValueType);
1891             LocalFree(buf);
1892         }
1893     }
1894 }
1895
1896 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1897 {
1898     if (n <= 0) return 0;
1899     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1900     return *str1 - *str2;
1901 }
1902
1903 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1904 {
1905     DWORD i;
1906
1907     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1908     {
1909         BYTE *buf = NULL;
1910         BOOL ret;
1911         DWORD size = 0;
1912
1913         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1914          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1915          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1916         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1917          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1918         if (ret && buf)
1919         {
1920             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1921
1922             ok(value->dwValueType == unicodeResults[i].valueType,
1923              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1924              value->dwValueType);
1925             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1926              value->Value.cbData / sizeof(WCHAR)),
1927              "Unexpected decoded value for index %d (value type %d)\n", i,
1928              unicodeResults[i].valueType);
1929             LocalFree(buf);
1930         }
1931     }
1932 }
1933
1934 struct encodedOctets
1935 {
1936     const BYTE *val;
1937     const BYTE *encoded;
1938 };
1939
1940 static const unsigned char bin46[] = { 'h','i',0 };
1941 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1942 static const unsigned char bin48[] = {
1943      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1944 static const unsigned char bin49[] = {
1945      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1946 static const unsigned char bin50[] = { 0 };
1947 static const unsigned char bin51[] = { 0x04,0x00,0 };
1948
1949 static const struct encodedOctets octets[] = {
1950     { bin46, bin47 },
1951     { bin48, bin49 },
1952     { bin50, bin51 },
1953 };
1954
1955 static void test_encodeOctets(DWORD dwEncoding)
1956 {
1957     CRYPT_DATA_BLOB blob;
1958     DWORD i;
1959
1960     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1961     {
1962         BYTE *buf = NULL;
1963         BOOL ret;
1964         DWORD bufSize = 0;
1965
1966         blob.cbData = strlen((const char*)octets[i].val);
1967         blob.pbData = (BYTE*)octets[i].val;
1968         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1969          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1970         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1971         if (buf)
1972         {
1973             ok(buf[0] == 4,
1974              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1975             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1976              buf[1], octets[i].encoded[1]);
1977             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1978              octets[i].encoded[1] + 1), "Got unexpected value\n");
1979             LocalFree(buf);
1980         }
1981     }
1982 }
1983
1984 static void test_decodeOctets(DWORD dwEncoding)
1985 {
1986     DWORD i;
1987
1988     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1989     {
1990         BYTE *buf = NULL;
1991         BOOL ret;
1992         DWORD bufSize = 0;
1993
1994         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1995          octets[i].encoded, octets[i].encoded[1] + 2,
1996          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1997         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1998         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1999          "Expected size >= %d, got %d\n",
2000            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2001         ok(buf != NULL, "Expected allocated buffer\n");
2002         if (buf)
2003         {
2004             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2005
2006             if (blob->cbData)
2007                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2008                  "Unexpected value\n");
2009             LocalFree(buf);
2010         }
2011     }
2012 }
2013
2014 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2015
2016 struct encodedBits
2017 {
2018     DWORD cUnusedBits;
2019     const BYTE *encoded;
2020     DWORD cbDecoded;
2021     const BYTE *decoded;
2022 };
2023
2024 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2025 static const unsigned char bin53[] = { 0xff,0xff };
2026 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2027 static const unsigned char bin55[] = { 0xff,0xfe };
2028 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2029 static const unsigned char bin57[] = { 0xfe };
2030 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
2031
2032 static const struct encodedBits bits[] = {
2033     /* normal test cases */
2034     { 0, bin52, 2, bin53 },
2035     { 1, bin54, 2, bin55 },
2036     /* strange test case, showing cUnusedBits >= 8 is allowed */
2037     { 9, bin56, 1, bin57 },
2038 };
2039
2040 static void test_encodeBits(DWORD dwEncoding)
2041 {
2042     DWORD i;
2043
2044     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2045     {
2046         CRYPT_BIT_BLOB blob;
2047         BOOL ret;
2048         BYTE *buf = NULL;
2049         DWORD bufSize = 0;
2050
2051         blob.cbData = sizeof(bytesToEncode);
2052         blob.pbData = (BYTE *)bytesToEncode;
2053         blob.cUnusedBits = bits[i].cUnusedBits;
2054         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2055          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2056         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2057         if (buf)
2058         {
2059             ok(bufSize == bits[i].encoded[1] + 2,
2060              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2061              bits[i].encoded[1] + 2);
2062             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2063              "%d: Unexpected value\n", i);
2064             LocalFree(buf);
2065         }
2066     }
2067 }
2068
2069 static void test_decodeBits(DWORD dwEncoding)
2070 {
2071     static const BYTE ber[] = "\x03\x02\x01\xff";
2072     static const BYTE berDecoded = 0xfe;
2073     DWORD i;
2074     BOOL ret;
2075     BYTE *buf = NULL;
2076     DWORD bufSize = 0;
2077
2078     /* normal cases */
2079     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2080     {
2081         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2082          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2083          &bufSize);
2084         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2085         if (buf)
2086         {
2087             CRYPT_BIT_BLOB *blob;
2088
2089             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2090                "Got unexpected size %d\n", bufSize);
2091             blob = (CRYPT_BIT_BLOB *)buf;
2092             ok(blob->cbData == bits[i].cbDecoded,
2093              "Got unexpected length %d, expected %d\n", blob->cbData,
2094              bits[i].cbDecoded);
2095             if (blob->cbData && bits[i].cbDecoded)
2096                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2097                  "Unexpected value\n");
2098             LocalFree(buf);
2099         }
2100     }
2101     /* special case: check that something that's valid in BER but not in DER
2102      * decodes successfully
2103      */
2104     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2105      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2106     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2107     if (buf)
2108     {
2109         CRYPT_BIT_BLOB *blob;
2110
2111         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2112            "Got unexpected size %d\n", bufSize);
2113         blob = (CRYPT_BIT_BLOB *)buf;
2114         ok(blob->cbData == sizeof(berDecoded),
2115            "Got unexpected length %d\n", blob->cbData);
2116         if (blob->cbData)
2117             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2118         LocalFree(buf);
2119     }
2120 }
2121
2122 struct Constraints2
2123 {
2124     CERT_BASIC_CONSTRAINTS2_INFO info;
2125     const BYTE *encoded;
2126 };
2127
2128 static const unsigned char bin59[] = { 0x30,0x00 };
2129 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2130 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2131 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2132 static const struct Constraints2 constraints2[] = {
2133  /* empty constraints */
2134  { { FALSE, FALSE, 0}, bin59 },
2135  /* can be a CA */
2136  { { TRUE,  FALSE, 0}, bin60 },
2137  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2138   * but that's not the case
2139   */
2140  { { FALSE, TRUE,  0}, bin61 },
2141  /* can be a CA and has path length constraints set */
2142  { { TRUE,  TRUE,  1}, bin62 },
2143 };
2144
2145 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2146 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2147  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2148  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2149  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2150 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2151  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2152  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2153  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2154  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2155
2156 static void test_encodeBasicConstraints(DWORD dwEncoding)
2157 {
2158     DWORD i, bufSize = 0;
2159     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2160     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2161      (LPBYTE)encodedDomainName };
2162     BOOL ret;
2163     BYTE *buf = NULL;
2164
2165     /* First test with the simpler info2 */
2166     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2167     {
2168         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2169          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2170          &bufSize);
2171         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2172         if (buf)
2173         {
2174             ok(bufSize == constraints2[i].encoded[1] + 2,
2175              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2176              bufSize);
2177             ok(!memcmp(buf, constraints2[i].encoded,
2178              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2179             LocalFree(buf);
2180         }
2181     }
2182     /* Now test with more complex basic constraints */
2183     info.SubjectType.cbData = 0;
2184     info.fPathLenConstraint = FALSE;
2185     info.cSubtreesConstraint = 0;
2186     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2187      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2188     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2189      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2190     if (buf)
2191     {
2192         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2193         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2194          "Unexpected value\n");
2195         LocalFree(buf);
2196     }
2197     /* None of the certs I examined had any subtree constraint, but I test one
2198      * anyway just in case.
2199      */
2200     info.cSubtreesConstraint = 1;
2201     info.rgSubtreesConstraint = &nameBlob;
2202     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2203      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2204     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2205      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2206     if (buf)
2207     {
2208         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2209         ok(!memcmp(buf, constraintWithDomainName,
2210          sizeof(constraintWithDomainName)), "Unexpected value\n");
2211         LocalFree(buf);
2212     }
2213     /* FIXME: test encoding with subject type. */
2214 }
2215
2216 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2217
2218 static void test_decodeBasicConstraints(DWORD dwEncoding)
2219 {
2220     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2221      0xff };
2222     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2223     DWORD i;
2224     BOOL ret;
2225     BYTE *buf = NULL;
2226     DWORD bufSize = 0;
2227
2228     /* First test with simpler info2 */
2229     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2230     {
2231         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2232          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2233          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2234         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2235          GetLastError());
2236         if (buf)
2237         {
2238             CERT_BASIC_CONSTRAINTS2_INFO *info =
2239              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2240
2241             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2242              "Unexpected value for item %d\n", i);
2243             LocalFree(buf);
2244         }
2245     }
2246     /* Check with the order of encoded elements inverted */
2247     buf = (PBYTE)1;
2248     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2249      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2250      &bufSize);
2251     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2252      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2253      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2254      GetLastError());
2255     ok(!buf, "Expected buf to be set to NULL\n");
2256     /* Check with a non-DER bool */
2257     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2258      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2259      &buf, &bufSize);
2260     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2261     if (buf)
2262     {
2263         CERT_BASIC_CONSTRAINTS2_INFO *info =
2264          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2265
2266         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2267         LocalFree(buf);
2268     }
2269     /* Check with a non-basic constraints value */
2270     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2271      encodedCommonName, encodedCommonName[1] + 2,
2272      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2273     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2274      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2275      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2276      GetLastError());
2277     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2278     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2279      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2280      &buf, &bufSize);
2281     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2282     if (buf)
2283     {
2284         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2285
2286         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2287         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2288         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2289         LocalFree(buf);
2290     }
2291     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2292      constraintWithDomainName, sizeof(constraintWithDomainName),
2293      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2294     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2295     if (buf)
2296     {
2297         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2298
2299         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2300         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2301         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2302         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2303         {
2304             ok(info->rgSubtreesConstraint[0].cbData ==
2305              sizeof(encodedDomainName), "Wrong size %d\n",
2306              info->rgSubtreesConstraint[0].cbData);
2307             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2308              sizeof(encodedDomainName)), "Unexpected value\n");
2309         }
2310         LocalFree(buf);
2311     }
2312 }
2313
2314 /* These are terrible public keys of course, I'm just testing encoding */
2315 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2316 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2317 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2318 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2319 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2320 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2321 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2322 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2323
2324 struct EncodedRSAPubKey
2325 {
2326     const BYTE *modulus;
2327     size_t modulusLen;
2328     const BYTE *encoded;
2329     size_t decodedModulusLen;
2330 };
2331
2332 struct EncodedRSAPubKey rsaPubKeys[] = {
2333     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2334     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2335     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2336     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2337 };
2338
2339 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2340 {
2341     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2342     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2343     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2344     BOOL ret;
2345     BYTE *buf = NULL;
2346     DWORD bufSize = 0, i;
2347
2348     /* Try with a bogus blob type */
2349     hdr->bType = 2;
2350     hdr->bVersion = CUR_BLOB_VERSION;
2351     hdr->reserved = 0;
2352     hdr->aiKeyAlg = CALG_RSA_KEYX;
2353     rsaPubKey->magic = 0x31415352;
2354     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2355     rsaPubKey->pubexp = 65537;
2356     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2357      sizeof(modulus1));
2358
2359     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2360      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2361     ok(!ret && GetLastError() == E_INVALIDARG,
2362      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2363     /* Now with a bogus reserved field */
2364     hdr->bType = PUBLICKEYBLOB;
2365     hdr->reserved = 1;
2366     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2367      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2368     if (buf)
2369     {
2370         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2371          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2372         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2373         LocalFree(buf);
2374     }
2375     /* Now with a bogus blob version */
2376     hdr->reserved = 0;
2377     hdr->bVersion = 0;
2378     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2379      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2380     if (buf)
2381     {
2382         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2383          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2384         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2385         LocalFree(buf);
2386     }
2387     /* And with a bogus alg ID */
2388     hdr->bVersion = CUR_BLOB_VERSION;
2389     hdr->aiKeyAlg = CALG_DES;
2390     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2391      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2392     if (buf)
2393     {
2394         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2395          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2396         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2397         LocalFree(buf);
2398     }
2399     /* Check a couple of RSA-related OIDs */
2400     hdr->aiKeyAlg = CALG_RSA_KEYX;
2401     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2402      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2403     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2404      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2405     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2406      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2407     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2408      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2409     /* Finally, all valid */
2410     hdr->aiKeyAlg = CALG_RSA_KEYX;
2411     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2412     {
2413         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2414          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2415         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2416          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2417         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2418         if (buf)
2419         {
2420             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2421              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2422              bufSize);
2423             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2424              "Unexpected value\n");
2425             LocalFree(buf);
2426         }
2427     }
2428 }
2429
2430 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2431 {
2432     DWORD i;
2433     LPBYTE buf = NULL;
2434     DWORD bufSize = 0;
2435     BOOL ret;
2436
2437     /* Try with a bad length */
2438     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2439      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2440      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2441     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2442      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2443      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2444      GetLastError());
2445     /* Try with a couple of RSA-related OIDs */
2446     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2447      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2448      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2449     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2450      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2451     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2452      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2453      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2454     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2455      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2456     /* Now try success cases */
2457     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2458     {
2459         bufSize = 0;
2460         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2461          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2462          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2463         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2464         if (buf)
2465         {
2466             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2467             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2468
2469             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2470              rsaPubKeys[i].decodedModulusLen,
2471              "Wrong size %d\n", bufSize);
2472             ok(hdr->bType == PUBLICKEYBLOB,
2473              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2474              hdr->bType);
2475             ok(hdr->bVersion == CUR_BLOB_VERSION,
2476              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2477              CUR_BLOB_VERSION, hdr->bVersion);
2478             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2479              hdr->reserved);
2480             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2481              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2482             ok(rsaPubKey->magic == 0x31415352,
2483              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2484             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2485              "Wrong bit len %d\n", rsaPubKey->bitlen);
2486             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2487              rsaPubKey->pubexp);
2488             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2489              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2490              "Unexpected modulus\n");
2491             LocalFree(buf);
2492         }
2493     }
2494 }
2495
2496 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2497  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2498  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2499
2500 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2501  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2502  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2503  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2504
2505 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2506 {
2507     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2508     CRYPT_SEQUENCE_OF_ANY seq;
2509     DWORD i;
2510     BOOL ret;
2511     BYTE *buf = NULL;
2512     DWORD bufSize = 0;
2513
2514     /* Encode a homogeneous sequence */
2515     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2516     {
2517         blobs[i].cbData = ints[i].encoded[1] + 2;
2518         blobs[i].pbData = (BYTE *)ints[i].encoded;
2519     }
2520     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2521     seq.rgValue = blobs;
2522
2523     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2524      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2525     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2526     if (buf)
2527     {
2528         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2529         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2530         LocalFree(buf);
2531     }
2532     /* Change the type of the first element in the sequence, and give it
2533      * another go
2534      */
2535     blobs[0].cbData = times[0].encodedTime[1] + 2;
2536     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2537     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2538      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2539     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2540     if (buf)
2541     {
2542         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2543         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2544          "Unexpected value\n");
2545         LocalFree(buf);
2546     }
2547 }
2548
2549 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2550 {
2551     BOOL ret;
2552     BYTE *buf = NULL;
2553     DWORD bufSize = 0;
2554
2555     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2556      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2557     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2558     if (buf)
2559     {
2560         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2561         DWORD i;
2562
2563         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2564          "Wrong elements %d\n", seq->cValue);
2565         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2566         {
2567             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2568              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2569              seq->rgValue[i].cbData);
2570             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2571              ints[i].encoded[1] + 2), "Unexpected value\n");
2572         }
2573         LocalFree(buf);
2574     }
2575     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2576      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2577      &bufSize);
2578     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2579     if (buf)
2580     {
2581         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2582
2583         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2584          "Wrong elements %d\n", seq->cValue);
2585         /* Just check the first element since it's all that changed */
2586         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2587          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2588          seq->rgValue[0].cbData);
2589         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2590          times[0].encodedTime[1] + 2), "Unexpected value\n");
2591         LocalFree(buf);
2592     }
2593 }
2594
2595 struct encodedExtensions
2596 {
2597     CERT_EXTENSIONS exts;
2598     const BYTE *encoded;
2599 };
2600
2601 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2602 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2603 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2604 static CERT_EXTENSION criticalExt =
2605  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2606 static CERT_EXTENSION nonCriticalExt =
2607  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2608 static CHAR oid_short[] = "1.1";
2609 static CERT_EXTENSION extWithShortOid =
2610  { oid_short, FALSE, { 0, NULL } };
2611
2612 static const BYTE ext0[] = { 0x30,0x00 };
2613 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2614                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2615 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2616                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2617 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2618
2619 static const struct encodedExtensions exts[] = {
2620  { { 0, NULL }, ext0 },
2621  { { 1, &criticalExt }, ext1 },
2622  { { 1, &nonCriticalExt }, ext2 },
2623  { { 1, &extWithShortOid }, ext3 }
2624 };
2625
2626 static void test_encodeExtensions(DWORD dwEncoding)
2627 {
2628     DWORD i;
2629
2630     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2631     {
2632         BOOL ret;
2633         BYTE *buf = NULL;
2634         DWORD bufSize = 0;
2635
2636         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2637          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2638         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2639         if (buf)
2640         {
2641             ok(bufSize == exts[i].encoded[1] + 2,
2642              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2643             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2644              "Unexpected value\n");
2645             LocalFree(buf);
2646         }
2647     }
2648 }
2649
2650 static void test_decodeExtensions(DWORD dwEncoding)
2651 {
2652     DWORD i;
2653
2654     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2655     {
2656         BOOL ret;
2657         BYTE *buf = NULL;
2658         DWORD bufSize = 0;
2659
2660         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2661          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2662          NULL, &buf, &bufSize);
2663         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2664         if (buf)
2665         {
2666             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2667             DWORD j;
2668
2669             ok(ext->cExtension == exts[i].exts.cExtension,
2670              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2671              ext->cExtension);
2672             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2673             {
2674                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2675                  exts[i].exts.rgExtension[j].pszObjId),
2676                  "Expected OID %s, got %s\n",
2677                  exts[i].exts.rgExtension[j].pszObjId,
2678                  ext->rgExtension[j].pszObjId);
2679                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2680                  exts[i].exts.rgExtension[j].Value.pbData,
2681                  exts[i].exts.rgExtension[j].Value.cbData),
2682                  "Unexpected value\n");
2683             }
2684             LocalFree(buf);
2685         }
2686     }
2687 }
2688
2689 /* MS encodes public key info with a NULL if the algorithm identifier's
2690  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2691  * it encodes them by omitting the algorithm parameters.  It accepts either
2692  * form for decoding.
2693  */
2694 struct encodedPublicKey
2695 {
2696     CERT_PUBLIC_KEY_INFO info;
2697     const BYTE *encoded;
2698     const BYTE *encodedNoNull;
2699     CERT_PUBLIC_KEY_INFO decoded;
2700 };
2701
2702 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2703  0xe, 0xf };
2704 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2705
2706 static const unsigned char bin64[] = {
2707     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2708 static const unsigned char bin65[] = {
2709     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2710 static const unsigned char bin66[] = {
2711     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2712 static const unsigned char bin67[] = {
2713     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2714 static const unsigned char bin68[] = {
2715     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2716     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2717 static const unsigned char bin69[] = {
2718     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2719     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2720 static const unsigned char bin70[] = {
2721     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2722     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2723     0x0f};
2724 static const unsigned char bin71[] = {
2725     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2726     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2727     0x0f};
2728 static unsigned char bin72[] = { 0x05,0x00};
2729
2730 static CHAR oid_bogus[] = "1.2.3",
2731             oid_rsa[]   = szOID_RSA;
2732
2733 static const struct encodedPublicKey pubKeys[] = {
2734  /* with a bogus OID */
2735  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2736   bin64, bin65,
2737   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2738  /* some normal keys */
2739  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2740   bin66, bin67,
2741   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2742  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2743   bin68, bin69,
2744   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2745  /* with add'l parameters--note they must be DER-encoded */
2746  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2747   (BYTE *)aKey, 0 } },
2748   bin70, bin71,
2749   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2750   (BYTE *)aKey, 0 } } },
2751 };
2752
2753 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2754 {
2755     DWORD i;
2756
2757     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2758     {
2759         BOOL ret;
2760         BYTE *buf = NULL;
2761         DWORD bufSize = 0;
2762
2763         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2764          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2765          &bufSize);
2766         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2767          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2768         if (buf)
2769         {
2770             ok(bufSize == pubKeys[i].encoded[1] + 2,
2771              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2772             if (bufSize == pubKeys[i].encoded[1] + 2)
2773                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2774                  "Unexpected value\n");
2775             LocalFree(buf);
2776         }
2777     }
2778 }
2779
2780 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2781  const CERT_PUBLIC_KEY_INFO *got)
2782 {
2783     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2784      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2785      got->Algorithm.pszObjId);
2786     ok(expected->Algorithm.Parameters.cbData ==
2787      got->Algorithm.Parameters.cbData,
2788      "Expected parameters of %d bytes, got %d\n",
2789      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2790     if (expected->Algorithm.Parameters.cbData)
2791         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2792          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2793          "Unexpected algorithm parameters\n");
2794     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2795      "Expected public key of %d bytes, got %d\n",
2796      expected->PublicKey.cbData, got->PublicKey.cbData);
2797     if (expected->PublicKey.cbData)
2798         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2799          got->PublicKey.cbData), "Unexpected public key value\n");
2800 }
2801
2802 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2803 {
2804     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2805      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2806      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2807      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2808     DWORD i;
2809     BOOL ret;
2810     BYTE *buf = NULL;
2811     DWORD bufSize = 0;
2812
2813     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2814     {
2815         /* The NULL form decodes to the decoded member */
2816         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2817          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2818          NULL, &buf, &bufSize);
2819         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2820         if (buf)
2821         {
2822             comparePublicKeyInfo(&pubKeys[i].decoded,
2823              (CERT_PUBLIC_KEY_INFO *)buf);
2824             LocalFree(buf);
2825         }
2826         /* The non-NULL form decodes to the original */
2827         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2828          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2829          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2830         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2831         if (buf)
2832         {
2833             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2834             LocalFree(buf);
2835         }
2836     }
2837     /* Test with bogus (not valid DER) parameters */
2838     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2839      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2840      NULL, &buf, &bufSize);
2841     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2842      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2843      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2844      GetLastError());
2845 }
2846
2847 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2848  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2849  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2850  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2851  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2852 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2853  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2854  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2855  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2856  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2857 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2858  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2859  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2860  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2861  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2862 static const BYTE v4Cert[] = {
2863 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2864 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2865 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2866 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2867 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2868  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2869  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2870  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2871  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2872  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2873  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2874 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2875  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2876  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2877  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2878  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2879  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2880  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2881 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2882  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2883  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2884  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2885  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2886  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2887  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2888  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2889  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2890  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2891 static const BYTE v1CertWithPubKey[] = {
2892 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2893 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2894 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2895 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2896 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2897 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2898 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2899 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2900 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2901 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2902 0x01,0x01 };
2903 static const BYTE v1CertWithPubKeyNoNull[] = {
2904 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2905 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2906 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2907 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2908 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2909 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2910 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2911 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2912 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2913 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2914 static const BYTE v1CertWithSubjectKeyId[] = {
2915 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2916 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2917 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2918 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2919 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2920 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2921 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2922 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2923 0x4c,0x61,0x6e,0x67,0x00 };
2924 static const BYTE v1CertWithIssuerUniqueId[] = {
2925 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2926 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2927 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2928 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2929 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2930 0x30,0x81,0x99,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,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2939 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2940 0x01,0x01,0xff,0x02,0x01,0x01 };
2941 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2942 0x30,0x81,0x97,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,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2951 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2952 0xff,0x02,0x01,0x01 };
2953
2954 static const BYTE serialNum[] = { 0x01 };
2955
2956 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2957 {
2958     BOOL ret;
2959     BYTE *buf = NULL;
2960     DWORD size = 0;
2961     CERT_INFO info = { 0 };
2962     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2963     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2964     CERT_EXTENSION ext;
2965
2966     if (0)
2967     {
2968         /* Test with NULL pvStructInfo (crashes on win9x) */
2969         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2970          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2971         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2972          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2973     }
2974     /* Test with a V1 cert */
2975     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2976      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2977     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2978      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2979     if (buf)
2980     {
2981         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2982          v1Cert[1] + 2, size);
2983         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2984         LocalFree(buf);
2985     }
2986     /* Test v2 cert */
2987     info.dwVersion = CERT_V2;
2988     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2989      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2990     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2991      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2992     if (buf)
2993     {
2994         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2995         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2996         LocalFree(buf);
2997     }
2998     /* Test v3 cert */
2999     info.dwVersion = CERT_V3;
3000     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3001      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3002     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3003      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3004     if (buf)
3005     {
3006         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3007         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3008         LocalFree(buf);
3009     }
3010     /* A v4 cert? */
3011     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3012     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3013      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3014     if (buf)
3015     {
3016         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3017         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3018         LocalFree(buf);
3019     }
3020     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3021      * API doesn't prevent it)
3022      */
3023     info.dwVersion = CERT_V1;
3024     info.cExtension = 1;
3025     info.rgExtension = &criticalExt;
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 (buf)
3031     {
3032         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3033         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3034         LocalFree(buf);
3035     }
3036     /* test v1 cert with a serial number */
3037     info.SerialNumber.cbData = sizeof(serialNum);
3038     info.SerialNumber.pbData = (BYTE *)serialNum;
3039     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3040      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3041     if (buf)
3042     {
3043         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3044         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3045         LocalFree(buf);
3046     }
3047     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3048     info.dwVersion = CERT_V1;
3049     info.cExtension = 0;
3050     info.IssuerUniqueId.cbData = sizeof(serialNum);
3051     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3052     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3053      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3054     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3055     if (buf)
3056     {
3057         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3058         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3059          "Got unexpected value\n");
3060         LocalFree(buf);
3061     }
3062     /* Test v1 cert with an issuer name, a subject name, and a serial number */
3063     info.IssuerUniqueId.cbData = 0;
3064     info.IssuerUniqueId.pbData = NULL;
3065     info.cExtension = 1;
3066     info.rgExtension = &criticalExt;
3067     info.Issuer.cbData = sizeof(encodedCommonName);
3068     info.Issuer.pbData = (BYTE *)encodedCommonName;
3069     info.Subject.cbData = sizeof(encodedCommonName);
3070     info.Subject.pbData = (BYTE *)encodedCommonName;
3071     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3072      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3073     if (buf)
3074     {
3075         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3076         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3077         LocalFree(buf);
3078     }
3079     /* Add a public key */
3080     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3081     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3082     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3083     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3084      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3085     if (buf)
3086     {
3087         ok(size == sizeof(v1CertWithPubKey) ||
3088          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3089         if (size == sizeof(v1CertWithPubKey))
3090             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3091         else if (size == sizeof(v1CertWithPubKeyNoNull))
3092             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3093              "Got unexpected value\n");
3094         LocalFree(buf);
3095     }
3096     /* Again add an issuer unique id */
3097     info.IssuerUniqueId.cbData = sizeof(serialNum);
3098     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3099     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3100      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3101     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3102     if (buf)
3103     {
3104         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3105          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3106          "Wrong size %d\n", size);
3107         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3108             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3109              size), "unexpected value\n");
3110         else if (size ==
3111          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3112             ok(!memcmp(buf,
3113              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3114              "unexpected value\n");
3115         LocalFree(buf);
3116     }
3117     /* Remove the public key, and add a subject key identifier extension */
3118     info.IssuerUniqueId.cbData = 0;
3119     info.IssuerUniqueId.pbData = NULL;
3120     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3121     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3122     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3123     ext.pszObjId = oid_subject_key_identifier;
3124     ext.fCritical = FALSE;
3125     ext.Value.cbData = sizeof(octetCommonNameValue);
3126     ext.Value.pbData = octetCommonNameValue;
3127     info.cExtension = 1;
3128     info.rgExtension = &ext;
3129     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3130      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3131     if (buf)
3132     {
3133         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3134         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3135         LocalFree(buf);
3136     }
3137 }
3138
3139 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3140 {
3141     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3142      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3143     BOOL ret;
3144     BYTE *buf = NULL;
3145     DWORD size = 0, i;
3146
3147     /* Test with NULL pbEncoded */
3148     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3149      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3150     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3151      GetLastError() == OSS_BAD_ARG /* Win9x */),
3152      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3153     if (0)
3154     {
3155         /* Crashes on win9x */
3156         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3157          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3158         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3159          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3160     }
3161     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3162      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3163      * serial number, an issuer, a subject, and a public key.
3164      */
3165     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3166     {
3167         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3168          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3169          &buf, &size);
3170         ok(!ret, "Expected failure\n");
3171     }
3172     /* The following succeeds, even though v1 certs are not allowed to have
3173      * extensions.
3174      */
3175     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3176      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3177      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3178     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3179     if (ret)
3180     {
3181         CERT_INFO *info = (CERT_INFO *)buf;
3182
3183         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3184         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3185          info->dwVersion);
3186         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3187          info->cExtension);
3188         LocalFree(buf);
3189     }
3190     /* The following also succeeds, even though V1 certs are not allowed to
3191      * have issuer unique ids.
3192      */
3193     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3194      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3195      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3196      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3197     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3198     if (ret)
3199     {
3200         CERT_INFO *info = (CERT_INFO *)buf;
3201
3202         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3203         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3204          info->dwVersion);
3205         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3206          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3207         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3208          "unexpected issuer unique id value\n");
3209         LocalFree(buf);
3210     }
3211     /* Now check with serial number, subject and issuer specified */
3212     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3213      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3214     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3215     if (buf)
3216     {
3217         CERT_INFO *info = (CERT_INFO *)buf;
3218
3219         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3220         ok(info->SerialNumber.cbData == 1,
3221          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3222         ok(*info->SerialNumber.pbData == *serialNum,
3223          "Expected serial number %d, got %d\n", *serialNum,
3224          *info->SerialNumber.pbData);
3225         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3226          "Wrong size %d\n", info->Issuer.cbData);
3227         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3228          "Unexpected issuer\n");
3229         ok(info->Subject.cbData == sizeof(encodedCommonName),
3230          "Wrong size %d\n", info->Subject.cbData);
3231         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3232          info->Subject.cbData), "Unexpected subject\n");
3233         LocalFree(buf);
3234     }
3235     /* Check again with pub key specified */
3236     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3237      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3238      &buf, &size);
3239     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3240     if (buf)
3241     {
3242         CERT_INFO *info = (CERT_INFO *)buf;
3243
3244         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3245         ok(info->SerialNumber.cbData == 1,
3246          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3247         ok(*info->SerialNumber.pbData == *serialNum,
3248          "Expected serial number %d, got %d\n", *serialNum,
3249          *info->SerialNumber.pbData);
3250         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3251          "Wrong size %d\n", info->Issuer.cbData);
3252         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3253          "Unexpected issuer\n");
3254         ok(info->Subject.cbData == sizeof(encodedCommonName),
3255          "Wrong size %d\n", info->Subject.cbData);
3256         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3257          info->Subject.cbData), "Unexpected subject\n");
3258         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3259          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3260          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3261         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3262          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3263         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3264          sizeof(aKey)), "Unexpected public key\n");
3265         LocalFree(buf);
3266     }
3267 }
3268
3269 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3270  0xe, 0xf };
3271
3272 static const BYTE signedBigCert[] = {
3273  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3274  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3275  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3276  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3277  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3278  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3279  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3280  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3281  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3282  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3283  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3284  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3285
3286 static void test_encodeCert(DWORD dwEncoding)
3287 {
3288     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3289      * also that bigCert is a NULL-terminated string, so don't count its
3290      * last byte (otherwise the signed cert won't decode.)
3291      */
3292     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3293      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3294     BOOL ret;
3295     BYTE *buf = NULL;
3296     DWORD bufSize = 0;
3297
3298     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3299      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3300     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3301     if (buf)
3302     {
3303         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3304         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3305         LocalFree(buf);
3306     }
3307 }
3308
3309 static void test_decodeCert(DWORD dwEncoding)
3310 {
3311     BOOL ret;
3312     BYTE *buf = NULL;
3313     DWORD size = 0;
3314
3315     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3316      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3317     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3318     if (buf)
3319     {
3320         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3321
3322         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3323          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3324         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3325          "Unexpected cert\n");
3326         ok(info->Signature.cbData == sizeof(hash),
3327          "Wrong signature size %d\n", info->Signature.cbData);
3328         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3329          "Unexpected signature\n");
3330         LocalFree(buf);
3331     }
3332     /* A signed cert decodes as a CERT_INFO too */
3333     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3334      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3335     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3336     if (buf)
3337     {
3338         CERT_INFO *info = (CERT_INFO *)buf;
3339
3340         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3341         ok(info->SerialNumber.cbData == 1,
3342          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3343         ok(*info->SerialNumber.pbData == *serialNum,
3344          "Expected serial number %d, got %d\n", *serialNum,
3345          *info->SerialNumber.pbData);
3346         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3347          "Wrong size %d\n", info->Issuer.cbData);
3348         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3349          "Unexpected issuer\n");
3350         ok(info->Subject.cbData == sizeof(encodedCommonName),
3351          "Wrong size %d\n", info->Subject.cbData);
3352         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3353          info->Subject.cbData), "Unexpected subject\n");
3354         LocalFree(buf);
3355     }
3356 }
3357
3358 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3359 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3360  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3361  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3362 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3363  0x00, 0x03 };
3364 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3365  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3366  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3367 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3368  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3369  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3370  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3371  0x2e, 0x6f, 0x72, 0x67 };
3372 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3373  CRL_REASON_AFFILIATION_CHANGED;
3374
3375 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3376 {
3377     CRL_DIST_POINTS_INFO info = { 0 };
3378     CRL_DIST_POINT point = { { 0 } };
3379     CERT_ALT_NAME_ENTRY entry = { 0 };
3380     BOOL ret;
3381     BYTE *buf = NULL;
3382     DWORD size = 0;
3383
3384     /* Test with an empty info */
3385     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3386      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3387     ok(!ret && GetLastError() == E_INVALIDARG,
3388      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3389     /* Test with one empty dist point */
3390     info.cDistPoint = 1;
3391     info.rgDistPoint = &point;
3392     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3393      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3394     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3395     if (buf)
3396     {
3397         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3398         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3399         LocalFree(buf);
3400     }
3401     /* A dist point with an invalid name */
3402     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3403     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3404     U(entry).pwszURL = (LPWSTR)nihongoURL;
3405     U(point.DistPointName).FullName.cAltEntry = 1;
3406     U(point.DistPointName).FullName.rgAltEntry = &entry;
3407     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3408      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3409     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3410      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3411     /* The first invalid character is at index 7 */
3412     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3413      "Expected invalid char at index 7, got %d\n",
3414      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3415     /* A dist point with (just) a valid name */
3416     U(entry).pwszURL = (LPWSTR)url;
3417     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3418      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3419     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3420     if (buf)
3421     {
3422         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3423         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3424         LocalFree(buf);
3425     }
3426     /* A dist point with (just) reason flags */
3427     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3428     point.ReasonFlags.cbData = sizeof(crlReason);
3429     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3430     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3431      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3432     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3433     if (buf)
3434     {
3435         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3436         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3437         LocalFree(buf);
3438     }
3439     /* A dist point with just an issuer */
3440     point.ReasonFlags.cbData = 0;
3441     point.CRLIssuer.cAltEntry = 1;
3442     point.CRLIssuer.rgAltEntry = &entry;
3443     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3444      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3445     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3446     if (buf)
3447     {
3448         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3449         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3450         LocalFree(buf);
3451     }
3452     /* A dist point with both a name and an issuer */
3453     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3454     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3455      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3456     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3457     if (buf)
3458     {
3459         ok(size == sizeof(distPointWithUrlAndIssuer),
3460          "Wrong size %d\n", size);
3461         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3462         LocalFree(buf);
3463     }
3464 }
3465
3466 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3467 {
3468     BOOL ret;
3469     BYTE *buf = NULL;
3470     DWORD size = 0;
3471     PCRL_DIST_POINTS_INFO info;
3472     PCRL_DIST_POINT point;
3473     PCERT_ALT_NAME_ENTRY entry;
3474
3475     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3476      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3477      &buf, &size);
3478     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3479     if (ret)
3480     {
3481         info = (PCRL_DIST_POINTS_INFO)buf;
3482         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3483          "Wrong size %d\n", size);
3484         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3485          info->cDistPoint);
3486         point = info->rgDistPoint;
3487         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3488          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3489          point->DistPointName.dwDistPointNameChoice);
3490         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3491         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3492         LocalFree(buf);
3493     }
3494     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3495      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3496      &buf, &size);
3497     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3498     if (ret)
3499     {
3500         info = (PCRL_DIST_POINTS_INFO)buf;
3501         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3502          "Wrong size %d\n", size);
3503         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3504          info->cDistPoint);
3505         point = info->rgDistPoint;
3506         ok(point->DistPointName.dwDistPointNameChoice ==
3507          CRL_DIST_POINT_FULL_NAME,
3508          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3509          point->DistPointName.dwDistPointNameChoice);
3510         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3511          "Expected 1 name entry, got %d\n",
3512          U(point->DistPointName).FullName.cAltEntry);
3513         entry = U(point->DistPointName).FullName.rgAltEntry;
3514         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3515          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3516         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3517         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3518         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3519         LocalFree(buf);
3520     }
3521     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3522      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3523      NULL, &buf, &size);
3524     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3525     if (ret)
3526     {
3527         info = (PCRL_DIST_POINTS_INFO)buf;
3528         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3529          "Wrong size %d\n", size);
3530         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3531          info->cDistPoint);
3532         point = info->rgDistPoint;
3533         ok(point->DistPointName.dwDistPointNameChoice ==
3534          CRL_DIST_POINT_NO_NAME,
3535          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3536          point->DistPointName.dwDistPointNameChoice);
3537         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3538          "Expected reason length\n");
3539         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3540          "Unexpected reason\n");
3541         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3542         LocalFree(buf);
3543     }
3544     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3545      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3546      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3547     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3548     if (ret)
3549     {
3550         info = (PCRL_DIST_POINTS_INFO)buf;
3551         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3552          "Wrong size %d\n", size);
3553         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3554          info->cDistPoint);
3555         point = info->rgDistPoint;
3556         ok(point->DistPointName.dwDistPointNameChoice ==
3557          CRL_DIST_POINT_FULL_NAME,
3558          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3559          point->DistPointName.dwDistPointNameChoice);
3560         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3561          "Expected 1 name entry, got %d\n",
3562          U(point->DistPointName).FullName.cAltEntry);
3563         entry = U(point->DistPointName).FullName.rgAltEntry;
3564         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3565          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3566         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3567         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3568         ok(point->CRLIssuer.cAltEntry == 1,
3569          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3570         entry = point->CRLIssuer.rgAltEntry;
3571         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3572          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3573         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3574         LocalFree(buf);
3575     }
3576 }
3577
3578 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3579 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3580 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3581  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3582  0x67 };
3583
3584 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3585 {
3586     BOOL ret;
3587     BYTE *buf = NULL;
3588     DWORD size = 0;
3589     CRL_ISSUING_DIST_POINT point = { { 0 } };
3590     CERT_ALT_NAME_ENTRY entry;
3591
3592     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3593      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3594     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3595     {
3596         skip("no X509_ISSUING_DIST_POINT encode support\n");
3597         return;
3598     }
3599     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3600      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3601     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3602      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3603     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3604     if (buf)
3605     {
3606         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3607         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3608         LocalFree(buf);
3609     }
3610     /* nonsensical flags */
3611     point.fOnlyContainsUserCerts = TRUE;
3612     point.fOnlyContainsCACerts = TRUE;
3613     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3614      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3615     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3616     if (buf)
3617     {
3618         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3619         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3620         LocalFree(buf);
3621     }
3622     /* unimplemented name type */
3623     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3624     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3625     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3626      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3627     ok(!ret && GetLastError() == E_INVALIDARG,
3628      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3629     /* empty name */
3630     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3631     U(point.DistPointName).FullName.cAltEntry = 0;
3632     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3633      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3634     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3635     if (buf)
3636     {
3637         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3638         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3639         LocalFree(buf);
3640     }
3641     /* name with URL entry */
3642     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3643     U(entry).pwszURL = (LPWSTR)url;
3644     U(point.DistPointName).FullName.cAltEntry = 1;
3645     U(point.DistPointName).FullName.rgAltEntry = &entry;
3646     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3647      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3648     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3649     if (buf)
3650     {
3651         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3652         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3653         LocalFree(buf);
3654     }
3655 }
3656
3657 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3658  const CERT_ALT_NAME_ENTRY *got)
3659 {
3660     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3661      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3662      got->dwAltNameChoice);
3663     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3664     {
3665         switch (got->dwAltNameChoice)
3666         {
3667         case CERT_ALT_NAME_RFC822_NAME:
3668         case CERT_ALT_NAME_DNS_NAME:
3669         case CERT_ALT_NAME_EDI_PARTY_NAME:
3670         case CERT_ALT_NAME_URL:
3671         case CERT_ALT_NAME_REGISTERED_ID:
3672             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3673              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3674              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3675              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3676              "Unexpected name\n");
3677             break;
3678         case CERT_ALT_NAME_X400_ADDRESS:
3679         case CERT_ALT_NAME_DIRECTORY_NAME:
3680         case CERT_ALT_NAME_IP_ADDRESS:
3681             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3682                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3683             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3684                        U(*got).IPAddress.cbData), "Unexpected value\n");
3685             break;
3686         }
3687     }
3688 }
3689
3690 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3691  const CERT_ALT_NAME_INFO *got)
3692 {
3693     DWORD i;
3694
3695     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3696      expected->cAltEntry, got->cAltEntry);
3697     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3698         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3699 }
3700
3701 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3702  const CRL_DIST_POINT_NAME *got)
3703 {
3704     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3705      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3706     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3707         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3708 }
3709
3710 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3711  const CRL_ISSUING_DIST_POINT *got)
3712 {
3713     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3714     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3715      "Unexpected fOnlyContainsUserCerts\n");
3716     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3717      "Unexpected fOnlyContainsCACerts\n");
3718     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3719      "Unexpected reason flags\n");
3720     ok(got->fIndirectCRL == expected->fIndirectCRL,
3721      "Unexpected fIndirectCRL\n");
3722 }
3723
3724 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3725 {
3726     BOOL ret;
3727     BYTE *buf = NULL;
3728     DWORD size = 0;
3729     CRL_ISSUING_DIST_POINT point = { { 0 } };
3730
3731     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3732      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3733      &buf, &size);
3734     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3735     {
3736         skip("no X509_ISSUING_DIST_POINT decode support\n");
3737         return;
3738     }
3739     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3740     if (ret)
3741     {
3742         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3743         LocalFree(buf);
3744     }
3745     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3746      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3747      &buf, &size);
3748     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3749     if (ret)
3750     {
3751         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3752         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3753         LocalFree(buf);
3754     }
3755     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3756      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3757      &buf, &size);
3758     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3759     if (ret)
3760     {
3761         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3762         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3763         U(point.DistPointName).FullName.cAltEntry = 0;
3764         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3765         LocalFree(buf);
3766     }
3767     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3768      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3769     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3770     if (ret)
3771     {
3772         CERT_ALT_NAME_ENTRY entry;
3773
3774         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3775         U(entry).pwszURL = (LPWSTR)url;
3776         U(point.DistPointName).FullName.cAltEntry = 1;
3777         U(point.DistPointName).FullName.rgAltEntry = &entry;
3778         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3779         LocalFree(buf);
3780     }
3781 }
3782
3783 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3784  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3785  0x30, 0x5a };
3786 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3787  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3788  0x30, 0x30, 0x30, 0x30, 0x5a };
3789 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3790  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3791  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3792  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3793  0x5a };
3794 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3795  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3796  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3797  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3798  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3799  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3800 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3801  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3802  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3803  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3804  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3805  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3806 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3807  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3808  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3809  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3810  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3811  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3812  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3813 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3814  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3815  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3816  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3817  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3818  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3819  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3820 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3821  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3822  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3823  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3824  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3825  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3826  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3827 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3828  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3829  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3830  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3831  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3832  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3833  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3834
3835 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3836 {
3837     BOOL ret;
3838     BYTE *buf = NULL;
3839     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3840     DWORD size = 0;
3841     CRL_INFO info = { 0 };
3842     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3843     CERT_EXTENSION ext;
3844
3845     /* Test with a V1 CRL */
3846     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3847      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3848     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3849      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3850     if (buf)
3851     {
3852         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3853         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3854         LocalFree(buf);
3855     }
3856     /* Test v2 CRL */
3857     info.dwVersion = CRL_V2;
3858     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3859      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3860     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3861      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3862     if (buf)
3863     {
3864         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3865          v2CRL[1] + 2, size);
3866         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3867         LocalFree(buf);
3868     }
3869     /* v1 CRL with a name */
3870     info.dwVersion = CRL_V1;
3871     info.Issuer.cbData = sizeof(encodedCommonName);
3872     info.Issuer.pbData = (BYTE *)encodedCommonName;
3873     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3874      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3875     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3876     if (buf)
3877     {
3878         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3879         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3880         LocalFree(buf);
3881     }
3882     if (0)
3883     {
3884         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3885         info.cCRLEntry = 1;
3886         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3887          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3888         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3889          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3890     }
3891     /* now set an empty entry */
3892     info.cCRLEntry = 1;
3893     info.rgCRLEntry = &entry;
3894     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3895      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3896     if (buf)
3897     {
3898         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3899          "Wrong size %d\n", size);
3900         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3901          "Got unexpected value\n");
3902         LocalFree(buf);
3903     }
3904     /* an entry with a serial number */
3905     entry.SerialNumber.cbData = sizeof(serialNum);
3906     entry.SerialNumber.pbData = (BYTE *)serialNum;
3907     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3908      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3909     if (buf)
3910     {
3911         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3912          "Wrong size %d\n", size);
3913         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3914          "Got unexpected value\n");
3915         LocalFree(buf);
3916     }
3917     /* an entry with an extension */
3918     entry.cExtension = 1;
3919     entry.rgExtension = &criticalExt;
3920     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3921      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3922     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3923     if (buf)
3924     {
3925         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3926         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3927         LocalFree(buf);
3928     }
3929     /* a CRL with an extension */
3930     entry.cExtension = 0;
3931     info.cExtension = 1;
3932     info.rgExtension = &criticalExt;
3933     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3934      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3935     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3936     if (buf)
3937     {
3938         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3939         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3940         LocalFree(buf);
3941     }
3942     /* a v2 CRL with an extension, this time non-critical */
3943     info.dwVersion = CRL_V2;
3944     info.rgExtension = &nonCriticalExt;
3945     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3946      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3947     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3948     if (buf)
3949     {
3950         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3951         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3952         LocalFree(buf);
3953     }
3954     /* a v2 CRL with an issuing dist point extension */
3955     ext.pszObjId = oid_issuing_dist_point;
3956     ext.fCritical = TRUE;
3957     ext.Value.cbData = sizeof(urlIDP);
3958     ext.Value.pbData = (LPBYTE)urlIDP;
3959     entry.rgExtension = &ext;
3960     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3961      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3962     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3963     if (buf)
3964     {
3965         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3966         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3967         LocalFree(buf);
3968     }
3969 }
3970
3971 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3972  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3973  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3974  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3975  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3976  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3977  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3978  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3979  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3980  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3981  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3982  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3983  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3984  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3985  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3986  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3987  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3988  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3989  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3990  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3991  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3992  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3993  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3994  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3995  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3996  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3997  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3998  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3999  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4000  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4001  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4002  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4003  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4004  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4005  0xcd };
4006 static const BYTE verisignCRLWithLotsOfEntries[] = {
4007 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4008 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4009 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4010 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4011 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4012 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4013 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4014 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4015 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4016 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4017 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4018 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4019 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4020 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4021 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4022 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4023 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4024 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4025 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4026 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4027 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4028 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4029 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4030 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4031 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4032 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4033 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4034 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4035 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4036 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4037 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4038 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4039 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4040 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4041 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4042 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4043 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4044 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4045 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4046 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4047 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4048 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4049 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4050 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4051 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4052 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4053 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4054 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4055 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4056 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4057 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4058 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4059 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4060 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4061 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4062 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4063 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4064 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4065 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4066 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4067 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4068 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4069 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4070 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4071 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4072 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4073 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4074 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4075 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4076 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4077 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4078 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4079 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4080 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4081 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4082 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4083 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4084 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4085 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4086 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4087 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4088 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4089 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4090 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4091 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4092 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4093 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4094 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4095 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4096 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4097 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4098 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4099 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4100 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4101 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4102 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4103 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4104 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4105 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4106 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4107 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4108 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4109 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4110 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4111 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4112 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4113 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4114 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4115 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4116 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4117 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4118 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4119 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4120 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4121 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4122 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4123 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4124 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4125 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4126 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4127 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4128 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4129 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4130 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4131 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4132 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4133 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4134 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4135 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4136 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4137 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4138 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4139 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4140 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4141 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4142 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4143 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4144 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4145 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4146 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4147 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4148 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4149 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4150 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4151 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4152 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4153 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4154 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4155 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4156 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4157 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4158 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4159 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4160 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4161 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4162 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4163 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4164 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4165 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4166 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4167 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4168 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4169 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4170 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4171 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4172 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4173 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4174 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4175 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4176 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4177 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4178 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4179 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4180 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4181 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4182 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4183 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4184 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4185 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4186 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4187 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4188 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4189 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4190 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4191 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4192 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4193 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4194 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4195 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4196 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4197 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4198 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4199 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4200 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4201 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4202 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4203 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4204 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4205 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4206 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4207 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4208 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4209 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4210 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4211 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4212 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4213 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4214 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4215 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4216 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4217 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4218 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4219 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4220 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4221 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4222 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4223 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4224 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4225 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4226 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4227 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4228 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4229 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4230 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4231 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4232 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4233 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4234 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4235 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4236 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4237 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4238 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4239 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4240 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4241 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4242 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4243 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4244 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4245 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4246 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4247 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4248 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4249 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4250 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4251 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4252 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4253 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4254 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4255 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4256 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4257 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4258 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4259 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4260 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4261 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4262 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4263 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4264 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4265 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4266 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4267 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4268 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4269 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4270 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4271 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4272 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4273 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4274 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4275 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4276 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4277 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4278 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4279 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4280 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4281 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4282 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4283 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4284 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4285 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4286 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4287 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4288 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4289 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4290 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4291 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4292 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4293 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4294 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4295 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4296 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4297 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4298 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4299 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4300 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4301 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4302 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4303 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4304 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4305 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4306 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4307 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4308 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4309 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4310 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4311 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4312 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4313 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4314 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4315 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4316 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4317 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4318 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4319 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4320 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4321 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4322 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4323 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4324 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4325 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4326 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4327 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4328 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4329 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4330 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4331 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4332 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4333 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4334 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4335 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4336 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4337 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4338 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4339 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4340 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4341 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4342 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4343 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4344 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4345 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4346 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4347 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4348 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4349 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4350 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4351 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4352 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4353 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4354 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4355 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4356 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4357 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4358 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4359 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4360 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4361 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4362 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4363 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4364 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4365 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4366 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4367 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4368 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4369 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4370 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4371 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4372 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4373 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4374 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4375 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4376 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4377 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4378 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4379 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4380 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4381 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4382 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4383 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4384 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4385 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4386 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4387 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4388 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4389 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4390 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4391 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4392 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4393 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4394 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4395 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4396 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4397 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4398 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4399 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4400 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4401 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4402 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4403 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4404 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4405 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4406 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4407 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4408 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4409 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4410 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4411 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4412 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4413 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4414 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4415 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4416 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4417 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4418 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4419 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4420 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4421 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4422 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4423 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4424 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4425 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4426 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4427 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4428 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4429 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4430 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4431 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4432 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4433 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4434 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4435 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4436 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4437 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4438 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4439 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4440 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4441 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4442 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4443 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4444 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4445 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4446 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4447 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4448 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4449 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4450 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4451 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4452 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4453 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4454 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4455 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4456 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4457 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4458 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4459 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4460 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4461 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4462 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4463 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4464 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4465 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4466 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4467 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4468 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4469 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4470 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4471 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4472 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4473 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4474 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4475 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4476 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4477 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4478 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4479 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4480 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4481 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4482 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4483 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4484 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4485 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4486 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4487 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4488 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4489 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4490 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4491 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4492 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4493 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4494 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4495 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4496 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4497 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4498 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4499 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4500 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4501 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4502 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4503 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4504 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4505 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4506 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4507 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4508 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4509 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4510 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4511 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4512 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4513 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4514 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4515
4516 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4517 {
4518     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4519     BOOL ret;
4520     BYTE *buf = NULL;
4521     DWORD size = 0, i;
4522
4523     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4524     {
4525         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4526          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4527          &buf, &size);
4528         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4529          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4530          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4531          GetLastError());
4532     }
4533     /* at a minimum, a CRL must contain an issuer: */
4534     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4535      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4536      &buf, &size);
4537     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4538     if (buf)
4539     {
4540         CRL_INFO *info = (CRL_INFO *)buf;
4541
4542         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4543         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4544          info->cCRLEntry);
4545         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4546          "Wrong issuer size %d\n", info->Issuer.cbData);
4547         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4548          "Unexpected issuer\n");
4549         LocalFree(buf);
4550     }
4551     /* check decoding with an empty CRL entry */
4552     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4553      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4554      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4555     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4556      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4557      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4558      GetLastError());
4559     /* with a real CRL entry */
4560     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4561      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4562      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4563     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4564     if (buf)
4565     {
4566         CRL_INFO *info = (CRL_INFO *)buf;
4567         CRL_ENTRY *entry;
4568
4569         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4570         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4571          info->cCRLEntry);
4572         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4573         entry = info->rgCRLEntry;
4574         ok(entry->SerialNumber.cbData == 1,
4575          "Expected serial number size 1, got %d\n",
4576          entry->SerialNumber.cbData);
4577         ok(*entry->SerialNumber.pbData == *serialNum,
4578          "Expected serial number %d, got %d\n", *serialNum,
4579          *entry->SerialNumber.pbData);
4580         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4581          "Wrong issuer size %d\n", info->Issuer.cbData);
4582         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4583          "Unexpected issuer\n");
4584         LocalFree(buf);
4585     }
4586     /* a real CRL from verisign that has extensions */
4587     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4588      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4589      NULL, &buf, &size);
4590     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4591     if (buf)
4592     {
4593         CRL_INFO *info = (CRL_INFO *)buf;
4594         CRL_ENTRY *entry;
4595
4596         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4597         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4598          info->cCRLEntry);
4599         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4600         entry = info->rgCRLEntry;
4601         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4602          info->cExtension);
4603         LocalFree(buf);
4604     }
4605     /* another real CRL from verisign that has lots of entries */
4606     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4607      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4608      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4609     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4610     if (buf)
4611     {
4612         CRL_INFO *info = (CRL_INFO *)buf;
4613
4614         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4615         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4616          info->cCRLEntry);
4617         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4618          info->cExtension);
4619         LocalFree(buf);
4620     }
4621     /* and finally, with an extension */
4622     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4623      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4624      NULL, &buf, &size);
4625     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4626     if (buf)
4627     {
4628         CRL_INFO *info = (CRL_INFO *)buf;
4629         CRL_ENTRY *entry;
4630
4631         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4632         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4633          info->cCRLEntry);
4634         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4635         entry = info->rgCRLEntry;
4636         ok(entry->SerialNumber.cbData == 1,
4637          "Expected serial number size 1, got %d\n",
4638          entry->SerialNumber.cbData);
4639         ok(*entry->SerialNumber.pbData == *serialNum,
4640          "Expected serial number %d, got %d\n", *serialNum,
4641          *entry->SerialNumber.pbData);
4642         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4643          "Wrong issuer size %d\n", info->Issuer.cbData);
4644         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4645          "Unexpected issuer\n");
4646         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4647          info->cExtension);
4648         LocalFree(buf);
4649     }
4650     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4651      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4652      NULL, &buf, &size);
4653     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4654     if (buf)
4655     {
4656         CRL_INFO *info = (CRL_INFO *)buf;
4657
4658         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4659          info->cExtension);
4660         LocalFree(buf);
4661     }
4662     /* And again, with an issuing dist point */
4663     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4664      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4665      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4666     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4667     if (buf)
4668     {
4669         CRL_INFO *info = (CRL_INFO *)buf;
4670
4671         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4672          info->cExtension);
4673         LocalFree(buf);
4674     }
4675 }
4676
4677 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4678  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4679 static const BYTE encodedUsage[] = {
4680  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4681  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4682  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4683
4684 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4685 {
4686     BOOL ret;
4687     BYTE *buf = NULL;
4688     DWORD size = 0;
4689     CERT_ENHKEY_USAGE usage;
4690
4691     /* Test with empty usage */
4692     usage.cUsageIdentifier = 0;
4693     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4694      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4695     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4696     if (buf)
4697     {
4698         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4699         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4700         LocalFree(buf);
4701     }
4702     /* Test with a few usages */
4703     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4704     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4705     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4706      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4707     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4708     if (buf)
4709     {
4710         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4711         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4712         LocalFree(buf);
4713     }
4714 }
4715
4716 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4717 {
4718     BOOL ret;
4719     LPBYTE buf = NULL;
4720     DWORD size = 0;
4721
4722     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4723      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4724      &buf, &size);
4725     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4726     if (buf)
4727     {
4728         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4729
4730         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4731          "Wrong size %d\n", size);
4732         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4733          usage->cUsageIdentifier);
4734         LocalFree(buf);
4735     }
4736     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4737      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4738      &buf, &size);
4739     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4740     if (buf)
4741     {
4742         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4743         DWORD i;
4744
4745         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4746          "Wrong size %d\n", size);
4747         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4748          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4749         for (i = 0; i < usage->cUsageIdentifier; i++)
4750             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4751              "Expected OID %s, got %s\n", keyUsages[i],
4752              usage->rgpszUsageIdentifier[i]);
4753         LocalFree(buf);
4754     }
4755 }
4756
4757 static BYTE keyId[] = { 1,2,3,4 };
4758 static const BYTE authorityKeyIdWithId[] = {
4759  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4760 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4761  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4762  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4763 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4764
4765 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4766 {
4767     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4768     BOOL ret;
4769     BYTE *buf = NULL;
4770     DWORD size = 0;
4771
4772     /* Test with empty id */
4773     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4774      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4775     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4776     if (buf)
4777     {
4778         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4779         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4780         LocalFree(buf);
4781     }
4782     /* With just a key id */
4783     info.KeyId.cbData = sizeof(keyId);
4784     info.KeyId.pbData = keyId;
4785     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4786      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4787     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4788     if (buf)
4789     {
4790         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4791         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4792         LocalFree(buf);
4793     }
4794     /* With just an issuer */
4795     info.KeyId.cbData = 0;
4796     info.CertIssuer.cbData = sizeof(encodedCommonName);
4797     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4798     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4799      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4800     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4801     if (buf)
4802     {
4803         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4804          size);
4805         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4806         LocalFree(buf);
4807     }
4808     /* With just a serial number */
4809     info.CertIssuer.cbData = 0;
4810     info.CertSerialNumber.cbData = sizeof(serialNum);
4811     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4812     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4813      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4814     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4815     if (buf)
4816     {
4817         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4818          size);
4819         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4820         LocalFree(buf);
4821     }
4822 }
4823
4824 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4825 {
4826     BOOL ret;
4827     LPBYTE buf = NULL;
4828     DWORD size = 0;
4829
4830     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4831      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4832      &buf, &size);
4833     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4834     if (buf)
4835     {
4836         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4837
4838         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4839          size);
4840         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4841         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4842         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4843         LocalFree(buf);
4844     }
4845     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4846      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4847      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4848     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4849     if (buf)
4850     {
4851         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4852
4853         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4854          size);
4855         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4856         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4857          "Unexpected key id\n");
4858         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4859         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4860         LocalFree(buf);
4861     }
4862     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4863      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4864      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4865     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4866     if (buf)
4867     {
4868         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4869
4870         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4871          size);
4872         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4873         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4874          "Unexpected issuer len\n");
4875         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4876          sizeof(encodedCommonName)), "Unexpected issuer\n");
4877         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4878         LocalFree(buf);
4879     }
4880     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4881      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4882      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4883     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4884     if (buf)
4885     {
4886         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4887
4888         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4889          size);
4890         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4891         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4892         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4893          "Unexpected serial number len\n");
4894         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4895          "Unexpected serial number\n");
4896         LocalFree(buf);
4897     }
4898 }
4899
4900 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4901  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4902  0x6f,0x72,0x67 };
4903
4904 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4905 {
4906     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4907     CERT_ALT_NAME_ENTRY entry = { 0 };
4908     BOOL ret;
4909     BYTE *buf = NULL;
4910     DWORD size = 0;
4911
4912     /* Test with empty id */
4913     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4914      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4915     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4916     if (buf)
4917     {
4918         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4919         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4920         LocalFree(buf);
4921     }
4922     /* With just a key id */
4923     info.KeyId.cbData = sizeof(keyId);
4924     info.KeyId.pbData = keyId;
4925     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4926      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4927     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4928     if (buf)
4929     {
4930         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4931          size);
4932         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4933         LocalFree(buf);
4934     }
4935     /* With a bogus issuer name */
4936     info.KeyId.cbData = 0;
4937     info.AuthorityCertIssuer.cAltEntry = 1;
4938     info.AuthorityCertIssuer.rgAltEntry = &entry;
4939     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4940      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4941     ok(!ret && GetLastError() == E_INVALIDARG,
4942      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4943     /* With an issuer name */
4944     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4945     U(entry).pwszURL = (LPWSTR)url;
4946     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4947      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4948     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4949     if (buf)
4950     {
4951         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4952          size);
4953         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4954          "Unexpected value\n");
4955         LocalFree(buf);
4956     }
4957     /* With just a serial number */
4958     info.AuthorityCertIssuer.cAltEntry = 0;
4959     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4960     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4961     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4962      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4963     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4964     if (buf)
4965     {
4966         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4967          size);
4968         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4969         LocalFree(buf);
4970     }
4971 }
4972
4973 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4974 {
4975     BOOL ret;
4976     LPBYTE buf = NULL;
4977     DWORD size = 0;
4978
4979     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4980      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4981      &buf, &size);
4982     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4983     if (buf)
4984     {
4985         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4986
4987         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4988          size);
4989         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4990         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4991          "Expected no issuer name entries\n");
4992         ok(info->AuthorityCertSerialNumber.cbData == 0,
4993          "Expected no serial number\n");
4994         LocalFree(buf);
4995     }
4996     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4997      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4998      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4999     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5000     if (buf)
5001     {
5002         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5003
5004         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5005          size);
5006         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5007         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5008          "Unexpected key id\n");
5009         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5010          "Expected no issuer name entries\n");
5011         ok(info->AuthorityCertSerialNumber.cbData == 0,
5012          "Expected no serial number\n");
5013         LocalFree(buf);
5014     }
5015     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5016      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5017      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5018     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5019     if (buf)
5020     {
5021         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5022
5023         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5024          size);
5025         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5026         ok(info->AuthorityCertIssuer.cAltEntry == 1,
5027          "Expected 1 issuer entry, got %d\n",
5028          info->AuthorityCertIssuer.cAltEntry);
5029         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5030          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5031          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5032         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5033          url), "Unexpected URL\n");
5034         ok(info->AuthorityCertSerialNumber.cbData == 0,
5035          "Expected no serial number\n");
5036         LocalFree(buf);
5037     }
5038     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5039      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5040      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5041     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5042     if (buf)
5043     {
5044         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5045
5046         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5047          size);
5048         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5049         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5050          "Expected no issuer name entries\n");
5051         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5052          "Unexpected serial number len\n");
5053         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5054          sizeof(serialNum)), "Unexpected serial number\n");
5055         LocalFree(buf);
5056     }
5057 }
5058
5059 static const BYTE authorityInfoAccessWithUrl[] = {
5060 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5061 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5062 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5063 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5064 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5065 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5066
5067 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5068 {
5069     static char oid1[] = "1.2.3";
5070     static char oid2[] = "1.5.6";
5071     BOOL ret;
5072     BYTE *buf = NULL;
5073     DWORD size = 0;
5074     CERT_ACCESS_DESCRIPTION accessDescription[2];
5075     CERT_AUTHORITY_INFO_ACCESS aia;
5076
5077     memset(accessDescription, 0, sizeof(accessDescription));
5078     aia.cAccDescr = 0;
5079     aia.rgAccDescr = NULL;
5080     /* Having no access descriptions is allowed */
5081     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5082      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5083     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5084     if (buf)
5085     {
5086         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5087         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5088         LocalFree(buf);
5089         buf = NULL;
5090     }
5091     /* It can't have an empty access method */
5092     aia.cAccDescr = 1;
5093     aia.rgAccDescr = accessDescription;
5094     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5095      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5096     ok(!ret && (GetLastError() == E_INVALIDARG ||
5097      GetLastError() == OSS_LIMITED /* Win9x */),
5098      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5099     /* It can't have an empty location */
5100     accessDescription[0].pszAccessMethod = oid1;
5101     SetLastError(0xdeadbeef);
5102     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5103      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5104     ok(!ret && GetLastError() == E_INVALIDARG,
5105      "expected E_INVALIDARG, got %08x\n", GetLastError());
5106     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5107     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5108     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5109      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5110     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5111     if (buf)
5112     {
5113         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5114          size);
5115         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5116          "unexpected value\n");
5117         LocalFree(buf);
5118         buf = NULL;
5119     }
5120     accessDescription[1].pszAccessMethod = oid2;
5121     accessDescription[1].AccessLocation.dwAltNameChoice =
5122      CERT_ALT_NAME_IP_ADDRESS;
5123     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5124      sizeof(encodedIPAddr);
5125     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5126      (LPBYTE)encodedIPAddr;
5127     aia.cAccDescr = 2;
5128     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5129      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5130     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5131     if (buf)
5132     {
5133         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5134          "unexpected size %d\n", size);
5135         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5136          "unexpected value\n");
5137         LocalFree(buf);
5138         buf = NULL;
5139     }
5140 }
5141
5142 static void compareAuthorityInfoAccess(LPCSTR header,
5143  const CERT_AUTHORITY_INFO_ACCESS *expected,
5144  const CERT_AUTHORITY_INFO_ACCESS *got)
5145 {
5146     DWORD i;
5147
5148     ok(expected->cAccDescr == got->cAccDescr,
5149      "%s: expected %d access descriptions, got %d\n", header,
5150      expected->cAccDescr, got->cAccDescr);
5151     for (i = 0; i < expected->cAccDescr; i++)
5152     {
5153         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5154          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5155          header, i, expected->rgAccDescr[i].pszAccessMethod,
5156          got->rgAccDescr[i].pszAccessMethod);
5157         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5158          &got->rgAccDescr[i].AccessLocation);
5159     }
5160 }
5161
5162 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5163 {
5164     static char oid1[] = "1.2.3";
5165     static char oid2[] = "1.5.6";
5166     BOOL ret;
5167     LPBYTE buf = NULL;
5168     DWORD size = 0;
5169
5170     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5171      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5172      &buf, &size);
5173     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5174     if (buf)
5175     {
5176         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5177
5178         compareAuthorityInfoAccess("empty AIA", &aia,
5179          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5180         LocalFree(buf);
5181         buf = NULL;
5182     }
5183     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5184      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5185      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5186     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5187     if (buf)
5188     {
5189         CERT_ACCESS_DESCRIPTION accessDescription;
5190         CERT_AUTHORITY_INFO_ACCESS aia;
5191
5192         accessDescription.pszAccessMethod = oid1;
5193         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5194         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5195         aia.cAccDescr = 1;
5196         aia.rgAccDescr = &accessDescription;
5197         compareAuthorityInfoAccess("AIA with URL", &aia,
5198          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5199         LocalFree(buf);
5200         buf = NULL;
5201     }
5202     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5203      authorityInfoAccessWithUrlAndIPAddr,
5204      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5205      NULL, &buf, &size);
5206     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5207     if (buf)
5208     {
5209         CERT_ACCESS_DESCRIPTION accessDescription[2];
5210         CERT_AUTHORITY_INFO_ACCESS aia;
5211
5212         accessDescription[0].pszAccessMethod = oid1;
5213         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5214         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5215         accessDescription[1].pszAccessMethod = oid2;
5216         accessDescription[1].AccessLocation.dwAltNameChoice =
5217          CERT_ALT_NAME_IP_ADDRESS;
5218         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5219          sizeof(encodedIPAddr);
5220         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5221          (LPBYTE)encodedIPAddr;
5222         aia.cAccDescr = 2;
5223         aia.rgAccDescr = accessDescription;
5224         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5225          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5226         LocalFree(buf);
5227         buf = NULL;
5228     }
5229 }
5230
5231 static const BYTE emptyCTL[] = {
5232 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5233 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5234 static const BYTE emptyCTLWithVersion1[] = {
5235 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5236 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5237 static const BYTE ctlWithUsageIdentifier[] = {
5238 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5239 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5240 static const BYTE ctlWithListIdentifier[] = {
5241 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5242 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5243 static const BYTE ctlWithSequenceNumber[] = {
5244 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5245 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5246 static const BYTE ctlWithThisUpdate[] = {
5247 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5248 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5249 static const BYTE ctlWithThisAndNextUpdate[] = {
5250 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5251 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5252 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5253 static const BYTE ctlWithAlgId[] = {
5254 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5255 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5256 static const BYTE ctlWithBogusEntry[] = {
5257 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5258 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5259 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5260 static const BYTE ctlWithOneEntry[] = {
5261 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5262 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5263 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5264 static const BYTE ctlWithTwoEntries[] = {
5265 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5266 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5267 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5268 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5269 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5270
5271 static void test_encodeCTL(DWORD dwEncoding)
5272 {
5273     static char oid1[] = "1.2.3";
5274     static char oid2[] = "1.5.6";
5275     char *pOid1 = oid1;
5276     BOOL ret;
5277     BYTE *buf = NULL;
5278     DWORD size = 0;
5279     CTL_INFO info;
5280     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5281     CTL_ENTRY ctlEntry[2];
5282     CRYPT_ATTRIBUTE attr1, attr2;
5283     CRYPT_ATTR_BLOB value1, value2;
5284
5285     memset(&info, 0, sizeof(info));
5286     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5287      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5288     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5289     if (buf)
5290     {
5291         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5292         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5293         LocalFree(buf);
5294         buf = NULL;
5295     }
5296     info.dwVersion = 1;
5297     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5298      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5299     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5300     if (buf)
5301     {
5302         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5303         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5304         LocalFree(buf);
5305         buf = NULL;
5306     }
5307     info.dwVersion = 0;
5308     info.SubjectUsage.cUsageIdentifier = 1;
5309     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5310     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5311      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5312     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5313     if (buf)
5314     {
5315         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5316          size);
5317         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5318         LocalFree(buf);
5319         buf = NULL;
5320     }
5321     info.SubjectUsage.cUsageIdentifier = 0;
5322     info.ListIdentifier.cbData = sizeof(serialNum);
5323     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5324     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5325      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5326     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5327     if (buf)
5328     {
5329         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5330         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5331         LocalFree(buf);
5332         buf = NULL;
5333     }
5334     info.ListIdentifier.cbData = 0;
5335     info.SequenceNumber.cbData = sizeof(serialNum);
5336     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5337     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5338      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5339     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5340     if (buf)
5341     {
5342         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5343          size);
5344         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5345         LocalFree(buf);
5346         buf = NULL;
5347     }
5348     info.SequenceNumber.cbData = 0;
5349     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5350     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5351      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5352     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5353     if (buf)
5354     {
5355         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5356         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5357         LocalFree(buf);
5358         buf = NULL;
5359     }
5360     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
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 (buf)
5365     {
5366         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5367          size);
5368         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5369         LocalFree(buf);
5370         buf = NULL;
5371     }
5372     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5373     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5374     info.SubjectAlgorithm.pszObjId = oid2;
5375     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5376      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5377     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5378     if (buf)
5379     {
5380         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5381         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5382         LocalFree(buf);
5383         buf = NULL;
5384     }
5385     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5386      * (see tests below) but it'll encode fine.
5387      */
5388     info.SubjectAlgorithm.pszObjId = NULL;
5389     value1.cbData = sizeof(serialNum);
5390     value1.pbData = (LPBYTE)serialNum;
5391     attr1.pszObjId = oid1;
5392     attr1.cValue = 1;
5393     attr1.rgValue = &value1;
5394     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5395     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5396     ctlEntry[0].cAttribute = 1;
5397     ctlEntry[0].rgAttribute = &attr1;
5398     info.cCTLEntry = 1;
5399     info.rgCTLEntry = ctlEntry;
5400     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5401      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5402     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5403     if (buf)
5404     {
5405         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5406         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5407         LocalFree(buf);
5408         buf = NULL;
5409     }
5410     value1.cbData = sizeof(emptySequence);
5411     value1.pbData = (LPBYTE)emptySequence;
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 (buf)
5416     {
5417         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5418         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5419         LocalFree(buf);
5420         buf = NULL;
5421     }
5422     value2.cbData = sizeof(encodedIPAddr);
5423     value2.pbData = (LPBYTE)encodedIPAddr;
5424     attr2.pszObjId = oid2;
5425     attr2.cValue = 1;
5426     attr2.rgValue = &value2;
5427     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5428     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5429     ctlEntry[1].cAttribute = 1;
5430     ctlEntry[1].rgAttribute = &attr2;
5431     info.cCTLEntry = 2;
5432     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5433      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5434     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5435     if (buf)
5436     {
5437         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5438         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5439         LocalFree(buf);
5440         buf = NULL;
5441     }
5442 }
5443
5444 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5445  const CTL_INFO *got)
5446 {
5447     DWORD i, j, k;
5448
5449     ok(expected->dwVersion == got->dwVersion,
5450      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5451      got->dwVersion);
5452     ok(expected->SubjectUsage.cUsageIdentifier ==
5453      got->SubjectUsage.cUsageIdentifier,
5454      "%s: expected %d usage identifiers, got %d\n", header,
5455      expected->SubjectUsage.cUsageIdentifier,
5456      got->SubjectUsage.cUsageIdentifier);
5457     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5458         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5459          got->SubjectUsage.rgpszUsageIdentifier[i]),
5460          "%s[%d]: expected %s, got %s\n", header, i,
5461          expected->SubjectUsage.rgpszUsageIdentifier[i],
5462          got->SubjectUsage.rgpszUsageIdentifier[i]);
5463     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5464      "%s: expected list identifier of %d bytes, got %d\n", header,
5465      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5466     if (expected->ListIdentifier.cbData)
5467         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5468          expected->ListIdentifier.cbData),
5469          "%s: unexpected list identifier value\n", header);
5470     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5471      "%s: expected sequence number of %d bytes, got %d\n", header,
5472      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5473     if (expected->SequenceNumber.cbData)
5474         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5475          expected->SequenceNumber.cbData),
5476          "%s: unexpected sequence number value\n", header);
5477     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5478      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5479      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5480      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5481     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5482      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5483      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5484      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5485     if (expected->SubjectAlgorithm.pszObjId &&
5486      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5487         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5488          expected->SubjectAlgorithm.pszObjId);
5489     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5490         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5491          got->SubjectAlgorithm.pszObjId),
5492          "%s: expected subject algorithm %s, got %s\n", header,
5493          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5494     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5495      got->SubjectAlgorithm.Parameters.cbData,
5496      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5497      expected->SubjectAlgorithm.Parameters.cbData,
5498      got->SubjectAlgorithm.Parameters.cbData);
5499     if (expected->SubjectAlgorithm.Parameters.cbData)
5500         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5501          got->SubjectAlgorithm.Parameters.pbData,
5502          expected->SubjectAlgorithm.Parameters.cbData),
5503          "%s: unexpected subject algorithm parameter value\n", header);
5504     ok(expected->cCTLEntry == got->cCTLEntry,
5505      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5506      got->cCTLEntry);
5507     for (i = 0; i < expected->cCTLEntry; i++)
5508     {
5509         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5510          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5511          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5512          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5513          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5514         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5515             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5516              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5517              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5518              "%s[%d]: unexpected subject identifier value\n",
5519              header, i);
5520         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5521         {
5522             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5523              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5524              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5525              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5526              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5527             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5528             {
5529                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5530                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5531                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5532                  header, i, j, k,
5533                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5534                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5535                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5536                     ok(!memcmp(
5537                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5538                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5539                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5540                      "%s[%d][%d][%d]: unexpected value\n",
5541                      header, i, j, k);
5542             }
5543         }
5544     }
5545     ok(expected->cExtension == got->cExtension,
5546      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5547      got->cExtension);
5548     for (i = 0; i < expected->cExtension; i++)
5549     {
5550         ok(!strcmp(expected->rgExtension[i].pszObjId,
5551          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5552          header, i, expected->rgExtension[i].pszObjId,
5553          got->rgExtension[i].pszObjId);
5554         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5555          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5556          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5557         ok(expected->rgExtension[i].Value.cbData ==
5558          got->rgExtension[i].Value.cbData,
5559          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5560          header, i, expected->rgExtension[i].Value.cbData,
5561          got->rgExtension[i].Value.cbData);
5562         if (expected->rgExtension[i].Value.cbData)
5563             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5564              got->rgExtension[i].Value.pbData,
5565              expected->rgExtension[i].Value.cbData),
5566              "%s[%d]: unexpected extension value\n", header, i);
5567     }
5568 }
5569
5570 static const BYTE signedCTL[] = {
5571 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5572 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5573 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5574 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5575 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5576 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5577 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5578 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5579 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5580 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5581 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5582 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5583 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5584 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5585 static const BYTE signedCTLWithCTLInnerContent[] = {
5586 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5587 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5588 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5589 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5590 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5591 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5592 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5593 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5594 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5595 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5596 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5597 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5598 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5599 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5600 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5601 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5602 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5603 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5604 0x57,0x6c,0x0b,0x47,0xb8 };
5605
5606 static void test_decodeCTL(DWORD dwEncoding)
5607 {
5608     static char oid1[] = "1.2.3";
5609     static char oid2[] = "1.5.6";
5610     static BYTE nullData[] = { 5,0 };
5611     char *pOid1 = oid1;
5612     BOOL ret;
5613     BYTE *buf = NULL;
5614     DWORD size = 0;
5615     CTL_INFO info;
5616     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5617     CTL_ENTRY ctlEntry[2];
5618     CRYPT_ATTRIBUTE attr1, attr2;
5619     CRYPT_ATTR_BLOB value1, value2;
5620
5621     memset(&info, 0, sizeof(info));
5622     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5623      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5624     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5625     if (buf)
5626     {
5627         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5628         LocalFree(buf);
5629         buf = NULL;
5630     }
5631     info.dwVersion = 1;
5632     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5633      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5634      &size);
5635     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5636     if (buf)
5637     {
5638         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5639         LocalFree(buf);
5640         buf = NULL;
5641     }
5642     info.dwVersion = 0;
5643     info.SubjectUsage.cUsageIdentifier = 1;
5644     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5645     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5646      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5647      &buf, &size);
5648     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5649     if (buf)
5650     {
5651         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5652         LocalFree(buf);
5653         buf = NULL;
5654     }
5655     info.SubjectUsage.cUsageIdentifier = 0;
5656     info.ListIdentifier.cbData = sizeof(serialNum);
5657     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5658     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5659      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5660     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5661     if (buf)
5662     {
5663         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5664         LocalFree(buf);
5665         buf = NULL;
5666     }
5667     info.ListIdentifier.cbData = 0;
5668     info.SequenceNumber.cbData = sizeof(serialNum);
5669     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5670     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5671      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5672     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5673     if (buf)
5674     {
5675         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5676         LocalFree(buf);
5677         buf = NULL;
5678     }
5679     info.SequenceNumber.cbData = 0;
5680     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5681     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5682      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5683     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5684     if (buf)
5685     {
5686         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5687         LocalFree(buf);
5688         buf = NULL;
5689     }
5690     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5691     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5692      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5693      &buf, &size);
5694     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5695     if (buf)
5696     {
5697         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5698         LocalFree(buf);
5699         buf = NULL;
5700     }
5701     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5702     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5703     info.SubjectAlgorithm.pszObjId = oid2;
5704     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5705     info.SubjectAlgorithm.Parameters.pbData = nullData;
5706     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5707      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5708     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5709     if (buf)
5710     {
5711         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5712         LocalFree(buf);
5713         buf = NULL;
5714     }
5715     SetLastError(0xdeadbeef);
5716     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5717      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5718     ok(!ret &&
5719      (GetLastError() == CRYPT_E_ASN1_EOD ||
5720       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5721       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5722      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5723      GetLastError());
5724     info.SubjectAlgorithm.Parameters.cbData = 0;
5725     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5726     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5727     info.SubjectAlgorithm.pszObjId = oid2;
5728     info.SubjectAlgorithm.pszObjId = NULL;
5729     value1.cbData = sizeof(emptySequence);
5730     value1.pbData = (LPBYTE)emptySequence;
5731     attr1.pszObjId = oid1;
5732     attr1.cValue = 1;
5733     attr1.rgValue = &value1;
5734     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5735     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5736     ctlEntry[0].cAttribute = 1;
5737     ctlEntry[0].rgAttribute = &attr1;
5738     info.cCTLEntry = 1;
5739     info.rgCTLEntry = ctlEntry;
5740     SetLastError(0xdeadbeef);
5741     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5742      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5743     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5744     if (buf)
5745     {
5746         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5747         LocalFree(buf);
5748         buf = NULL;
5749     }
5750     value2.cbData = sizeof(encodedIPAddr);
5751     value2.pbData = (LPBYTE)encodedIPAddr;
5752     attr2.pszObjId = oid2;
5753     attr2.cValue = 1;
5754     attr2.rgValue = &value2;
5755     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5756     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5757     ctlEntry[1].cAttribute = 1;
5758     ctlEntry[1].rgAttribute = &attr2;
5759     info.cCTLEntry = 2;
5760     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5761      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5762     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5763     if (buf)
5764     {
5765         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5766         LocalFree(buf);
5767         buf = NULL;
5768     }
5769     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5770     SetLastError(0xdeadbeef);
5771     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5772      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5773     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5774      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5775      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5776      GetLastError());
5777     SetLastError(0xdeadbeef);
5778     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5779      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5780      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5781     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5782      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5783      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5784      GetLastError());
5785 }
5786
5787 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5788 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5789  0x03,0,0,0,0,0,0 };
5790 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5791  0xa0,0x01,0x01 };
5792 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5793  0x03,0x02,0x01,0x01 };
5794 static BYTE bogusDER[] = { 1 };
5795
5796 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5797 {
5798     BOOL ret;
5799     BYTE *buf = NULL;
5800     DWORD size = 0;
5801     CRYPT_CONTENT_INFO info = { 0 };
5802     char oid1[] = "1.2.3";
5803
5804     if (0)
5805     {
5806         /* Crashes on win9x */
5807         SetLastError(0xdeadbeef);
5808         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5809          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5810         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5811          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5812     }
5813     SetLastError(0xdeadbeef);
5814     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5815      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5816     ok(!ret && (GetLastError() == E_INVALIDARG ||
5817      GetLastError() == OSS_LIMITED /* Win9x */),
5818      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5819     info.pszObjId = oid1;
5820     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5821      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5822     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5823     if (buf)
5824     {
5825         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5826         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5827         LocalFree(buf);
5828     }
5829     info.Content.pbData = bogusDER;
5830     info.Content.cbData = sizeof(bogusDER);
5831     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5832      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5833     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5834     if (buf)
5835     {
5836         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5837         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5838         LocalFree(buf);
5839     }
5840     info.Content.pbData = (BYTE *)ints[0].encoded;
5841     info.Content.cbData = ints[0].encoded[1] + 2;
5842     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5843      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5844     if (buf)
5845     {
5846         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5847         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5848         LocalFree(buf);
5849     }
5850 }
5851
5852 static const BYTE indefiniteSignedPKCSContent[] = {
5853 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5854 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5855 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5856 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5857 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5858 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5859 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5860 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5861 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5862 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5863 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5864 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5865 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5866 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5867 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5868 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5869 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5870 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5871 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5872 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5873 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5874 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5875 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5876 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5877 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5878 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5879 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5880 0x00,0x00,0x00,0x00,0x00,0x00 };
5881
5882 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5883 {
5884     BOOL ret;
5885     LPBYTE buf = NULL;
5886     DWORD size = 0;
5887     CRYPT_CONTENT_INFO *info;
5888
5889     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5890      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5891      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5892     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5893     if (buf)
5894     {
5895         info = (CRYPT_CONTENT_INFO *)buf;
5896
5897         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5898          info->pszObjId);
5899         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5900          info->Content.cbData);
5901         LocalFree(buf);
5902     }
5903     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5904      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5905      0, NULL, NULL, &size);
5906     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5907     SetLastError(0xdeadbeef);
5908     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5909      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5910      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5911     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5912      * I doubt an app depends on that.
5913      */
5914     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5915      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5916      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5917      GetLastError());
5918     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5919      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5920      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5921     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5922     if (buf)
5923     {
5924         info = (CRYPT_CONTENT_INFO *)buf;
5925
5926         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5927          info->pszObjId);
5928         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5929          "Unexpected size %d\n", info->Content.cbData);
5930         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5931          info->Content.cbData), "Unexpected value\n");
5932         LocalFree(buf);
5933     }
5934     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5935      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5936      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5937     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5938     if (buf)
5939     {
5940         info = (CRYPT_CONTENT_INFO *)buf;
5941
5942         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5943          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5944         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5945          info->Content.cbData);
5946         LocalFree(buf);
5947     }
5948 }
5949
5950 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5951  0x00 };
5952 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5953  0x01 };
5954 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5955  0x02,0x01,0x01 };
5956
5957 static void test_encodePKCSAttribute(DWORD dwEncoding)
5958 {
5959     CRYPT_ATTRIBUTE attr = { 0 };
5960     BOOL ret;
5961     LPBYTE buf = NULL;
5962     DWORD size = 0;
5963     CRYPT_ATTR_BLOB blob;
5964     char oid[] = "1.2.3";
5965
5966     if (0)
5967     {
5968         /* Crashes on win9x */
5969         SetLastError(0xdeadbeef);
5970         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5971          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5972         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5973          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5974     }
5975     SetLastError(0xdeadbeef);
5976     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5977      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5978     ok(!ret && (GetLastError() == E_INVALIDARG ||
5979      GetLastError() == OSS_LIMITED /* Win9x */),
5980      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5981     attr.pszObjId = oid;
5982     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5983      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5984     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5985     if (buf)
5986     {
5987         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5988         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5989         LocalFree(buf);
5990     }
5991     blob.cbData = sizeof(bogusDER);
5992     blob.pbData = bogusDER;
5993     attr.cValue = 1;
5994     attr.rgValue = &blob;
5995     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5996      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5997     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5998     if (buf)
5999     {
6000         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
6001         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6002         LocalFree(buf);
6003     }
6004     blob.pbData = (BYTE *)ints[0].encoded;
6005     blob.cbData = ints[0].encoded[1] + 2;
6006     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6007      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6008     if (buf)
6009     {
6010         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6011         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6012         LocalFree(buf);
6013     }
6014 }
6015
6016 static void test_decodePKCSAttribute(DWORD dwEncoding)
6017 {
6018     BOOL ret;
6019     LPBYTE buf = NULL;
6020     DWORD size = 0;
6021     CRYPT_ATTRIBUTE *attr;
6022
6023     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6024      emptyPKCSAttr, sizeof(emptyPKCSAttr),
6025      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6026     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6027     if (buf)
6028     {
6029         attr = (CRYPT_ATTRIBUTE *)buf;
6030
6031         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6032          attr->pszObjId);
6033         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6034         LocalFree(buf);
6035     }
6036     SetLastError(0xdeadbeef);
6037     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6038      bogusPKCSAttr, sizeof(bogusPKCSAttr),
6039      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6040     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6041      * I doubt an app depends on that.
6042      */
6043     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6044      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6045      GetLastError() == OSS_MORE_INPUT /* Win9x */),
6046      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6047      GetLastError());
6048     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6049      intPKCSAttr, sizeof(intPKCSAttr),
6050      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6051     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6052     if (buf)
6053     {
6054         attr = (CRYPT_ATTRIBUTE *)buf;
6055
6056         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6057          attr->pszObjId);
6058         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6059         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6060          "Unexpected size %d\n", attr->rgValue[0].cbData);
6061         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6062          attr->rgValue[0].cbData), "Unexpected value\n");
6063         LocalFree(buf);
6064     }
6065 }
6066
6067 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6068 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6069  0x2a,0x03,0x31,0x00 };
6070 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6071  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6072
6073 static void test_encodePKCSAttributes(DWORD dwEncoding)
6074 {
6075     CRYPT_ATTRIBUTES attributes = { 0 };
6076     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6077     CRYPT_ATTR_BLOB blob;
6078     BOOL ret;
6079     LPBYTE buf = NULL;
6080     DWORD size = 0;
6081     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6082
6083     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6084      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6085     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6086     if (buf)
6087     {
6088         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6089         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6090         LocalFree(buf);
6091     }
6092     attributes.cAttr = 1;
6093     attributes.rgAttr = attr;
6094     SetLastError(0xdeadbeef);
6095     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6096      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6097     ok(!ret && (GetLastError() == E_INVALIDARG ||
6098      GetLastError() == OSS_LIMITED /* Win9x */),
6099      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6100     attr[0].pszObjId = oid1;
6101     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6102      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6103     if (buf)
6104     {
6105         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6106         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6107         LocalFree(buf);
6108     }
6109     attr[1].pszObjId = oid2;
6110     attr[1].cValue = 1;
6111     attr[1].rgValue = &blob;
6112     blob.pbData = (BYTE *)ints[0].encoded;
6113     blob.cbData = ints[0].encoded[1] + 2;
6114     attributes.cAttr = 2;
6115     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6116      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6117     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6118     if (buf)
6119     {
6120         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6121         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6122         LocalFree(buf);
6123     }
6124 }
6125
6126 static void test_decodePKCSAttributes(DWORD dwEncoding)
6127 {
6128     BOOL ret;
6129     LPBYTE buf = NULL;
6130     DWORD size = 0;
6131     CRYPT_ATTRIBUTES *attributes;
6132
6133     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6134      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6135      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6136     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6137     if (buf)
6138     {
6139         attributes = (CRYPT_ATTRIBUTES *)buf;
6140         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6141          attributes->cAttr);
6142         LocalFree(buf);
6143     }
6144     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6145      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6146      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6147     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6148     if (buf)
6149     {
6150         attributes = (CRYPT_ATTRIBUTES *)buf;
6151         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6152          attributes->cAttr);
6153         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6154          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6155         ok(attributes->rgAttr[0].cValue == 0,
6156          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6157         LocalFree(buf);
6158     }
6159     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6160      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6161      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6162     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6163     if (buf)
6164     {
6165         attributes = (CRYPT_ATTRIBUTES *)buf;
6166         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6167          attributes->cAttr);
6168         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6169          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6170         ok(attributes->rgAttr[0].cValue == 0,
6171          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6172         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6173          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6174         ok(attributes->rgAttr[1].cValue == 1,
6175          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6176         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6177          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6178         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6179          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6180         LocalFree(buf);
6181     }
6182 }
6183
6184 static const BYTE singleCapability[] = {
6185 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6186 static const BYTE twoCapabilities[] = {
6187 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6188 static const BYTE singleCapabilitywithNULL[] = {
6189 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6190
6191 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6192 {
6193     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6194     BOOL ret;
6195     LPBYTE buf = NULL;
6196     DWORD size = 0;
6197     CRYPT_SMIME_CAPABILITY capability[2];
6198     CRYPT_SMIME_CAPABILITIES capabilities;
6199
6200     /* An empty capabilities is allowed */
6201     capabilities.cCapability = 0;
6202     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6203      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6204     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6205     if (buf)
6206     {
6207         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6208         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6209         LocalFree(buf);
6210     }
6211     /* A non-empty capabilities with an empty capability (lacking an OID) is
6212      * not allowed
6213      */
6214     capability[0].pszObjId = NULL;
6215     capability[0].Parameters.cbData = 0;
6216     capabilities.cCapability = 1;
6217     capabilities.rgCapability = capability;
6218     SetLastError(0xdeadbeef);
6219     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6220      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6221     ok(!ret && (GetLastError() == E_INVALIDARG ||
6222      GetLastError() == OSS_LIMITED /* Win9x */),
6223      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6224     capability[0].pszObjId = oid1;
6225     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6226      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6227     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6228     if (buf)
6229     {
6230         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6231         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6232         LocalFree(buf);
6233     }
6234     capability[1].pszObjId = oid2;
6235     capability[1].Parameters.cbData = 0;
6236     capabilities.cCapability = 2;
6237     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6238      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6239     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6240     if (buf)
6241     {
6242         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6243         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6244         LocalFree(buf);
6245     }
6246 }
6247
6248 static void compareSMimeCapabilities(LPCSTR header,
6249  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6250 {
6251     DWORD i;
6252
6253     ok(got->cCapability == expected->cCapability,
6254      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6255      got->cCapability);
6256     for (i = 0; i < expected->cCapability; i++)
6257     {
6258         ok(!strcmp(expected->rgCapability[i].pszObjId,
6259          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6260          header, i, expected->rgCapability[i].pszObjId,
6261          got->rgCapability[i].pszObjId);
6262         ok(expected->rgCapability[i].Parameters.cbData ==
6263          got->rgCapability[i].Parameters.cbData,
6264          "%s[%d]: expected %d bytes, got %d\n", header, i,
6265          expected->rgCapability[i].Parameters.cbData,
6266          got->rgCapability[i].Parameters.cbData);
6267         if (expected->rgCapability[i].Parameters.cbData)
6268             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6269              got->rgCapability[i].Parameters.pbData,
6270              expected->rgCapability[i].Parameters.cbData),
6271              "%s[%d]: unexpected value\n", header, i);
6272     }
6273 }
6274
6275 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6276 {
6277     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6278     BOOL ret;
6279     DWORD size = 0;
6280     CRYPT_SMIME_CAPABILITY capability[2];
6281     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6282
6283     SetLastError(0xdeadbeef);
6284     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6285      emptySequence, sizeof(emptySequence),
6286      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6287     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6288     if (ret)
6289     {
6290         capabilities.cCapability = 0;
6291         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6292         LocalFree(ptr);
6293     }
6294     SetLastError(0xdeadbeef);
6295     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6296      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6297      &ptr, &size);
6298     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6299     if (ret)
6300     {
6301         capability[0].pszObjId = oid1;
6302         capability[0].Parameters.cbData = 0;
6303         capabilities.cCapability = 1;
6304         capabilities.rgCapability = capability;
6305         compareSMimeCapabilities("single capability", &capabilities, ptr);
6306         LocalFree(ptr);
6307     }
6308     SetLastError(0xdeadbeef);
6309     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6310      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6311      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6312     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6313     if (ret)
6314     {
6315         BYTE NULLparam[] = {0x05, 0x00};
6316         capability[0].pszObjId = oid1;
6317         capability[0].Parameters.cbData = 2;
6318         capability[0].Parameters.pbData = NULLparam;
6319         capabilities.cCapability = 1;
6320         capabilities.rgCapability = capability;
6321         compareSMimeCapabilities("single capability with NULL", &capabilities,
6322          ptr);
6323         LocalFree(ptr);
6324     }
6325     SetLastError(0xdeadbeef);
6326     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6327     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6328     &ptr, &size);
6329     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6330     if (ret)
6331     {
6332         capability[0].Parameters.cbData = 0;
6333         capability[1].pszObjId = oid2;
6334         capability[1].Parameters.cbData = 0;
6335         capabilities.cCapability = 2;
6336         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6337         LocalFree(ptr);
6338     }
6339 }
6340
6341 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6342  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6343  0x67 };
6344 static const BYTE minimalPKCSSigner[] = {
6345  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6346  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6347  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6348 static const BYTE PKCSSignerWithSerial[] = {
6349  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6350  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6351  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6352  0x00 };
6353 static const BYTE PKCSSignerWithHashAlgo[] = {
6354  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6355  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6356  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6357  0x00,0x04,0x00 };
6358 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6359  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6360  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6361  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6362  0x06,0x05,0x00,0x04,0x00 };
6363 static const BYTE PKCSSignerWithHash[] = {
6364  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6365  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6366  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6367  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6368  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6369 static const BYTE PKCSSignerWithAuthAttr[] = {
6370 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6371 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6372 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6373 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6374 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6375 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6376 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6377
6378 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6379 {
6380     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6381     BOOL ret;
6382     LPBYTE buf = NULL;
6383     DWORD size = 0;
6384     CMSG_SIGNER_INFO info = { 0 };
6385     char oid_common_name[] = szOID_COMMON_NAME;
6386     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6387      (LPBYTE)encodedCommonName };
6388     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6389
6390     SetLastError(0xdeadbeef);
6391     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6392      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6393     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6394     {
6395         skip("no PKCS7_SIGNER_INFO encode support\n");
6396         return;
6397     }
6398     ok(!ret && (GetLastError() == E_INVALIDARG ||
6399      GetLastError() == OSS_LIMITED /* Win9x */),
6400      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6401     /* To be encoded, a signer must have an issuer at least, and the encoding
6402      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6403      * see decoding tests.)
6404      */
6405     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6406     info.Issuer.pbData = encodedCommonNameNoNull;
6407     SetLastError(0xdeadbeef);
6408     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6409      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6410     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6411         ok(!ret && GetLastError() == E_INVALIDARG,
6412          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6413     else
6414     {
6415         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6416          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6417         if (buf)
6418         {
6419             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6420             if (size == sizeof(minimalPKCSSigner))
6421                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6422             else
6423                 ok(0, "Unexpected value\n");
6424             LocalFree(buf);
6425         }
6426     }
6427     info.SerialNumber.cbData = sizeof(serialNum);
6428     info.SerialNumber.pbData = (BYTE *)serialNum;
6429     SetLastError(0xdeadbeef);
6430     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6431      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6432     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6433         ok(!ret && GetLastError() == E_INVALIDARG,
6434          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6435     else
6436     {
6437         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6438          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6439         if (buf)
6440         {
6441             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6442              size);
6443             if (size == sizeof(PKCSSignerWithSerial))
6444                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6445                  "Unexpected value\n");
6446             else
6447                 ok(0, "Unexpected value\n");
6448             LocalFree(buf);
6449         }
6450     }
6451     info.HashAlgorithm.pszObjId = oid1;
6452     SetLastError(0xdeadbeef);
6453     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6454      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6455     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6456         ok(!ret && GetLastError() == E_INVALIDARG,
6457          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6458     else
6459     {
6460         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6461          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6462         if (buf)
6463         {
6464             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6465              size);
6466             if (size == sizeof(PKCSSignerWithHashAlgo))
6467                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6468                  "Unexpected value\n");
6469             else
6470                 ok(0, "Unexpected value\n");
6471             LocalFree(buf);
6472         }
6473     }
6474     info.HashEncryptionAlgorithm.pszObjId = oid2;
6475     SetLastError(0xdeadbeef);
6476     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6477      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6478     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6479         ok(!ret && GetLastError() == E_INVALIDARG,
6480          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6481     else
6482     {
6483         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6484         if (buf)
6485         {
6486             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6487              "Unexpected size %d\n", size);
6488             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6489                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6490                  "Unexpected value\n");
6491             else
6492                 ok(0, "Unexpected value\n");
6493             LocalFree(buf);
6494         }
6495     }
6496     info.EncryptedHash.cbData = sizeof(hash);
6497     info.EncryptedHash.pbData = (BYTE *)hash;
6498     SetLastError(0xdeadbeef);
6499     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6500      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6501     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6502         ok(!ret && GetLastError() == E_INVALIDARG,
6503          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6504     else
6505     {
6506         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6507         if (buf)
6508         {
6509             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6510              size);
6511             if (size == sizeof(PKCSSignerWithHash))
6512                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6513                  "Unexpected value\n");
6514             else
6515                 ok(0, "Unexpected value\n");
6516             LocalFree(buf);
6517         }
6518     }
6519     info.AuthAttrs.cAttr = 1;
6520     info.AuthAttrs.rgAttr = &attr;
6521     SetLastError(0xdeadbeef);
6522     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6523      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6524     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6525         ok(!ret && GetLastError() == E_INVALIDARG,
6526          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6527     else
6528     {
6529         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6530         if (buf)
6531         {
6532             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6533              size);
6534             if (size == sizeof(PKCSSignerWithAuthAttr))
6535                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6536                  "Unexpected value\n");
6537             else
6538                 ok(0, "Unexpected value\n");
6539             LocalFree(buf);
6540         }
6541     }
6542 }
6543
6544 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6545 {
6546     BOOL ret;
6547     LPBYTE buf = NULL;
6548     DWORD size = 0;
6549     CMSG_SIGNER_INFO *info;
6550
6551     /* A PKCS signer can't be decoded without a serial number. */
6552     SetLastError(0xdeadbeef);
6553     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6554      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6555      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6556     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6557      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6558      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6559      GetLastError());
6560     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6561      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6562      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6563     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6564      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6565     if (buf)
6566     {
6567         info = (CMSG_SIGNER_INFO *)buf;
6568         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6569          info->dwVersion);
6570         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6571          "Unexpected size %d\n", info->Issuer.cbData);
6572         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6573          info->Issuer.cbData), "Unexpected value\n");
6574         ok(info->SerialNumber.cbData == sizeof(serialNum),
6575          "Unexpected size %d\n", info->SerialNumber.cbData);
6576         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6577          "Unexpected value\n");
6578         LocalFree(buf);
6579     }
6580     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6581      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6582      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6583     if (buf)
6584     {
6585         info = (CMSG_SIGNER_INFO *)buf;
6586         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6587          info->dwVersion);
6588         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6589          "Unexpected size %d\n", info->Issuer.cbData);
6590         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6591          info->Issuer.cbData), "Unexpected value\n");
6592         ok(info->SerialNumber.cbData == sizeof(serialNum),
6593          "Unexpected size %d\n", info->SerialNumber.cbData);
6594         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6595          "Unexpected value\n");
6596         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6597          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6598         LocalFree(buf);
6599     }
6600     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6601      PKCSSignerWithHashAndEncryptionAlgo,
6602      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6603      NULL, &buf, &size);
6604     if (buf)
6605     {
6606         info = (CMSG_SIGNER_INFO *)buf;
6607         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6608          info->dwVersion);
6609         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6610          "Unexpected size %d\n", info->Issuer.cbData);
6611         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6612          info->Issuer.cbData), "Unexpected value\n");
6613         ok(info->SerialNumber.cbData == sizeof(serialNum),
6614          "Unexpected size %d\n", info->SerialNumber.cbData);
6615         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6616          "Unexpected value\n");
6617         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6618          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6619         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6620          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6621         LocalFree(buf);
6622     }
6623     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6624      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6625      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6626     if (buf)
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         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6640          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6641         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6642          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6643         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6644          info->EncryptedHash.cbData);
6645         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6646          "Unexpected value\n");
6647         LocalFree(buf);
6648     }
6649     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6650      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6651      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6652     if (buf)
6653     {
6654         info = (CMSG_SIGNER_INFO *)buf;
6655         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6656          info->AuthAttrs.cAttr);
6657         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6658          "Expected %s, got %s\n", szOID_COMMON_NAME,
6659          info->AuthAttrs.rgAttr[0].pszObjId);
6660         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6661          info->AuthAttrs.rgAttr[0].cValue);
6662         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6663          sizeof(encodedCommonName), "Unexpected size %d\n",
6664          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6665         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6666          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6667         LocalFree(buf);
6668     }
6669 }
6670
6671 static const BYTE CMSSignerWithKeyId[] = {
6672 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6673 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6674
6675 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6676 {
6677     BOOL ret;
6678     LPBYTE buf = NULL;
6679     DWORD size = 0;
6680     CMSG_CMS_SIGNER_INFO info = { 0 };
6681     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6682
6683     SetLastError(0xdeadbeef);
6684     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6685      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6686     ok(!ret, "Expected failure, got %d\n", ret);
6687     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6688     {
6689         skip("no CMS_SIGNER_INFO encode support\n");
6690         return;
6691     }
6692     ok(GetLastError() == E_INVALIDARG,
6693        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6694     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6695     SetLastError(0xdeadbeef);
6696     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6697      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6698     ok(!ret, "Expected failure, got %d\n", ret);
6699     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6700     {
6701         skip("no CMS_SIGNER_INFO encode support\n");
6702         return;
6703     }
6704     ok(GetLastError() == E_INVALIDARG,
6705        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6706     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6707      * be a key id or a issuer serial number with at least the issuer set, and
6708      * the encoding must include PKCS_7_ASN_ENCODING.
6709      * (That isn't enough to be decoded, see decoding tests.)
6710      */
6711     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6712      sizeof(encodedCommonNameNoNull);
6713     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6714     SetLastError(0xdeadbeef);
6715     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6716      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6717     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6718         ok(!ret && GetLastError() == E_INVALIDARG,
6719          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6720     else
6721     {
6722         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6723         if (buf)
6724         {
6725             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6726             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6727             LocalFree(buf);
6728         }
6729     }
6730     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6731     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6732     SetLastError(0xdeadbeef);
6733     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6734      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6735     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6736         ok(!ret && GetLastError() == E_INVALIDARG,
6737          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6738     else
6739     {
6740         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6741         if (buf)
6742         {
6743             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6744              size);
6745             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6746             LocalFree(buf);
6747         }
6748     }
6749     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6750     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6751     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6752     SetLastError(0xdeadbeef);
6753     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6754      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6755     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6756         ok(!ret && GetLastError() == E_INVALIDARG,
6757          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6758     else
6759     {
6760         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6761         if (buf)
6762         {
6763             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6764              size);
6765             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6766             LocalFree(buf);
6767         }
6768     }
6769     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6770      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6771      * (see RFC 3852, section 5.3.)
6772      */
6773     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6774     U(info.SignerId).HashId.cbData = sizeof(hash);
6775     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6776     SetLastError(0xdeadbeef);
6777     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6778      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6779     ok(!ret && GetLastError() == E_INVALIDARG,
6780      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6781     /* Now with a hash algo */
6782     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6783     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6784      sizeof(encodedCommonNameNoNull);
6785     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6786     info.HashAlgorithm.pszObjId = oid1;
6787     SetLastError(0xdeadbeef);
6788     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6789      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6790     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6791         ok(!ret && GetLastError() == E_INVALIDARG,
6792          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6793     else
6794     {
6795         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6796         if (buf)
6797         {
6798             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6799              size);
6800             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6801              "Unexpected value\n");
6802             LocalFree(buf);
6803         }
6804     }
6805     info.HashEncryptionAlgorithm.pszObjId = oid2;
6806     SetLastError(0xdeadbeef);
6807     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6808      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6809     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6810         ok(!ret && GetLastError() == E_INVALIDARG,
6811          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6812     else
6813     {
6814         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6815         if (buf)
6816         {
6817             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6818              "Unexpected size %d\n", size);
6819             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6820              "Unexpected value\n");
6821             LocalFree(buf);
6822         }
6823     }
6824     info.EncryptedHash.cbData = sizeof(hash);
6825     info.EncryptedHash.pbData = (BYTE *)hash;
6826     SetLastError(0xdeadbeef);
6827     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6828      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6829     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6830         ok(!ret && GetLastError() == E_INVALIDARG,
6831          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6832     else
6833     {
6834         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6835         if (buf)
6836         {
6837             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6838              size);
6839             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6840             LocalFree(buf);
6841         }
6842     }
6843 }
6844
6845 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6846 {
6847     BOOL ret;
6848     LPBYTE buf = NULL;
6849     DWORD size = 0;
6850     CMSG_CMS_SIGNER_INFO *info;
6851     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6852
6853     /* A CMS signer can't be decoded without a serial number. */
6854     SetLastError(0xdeadbeef);
6855     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6856      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6857      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6858     ok(!ret, "expected failure\n");
6859     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6860     {
6861         skip("no CMS_SIGNER_INFO decode support\n");
6862         return;
6863     }
6864     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6865      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6866     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6867      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6868      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6869     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6870     if (buf)
6871     {
6872         info = (CMSG_CMS_SIGNER_INFO *)buf;
6873         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6874          info->dwVersion);
6875         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6876          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6877          info->SignerId.dwIdChoice);
6878         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6879          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6880          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6881         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6882          encodedCommonNameNoNull,
6883          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6884          "Unexpected value\n");
6885         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6886          sizeof(serialNum), "Unexpected size %d\n",
6887          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6888         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6889          serialNum, sizeof(serialNum)), "Unexpected value\n");
6890         LocalFree(buf);
6891     }
6892     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6893      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6894      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6895     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6896     if (buf)
6897     {
6898         info = (CMSG_CMS_SIGNER_INFO *)buf;
6899         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6900          info->dwVersion);
6901         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6902          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6903          info->SignerId.dwIdChoice);
6904         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6905          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6906          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6907         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6908          encodedCommonNameNoNull,
6909          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6910          "Unexpected value\n");
6911         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6912          sizeof(serialNum), "Unexpected size %d\n",
6913          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6914         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6915          serialNum, sizeof(serialNum)), "Unexpected value\n");
6916         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6917          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6918         LocalFree(buf);
6919     }
6920     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6921      PKCSSignerWithHashAndEncryptionAlgo,
6922      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6923      NULL, &buf, &size);
6924     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6925     if (buf)
6926     {
6927         info = (CMSG_CMS_SIGNER_INFO *)buf;
6928         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6929          info->dwVersion);
6930         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6931          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6932          info->SignerId.dwIdChoice);
6933         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6934          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6935          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6936         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6937          encodedCommonNameNoNull,
6938          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6939          "Unexpected value\n");
6940         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6941          sizeof(serialNum), "Unexpected size %d\n",
6942          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6943         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6944          serialNum, sizeof(serialNum)), "Unexpected value\n");
6945         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6946          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6947         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6948          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6949         LocalFree(buf);
6950     }
6951     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6952      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6953      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6954     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6955     if (buf)
6956     {
6957         info = (CMSG_CMS_SIGNER_INFO *)buf;
6958         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6959          info->dwVersion);
6960         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6961          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6962          info->SignerId.dwIdChoice);
6963         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6964          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6965          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6966         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6967          encodedCommonNameNoNull,
6968          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6969          "Unexpected value\n");
6970         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6971          sizeof(serialNum), "Unexpected size %d\n",
6972          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6973         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6974          serialNum, sizeof(serialNum)), "Unexpected value\n");
6975         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6976          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6977         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6978          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6979         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6980          info->EncryptedHash.cbData);
6981         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6982          "Unexpected value\n");
6983         LocalFree(buf);
6984     }
6985     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6986      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6987      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6988     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6989     if (buf)
6990     {
6991         info = (CMSG_CMS_SIGNER_INFO *)buf;
6992         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6993          info->dwVersion);
6994         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6995          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6996          info->SignerId.dwIdChoice);
6997         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6998          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6999         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
7000          "Unexpected value\n");
7001         LocalFree(buf);
7002     }
7003 }
7004
7005 static BYTE emptyDNSPermittedConstraints[] = {
7006 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7007 static BYTE emptyDNSExcludedConstraints[] = {
7008 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7009 static BYTE DNSExcludedConstraints[] = {
7010 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7011 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7012 static BYTE permittedAndExcludedConstraints[] = {
7013 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7014 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7015 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7016 static BYTE permittedAndExcludedWithMinConstraints[] = {
7017 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7018 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7019 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7020 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7021 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7022 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7023 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7024
7025 static void test_encodeNameConstraints(DWORD dwEncoding)
7026 {
7027     BOOL ret;
7028     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7029     CERT_GENERAL_SUBTREE permitted = { { 0 } };
7030     CERT_GENERAL_SUBTREE excluded = { { 0 } };
7031     LPBYTE buf;
7032     DWORD size;
7033
7034     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7035      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7036     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7037     {
7038         skip("no X509_NAME_CONSTRAINTS encode support\n");
7039         return;
7040     }
7041     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7042     if (ret)
7043     {
7044         ok(size == sizeof(emptySequence), "Unexpected size\n");
7045         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7046         LocalFree(buf);
7047     }
7048     constraints.cPermittedSubtree = 1;
7049     constraints.rgPermittedSubtree = &permitted;
7050     SetLastError(0xdeadbeef);
7051     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7052      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7053     ok(!ret && GetLastError() == E_INVALIDARG,
7054      "Expected E_INVALIDARG, got %08x\n", GetLastError());
7055     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7056     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7057      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7058     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7059     if (ret)
7060     {
7061         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7062         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7063          "Unexpected value\n");
7064         LocalFree(buf);
7065     }
7066     constraints.cPermittedSubtree = 0;
7067     constraints.cExcludedSubtree = 1;
7068     constraints.rgExcludedSubtree = &excluded;
7069     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7070     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7071      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7072     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7073     if (ret)
7074     {
7075         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7076         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7077          "Unexpected value\n");
7078         LocalFree(buf);
7079     }
7080     U(excluded.Base).pwszURL = (LPWSTR)url;
7081     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7082      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7083     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7084     if (ret)
7085     {
7086         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7087         ok(!memcmp(buf, DNSExcludedConstraints, size),
7088          "Unexpected value\n");
7089         LocalFree(buf);
7090     }
7091     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7092     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7093     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7094     constraints.cPermittedSubtree = 1;
7095     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7096      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7097     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7098     if (ret)
7099     {
7100         ok(size == sizeof(permittedAndExcludedConstraints),
7101          "Unexpected size\n");
7102         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7103          "Unexpected value\n");
7104         LocalFree(buf);
7105     }
7106     permitted.dwMinimum = 5;
7107     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7108      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7109     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7110     if (ret)
7111     {
7112         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7113          "Unexpected size\n");
7114         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7115          "Unexpected value\n");
7116         LocalFree(buf);
7117     }
7118     permitted.fMaximum = TRUE;
7119     permitted.dwMaximum = 3;
7120     SetLastError(0xdeadbeef);
7121     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7122      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7123     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7124     if (ret)
7125     {
7126         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7127          "Unexpected size\n");
7128         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7129          "Unexpected value\n");
7130         LocalFree(buf);
7131     }
7132 }
7133
7134 struct EncodedNameConstraints
7135 {
7136     CRYPT_DATA_BLOB            encoded;
7137     CERT_NAME_CONSTRAINTS_INFO constraints;
7138 };
7139
7140 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7141  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7142 static CERT_GENERAL_SUBTREE DNSSubtree = {
7143  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7144 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7145  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7146 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7147  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7148 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7149  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7150
7151 struct EncodedNameConstraints encodedNameConstraints[] = {
7152  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7153  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7154    { 1, &emptyDNSSubtree, 0, NULL } },
7155  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7156    { 0, NULL, 1, &emptyDNSSubtree } },
7157  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7158    { 0, NULL, 1, &DNSSubtree } },
7159  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7160    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7161  { { sizeof(permittedAndExcludedWithMinConstraints),
7162      permittedAndExcludedWithMinConstraints },
7163    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7164  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7165      permittedAndExcludedWithMinMaxConstraints },
7166    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7167 };
7168
7169 static void test_decodeNameConstraints(DWORD dwEncoding)
7170 {
7171     BOOL ret;
7172     DWORD i;
7173     CERT_NAME_CONSTRAINTS_INFO *constraints;
7174
7175     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7176     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7177     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7178     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7179     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7180     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7181     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7182     for (i = 0;
7183      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7184      i++)
7185     {
7186         DWORD size;
7187
7188         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7189          encodedNameConstraints[i].encoded.pbData,
7190          encodedNameConstraints[i].encoded.cbData,
7191          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7192         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7193         {
7194             skip("no X509_NAME_CONSTRAINTS decode support\n");
7195             return;
7196         }
7197         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7198         if (ret)
7199         {
7200             DWORD j;
7201
7202             if (constraints->cPermittedSubtree !=
7203              encodedNameConstraints[i].constraints.cPermittedSubtree)
7204                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7205                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7206                  constraints->cPermittedSubtree);
7207             if (constraints->cPermittedSubtree ==
7208              encodedNameConstraints[i].constraints.cPermittedSubtree)
7209             {
7210                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7211                 {
7212                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7213                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7214                 }
7215             }
7216             if (constraints->cExcludedSubtree !=
7217              encodedNameConstraints[i].constraints.cExcludedSubtree)
7218                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7219                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7220                  constraints->cExcludedSubtree);
7221             if (constraints->cExcludedSubtree ==
7222              encodedNameConstraints[i].constraints.cExcludedSubtree)
7223             {
7224                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7225                 {
7226                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7227                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7228                 }
7229             }
7230             LocalFree(constraints);
7231         }
7232     }
7233 }
7234
7235 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7236  'n','o','t','i','c','e',0 };
7237 static const BYTE noticeWithDisplayText[] = {
7238  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7239  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7240  0x00,0x69,0x00,0x63,0x00,0x65
7241 };
7242 static char org[] = "Wine";
7243 static int noticeNumbers[] = { 2,3 };
7244 static BYTE noticeWithReference[] = {
7245  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7246  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7247  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7248  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7249 };
7250
7251 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7252 {
7253     BOOL ret;
7254     LPBYTE buf;
7255     DWORD size;
7256     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7257     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7258
7259     memset(&notice, 0, sizeof(notice));
7260     ret = pCryptEncodeObjectEx(dwEncoding,
7261      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7262      NULL, &buf, &size);
7263     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7264     {
7265         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7266         return;
7267     }
7268     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7269     if (ret)
7270     {
7271         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7272         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7273         LocalFree(buf);
7274     }
7275     notice.pszDisplayText = noticeText;
7276     ret = pCryptEncodeObjectEx(dwEncoding,
7277      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7278      NULL, &buf, &size);
7279     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7280     if (ret)
7281     {
7282         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7283         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7284         LocalFree(buf);
7285     }
7286     reference.pszOrganization = org;
7287     reference.cNoticeNumbers = 2;
7288     reference.rgNoticeNumbers = noticeNumbers;
7289     notice.pNoticeReference = &reference;
7290     ret = pCryptEncodeObjectEx(dwEncoding,
7291      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7292      NULL, &buf, &size);
7293     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7294     if (ret)
7295     {
7296         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7297         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7298         LocalFree(buf);
7299     }
7300 }
7301
7302 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7303 {
7304     BOOL ret;
7305     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7306     DWORD size;
7307
7308     ret = pCryptDecodeObjectEx(dwEncoding,
7309      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7310      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7311      &notice, &size);
7312     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7313     {
7314         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7315         return;
7316     }
7317     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7318     if (ret)
7319     {
7320         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7321         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7322         LocalFree(notice);
7323     }
7324     ret = pCryptDecodeObjectEx(dwEncoding,
7325      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7326      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7327      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7329     if (ret)
7330     {
7331         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7332          "unexpected display text\n");
7333         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7334         LocalFree(notice);
7335     }
7336     ret = pCryptDecodeObjectEx(dwEncoding,
7337      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7338      noticeWithReference, sizeof(noticeWithReference),
7339      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7340     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7341     if (ret)
7342     {
7343         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7344          "unexpected display text\n");
7345         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7346         if (notice->pNoticeReference)
7347         {
7348             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7349              "unexpected organization %s\n",
7350              notice->pNoticeReference->pszOrganization);
7351             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7352              "expected 2 notice numbers, got %d\n",
7353              notice->pNoticeReference->cNoticeNumbers);
7354             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7355              "unexpected notice number %d\n",
7356              notice->pNoticeReference->rgNoticeNumbers[0]);
7357             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7358              "unexpected notice number %d\n",
7359              notice->pNoticeReference->rgNoticeNumbers[1]);
7360         }
7361         LocalFree(notice);
7362     }
7363 }
7364
7365 static char oid_any_policy[] = "2.5.29.32.0";
7366 static const BYTE policiesWithAnyPolicy[] = {
7367  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7368 };
7369 static char oid1[] = "1.2.3";
7370 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7371 static const BYTE twoPolicies[] = {
7372  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7373  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7374  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7375  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7376  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7377  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7378 };
7379
7380 static void test_encodeCertPolicies(DWORD dwEncoding)
7381 {
7382     BOOL ret;
7383     CERT_POLICIES_INFO info;
7384     CERT_POLICY_INFO policy[2];
7385     CERT_POLICY_QUALIFIER_INFO qualifier;
7386     LPBYTE buf;
7387     DWORD size;
7388
7389     memset(&info, 0, sizeof(info));
7390     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7391      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7392     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7393     if (ret)
7394     {
7395         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7396         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7397         LocalFree(buf);
7398     }
7399     memset(policy, 0, sizeof(policy));
7400     info.cPolicyInfo = 1;
7401     info.rgPolicyInfo = policy;
7402     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7403      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7404     ok(!ret && (GetLastError() == E_INVALIDARG ||
7405      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7406      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7407     policy[0].pszPolicyIdentifier = oid_any_policy;
7408     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7409      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7410     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7411     if (ret)
7412     {
7413         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7414         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7415         LocalFree(buf);
7416     }
7417     policy[1].pszPolicyIdentifier = oid1;
7418     memset(&qualifier, 0, sizeof(qualifier));
7419     qualifier.pszPolicyQualifierId = oid_user_notice;
7420     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7421     qualifier.Qualifier.pbData = noticeWithReference;
7422     policy[1].cPolicyQualifier = 1;
7423     policy[1].rgPolicyQualifier = &qualifier;
7424     info.cPolicyInfo = 2;
7425     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7426      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7427     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7428     if (ret)
7429     {
7430         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7431         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7432         LocalFree(buf);
7433     }
7434 }
7435
7436 static void test_decodeCertPolicies(DWORD dwEncoding)
7437 {
7438     BOOL ret;
7439     CERT_POLICIES_INFO *info;
7440     DWORD size;
7441
7442     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7443      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7444      &info, &size);
7445     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7446     if (ret)
7447     {
7448         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7449          info->cPolicyInfo);
7450         LocalFree(info);
7451     }
7452     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7453      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7454      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7455     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7456     if (ret)
7457     {
7458         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7459          info->cPolicyInfo);
7460         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7461          "unexpected policy id %s\n",
7462          info->rgPolicyInfo[0].pszPolicyIdentifier);
7463         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7464          "unexpected policy qualifier count %d\n",
7465          info->rgPolicyInfo[0].cPolicyQualifier);
7466         LocalFree(info);
7467     }
7468     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7469      twoPolicies, sizeof(twoPolicies),
7470      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7471     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7472     if (ret)
7473     {
7474         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7475          info->cPolicyInfo);
7476         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7477          "unexpected policy id %s\n",
7478          info->rgPolicyInfo[0].pszPolicyIdentifier);
7479         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7480          "unexpected policy qualifier count %d\n",
7481          info->rgPolicyInfo[0].cPolicyQualifier);
7482         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7483          "unexpected policy id %s\n",
7484          info->rgPolicyInfo[1].pszPolicyIdentifier);
7485         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7486          "unexpected policy qualifier count %d\n",
7487          info->rgPolicyInfo[1].cPolicyQualifier);
7488         ok(!strcmp(
7489          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7490          oid_user_notice), "unexpected policy qualifier id %s\n",
7491          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7492         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7493          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7494          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7495         ok(!memcmp(
7496          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7497          noticeWithReference, sizeof(noticeWithReference)),
7498          "unexpected qualifier value\n");
7499         LocalFree(info);
7500     }
7501 }
7502
7503 static const BYTE policyMappingWithOneMapping[] = {
7504 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7505 static const BYTE policyMappingWithTwoMappings[] = {
7506 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7507 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7508 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7509  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7510
7511 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7512 {
7513     static char oid2[] = "2.3.4";
7514     static char oid3[] = "1.3.4";
7515     static char oid4[] = "2.5.6";
7516     BOOL ret;
7517     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7518     CERT_POLICY_MAPPING mapping[2];
7519     LPBYTE buf;
7520     DWORD size, i;
7521
7522     /* Each of the mapping OIDs is equivalent, so check with all of them */
7523     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7524     {
7525         memset(&info, 0, sizeof(info));
7526         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7527          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7528         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7529         if (ret)
7530         {
7531             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7532             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7533              "unexpected value\n");
7534             LocalFree(buf);
7535         }
7536         mapping[0].pszIssuerDomainPolicy = NULL;
7537         mapping[0].pszSubjectDomainPolicy = NULL;
7538         info.cPolicyMapping = 1;
7539         info.rgPolicyMapping = mapping;
7540         SetLastError(0xdeadbeef);
7541         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7542          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7543         ok(!ret && GetLastError() == E_INVALIDARG,
7544          "expected E_INVALIDARG, got %08x\n", GetLastError());
7545         mapping[0].pszIssuerDomainPolicy = oid1;
7546         mapping[0].pszSubjectDomainPolicy = oid2;
7547         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7548          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7549         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7550         if (ret)
7551         {
7552             ok(size == sizeof(policyMappingWithOneMapping),
7553              "unexpected size %d\n", size);
7554             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7555              "unexpected value\n");
7556             LocalFree(buf);
7557         }
7558         mapping[1].pszIssuerDomainPolicy = oid3;
7559         mapping[1].pszSubjectDomainPolicy = oid4;
7560         info.cPolicyMapping = 2;
7561         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7562          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7563         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7564         if (ret)
7565         {
7566             ok(size == sizeof(policyMappingWithTwoMappings),
7567              "unexpected size %d\n", size);
7568             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7569              "unexpected value\n");
7570             LocalFree(buf);
7571         }
7572     }
7573 }
7574
7575 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7576 {
7577     DWORD size, i;
7578     CERT_POLICY_MAPPINGS_INFO *info;
7579     BOOL ret;
7580
7581     /* Each of the mapping OIDs is equivalent, so check with all of them */
7582     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7583     {
7584         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7585          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7586          &info, &size);
7587         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7588         if (ret)
7589         {
7590             ok(info->cPolicyMapping == 0,
7591              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7592             LocalFree(info);
7593         }
7594         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7595          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7596          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7597         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7598         if (ret)
7599         {
7600             ok(info->cPolicyMapping == 1,
7601              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7602             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7603              "unexpected issuer policy %s\n",
7604              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7605             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7606              "2.3.4"), "unexpected subject policy %s\n",
7607              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7608             LocalFree(info);
7609         }
7610         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7611          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7612          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7613         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7614         if (ret)
7615         {
7616             ok(info->cPolicyMapping == 2,
7617              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7618             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7619              "unexpected issuer policy %s\n",
7620              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7621             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7622              "2.3.4"), "unexpected subject policy %s\n",
7623              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7624             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7625              "unexpected issuer policy %s\n",
7626              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7627             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7628              "2.5.6"), "unexpected subject policy %s\n",
7629              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7630             LocalFree(info);
7631         }
7632     }
7633 }
7634
7635 static const BYTE policyConstraintsWithRequireExplicit[] = {
7636 0x30,0x03,0x80,0x01,0x00 };
7637 static const BYTE policyConstraintsWithInhibitMapping[] = {
7638 0x30,0x03,0x81,0x01,0x01 };
7639 static const BYTE policyConstraintsWithBoth[] = {
7640 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7641
7642 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7643 {
7644     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7645     LPBYTE buf;
7646     DWORD size;
7647     BOOL ret;
7648
7649     /* Even though RFC 5280 explicitly states CAs must not issue empty
7650      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7651      */
7652     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7653      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7654     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7655     if (ret)
7656     {
7657         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7658         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7659          "unexpected value\n");
7660         LocalFree(buf);
7661     }
7662     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7663      * is not, then a skip of 0 is encoded.
7664      */
7665     info.fRequireExplicitPolicy = TRUE;
7666     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7667      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7668     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7669     if (ret)
7670     {
7671         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7672          "unexpected size %d\n", size);
7673         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7674          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7675         LocalFree(buf);
7676     }
7677     /* With inhibit policy mapping */
7678     info.fRequireExplicitPolicy = FALSE;
7679     info.dwRequireExplicitPolicySkipCerts = 0;
7680     info.fInhibitPolicyMapping = TRUE;
7681     info.dwInhibitPolicyMappingSkipCerts = 1;
7682     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7683      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7684     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7685     if (ret)
7686     {
7687         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7688          "unexpected size %d\n", size);
7689         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7690          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7691         LocalFree(buf);
7692     }
7693     /* And with both */
7694     info.fRequireExplicitPolicy = TRUE;
7695     info.dwRequireExplicitPolicySkipCerts = 1;
7696     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7697      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7698     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7699     if (ret)
7700     {
7701         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7702          size);
7703         ok(!memcmp(buf, policyConstraintsWithBoth,
7704          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7705         LocalFree(buf);
7706     }
7707 }
7708
7709 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7710 {
7711     CERT_POLICY_CONSTRAINTS_INFO *info;
7712     DWORD size;
7713     BOOL ret;
7714
7715     /* Again, even though CAs must not issue such constraints, they can be
7716      * decoded.
7717      */
7718     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7719      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7720      &info, &size);
7721     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7722     if (ret)
7723     {
7724         ok(!info->fRequireExplicitPolicy,
7725          "expected require explicit = FALSE\n");
7726         ok(!info->fInhibitPolicyMapping,
7727          "expected implicit mapping = FALSE\n");
7728         LocalFree(info);
7729     }
7730     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7731      policyConstraintsWithRequireExplicit,
7732      sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7733      NULL, &info, &size);
7734     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7735     if (ret)
7736     {
7737         ok(info->fRequireExplicitPolicy,
7738          "expected require explicit = TRUE\n");
7739         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7740          info->dwRequireExplicitPolicySkipCerts);
7741         ok(!info->fInhibitPolicyMapping,
7742          "expected implicit mapping = FALSE\n");
7743         LocalFree(info);
7744     }
7745     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7746      policyConstraintsWithInhibitMapping,
7747      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7748      NULL, &info, &size);
7749     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7750     if (ret)
7751     {
7752         ok(!info->fRequireExplicitPolicy,
7753          "expected require explicit = FALSE\n");
7754         ok(info->fInhibitPolicyMapping,
7755          "expected implicit mapping = TRUE\n");
7756         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7757          info->dwInhibitPolicyMappingSkipCerts);
7758         LocalFree(info);
7759     }
7760     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7761      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7762      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7763     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7764     if (ret)
7765     {
7766         ok(info->fRequireExplicitPolicy,
7767          "expected require explicit = TRUE\n");
7768         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7769          info->dwRequireExplicitPolicySkipCerts);
7770         ok(info->fInhibitPolicyMapping,
7771          "expected implicit mapping = TRUE\n");
7772         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7773          info->dwInhibitPolicyMappingSkipCerts);
7774         LocalFree(info);
7775     }
7776 }
7777
7778 /* Free *pInfo with HeapFree */
7779 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7780 {
7781     BOOL ret;
7782     DWORD size = 0;
7783     HCRYPTKEY key;
7784
7785     /* This crashes
7786     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7787      */
7788     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7789     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7790      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7791     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7792      &size);
7793     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7794      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7795     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7796      NULL, &size);
7797     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7798      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7799     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7800      0, NULL, NULL, &size);
7801     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7802      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7803     /* Test with no key */
7804     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7805      0, NULL, NULL, &size);
7806     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7807      GetLastError());
7808     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7809     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7810     if (ret)
7811     {
7812         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7813          NULL, 0, NULL, NULL, &size);
7814         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7815         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7816         if (*pInfo)
7817         {
7818             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7819              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7820             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7821              GetLastError());
7822             if (ret)
7823             {
7824                 /* By default (we passed NULL as the OID) the OID is
7825                  * szOID_RSA_RSA.
7826                  */
7827                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7828                  "Expected %s, got %s\n", szOID_RSA_RSA,
7829                  (*pInfo)->Algorithm.pszObjId);
7830             }
7831         }
7832     }
7833     CryptDestroyKey(key);
7834 }
7835
7836 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7837  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7838  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7839  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7840  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7841  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7842  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7843  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7844  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7845  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7846  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7847  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7848  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7849  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7850  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7851  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7852  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7853  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7854  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7855  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7856  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7857  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7858  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7859  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7860  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7861
7862 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7863 {
7864     BOOL ret;
7865     HCRYPTKEY key;
7866     PCCERT_CONTEXT context;
7867     DWORD dwSize;
7868     ALG_ID ai;
7869
7870     /* These crash
7871     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7872     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7873     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7874     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7875      NULL);
7876      */
7877     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7878     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7879      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7880     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7881     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7882      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7883     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7884      &key);
7885     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7886      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7887
7888     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7889     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7890      &key);
7891     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7892
7893     dwSize = sizeof(ai);
7894     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7895     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7896     if(ret)
7897     {
7898       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7899       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7900     }
7901
7902     CryptDestroyKey(key);
7903
7904     /* Repeat with forced algorithm */
7905     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7906      &key);
7907     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7908
7909     dwSize = sizeof(ai);
7910     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7911     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7912     if(ret)
7913     {
7914       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7915       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7916     }
7917
7918     CryptDestroyKey(key);
7919
7920     /* Test importing a public key from a certificate context */
7921     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7922      sizeof(expiredCert));
7923     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7924      GetLastError());
7925     if (context)
7926     {
7927         ok(!strcmp(szOID_RSA_RSA,
7928          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7929          "Expected %s, got %s\n", szOID_RSA_RSA,
7930          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7931         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7932          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7933         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7934         CryptDestroyKey(key);
7935         CertFreeCertificateContext(context);
7936     }
7937 }
7938
7939 static const char cspName[] = "WineCryptTemp";
7940
7941 static void testPortPublicKeyInfo(void)
7942 {
7943     HCRYPTPROV csp;
7944     BOOL ret;
7945     PCERT_PUBLIC_KEY_INFO info = NULL;
7946
7947     /* Just in case a previous run failed, delete this thing */
7948     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7949      CRYPT_DELETEKEYSET);
7950     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7951      CRYPT_NEWKEYSET);
7952
7953     testExportPublicKey(csp, &info);
7954     testImportPublicKey(csp, info);
7955
7956     HeapFree(GetProcessHeap(), 0, info);
7957     CryptReleaseContext(csp, 0);
7958     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7959      CRYPT_DELETEKEYSET);
7960 }
7961
7962 START_TEST(encode)
7963 {
7964     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7965      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7966     HMODULE hCrypt32;
7967     DWORD i;
7968
7969     hCrypt32 = GetModuleHandleA("crypt32.dll");
7970     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7971     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7972     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7973     {
7974         win_skip("CryptDecodeObjectEx() is not available\n");
7975         return;
7976     }
7977
7978     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7979     {
7980         test_encodeInt(encodings[i]);
7981         test_decodeInt(encodings[i]);
7982         test_encodeEnumerated(encodings[i]);
7983         test_decodeEnumerated(encodings[i]);
7984         test_encodeFiletime(encodings[i]);
7985         test_decodeFiletime(encodings[i]);
7986         test_encodeName(encodings[i]);
7987         test_decodeName(encodings[i]);
7988         test_encodeUnicodeName(encodings[i]);
7989         test_decodeUnicodeName(encodings[i]);
7990         test_encodeNameValue(encodings[i]);
7991         test_decodeNameValue(encodings[i]);
7992         test_encodeUnicodeNameValue(encodings[i]);
7993         test_decodeUnicodeNameValue(encodings[i]);
7994         test_encodeAltName(encodings[i]);
7995         test_decodeAltName(encodings[i]);
7996         test_encodeOctets(encodings[i]);
7997         test_decodeOctets(encodings[i]);
7998         test_encodeBits(encodings[i]);
7999         test_decodeBits(encodings[i]);
8000         test_encodeBasicConstraints(encodings[i]);
8001         test_decodeBasicConstraints(encodings[i]);
8002         test_encodeRsaPublicKey(encodings[i]);
8003         test_decodeRsaPublicKey(encodings[i]);
8004         test_encodeSequenceOfAny(encodings[i]);
8005         test_decodeSequenceOfAny(encodings[i]);
8006         test_encodeExtensions(encodings[i]);
8007         test_decodeExtensions(encodings[i]);
8008         test_encodePublicKeyInfo(encodings[i]);
8009         test_decodePublicKeyInfo(encodings[i]);
8010         test_encodeCertToBeSigned(encodings[i]);
8011         test_decodeCertToBeSigned(encodings[i]);
8012         test_encodeCert(encodings[i]);
8013         test_decodeCert(encodings[i]);
8014         test_encodeCRLDistPoints(encodings[i]);
8015         test_decodeCRLDistPoints(encodings[i]);
8016         test_encodeCRLIssuingDistPoint(encodings[i]);
8017         test_decodeCRLIssuingDistPoint(encodings[i]);
8018         test_encodeCRLToBeSigned(encodings[i]);
8019         test_decodeCRLToBeSigned(encodings[i]);
8020         test_encodeEnhancedKeyUsage(encodings[i]);
8021         test_decodeEnhancedKeyUsage(encodings[i]);
8022         test_encodeAuthorityKeyId(encodings[i]);
8023         test_decodeAuthorityKeyId(encodings[i]);
8024         test_encodeAuthorityKeyId2(encodings[i]);
8025         test_decodeAuthorityKeyId2(encodings[i]);
8026         test_encodeAuthorityInfoAccess(encodings[i]);
8027         test_decodeAuthorityInfoAccess(encodings[i]);
8028         test_encodeCTL(encodings[i]);
8029         test_decodeCTL(encodings[i]);
8030         test_encodePKCSContentInfo(encodings[i]);
8031         test_decodePKCSContentInfo(encodings[i]);
8032         test_encodePKCSAttribute(encodings[i]);
8033         test_decodePKCSAttribute(encodings[i]);
8034         test_encodePKCSAttributes(encodings[i]);
8035         test_decodePKCSAttributes(encodings[i]);
8036         test_encodePKCSSMimeCapabilities(encodings[i]);
8037         test_decodePKCSSMimeCapabilities(encodings[i]);
8038         test_encodePKCSSignerInfo(encodings[i]);
8039         test_decodePKCSSignerInfo(encodings[i]);
8040         test_encodeCMSSignerInfo(encodings[i]);
8041         test_decodeCMSSignerInfo(encodings[i]);
8042         test_encodeNameConstraints(encodings[i]);
8043         test_decodeNameConstraints(encodings[i]);
8044         test_encodePolicyQualifierUserNotice(encodings[i]);
8045         test_decodePolicyQualifierUserNotice(encodings[i]);
8046         test_encodeCertPolicies(encodings[i]);
8047         test_decodeCertPolicies(encodings[i]);
8048         test_encodeCertPolicyMappings(encodings[i]);
8049         test_decodeCertPolicyMappings(encodings[i]);
8050         test_encodeCertPolicyConstraints(encodings[i]);
8051         test_decodeCertPolicyConstraints(encodings[i]);
8052     }
8053     testPortPublicKeyInfo();
8054 }