crypt32: Add tests for encoding/decoding cert policy constraints.
[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
1268 static struct EncodedNameValue nameValues[] = {
1269  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1270      octetCommonNameValue, sizeof(octetCommonNameValue) },
1271  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1272      numericCommonNameValue, sizeof(numericCommonNameValue) },
1273  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1274      printableCommonNameValue, sizeof(printableCommonNameValue) },
1275  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1276      t61CommonNameValue, sizeof(t61CommonNameValue) },
1277  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1278      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1279  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1280      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1281  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1282      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1283  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1284      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1285  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1286      generalCommonNameValue, sizeof(generalCommonNameValue) },
1287  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1288      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1289  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1290      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1291  /* The following tests succeed under Windows, but really should fail,
1292   * they contain characters that are illegal for the encoding.  I'm
1293   * including them to justify my lazy encoding.
1294   */
1295  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1296      sizeof(bin42) },
1297  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1298      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1299  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1300      bin44, sizeof(bin44) },
1301 };
1302
1303 static void test_encodeNameValue(DWORD dwEncoding)
1304 {
1305     BYTE *buf = NULL;
1306     DWORD size = 0, i;
1307     BOOL ret;
1308     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1309
1310     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1311     value.Value.pbData = printableCommonNameValue;
1312     value.Value.cbData = sizeof(printableCommonNameValue);
1313     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1314      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1315     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1316     if (buf)
1317     {
1318         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1319          size);
1320         ok(!memcmp(buf, printableCommonNameValue, size),
1321          "Unexpected encoding\n");
1322         LocalFree(buf);
1323     }
1324     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1325     {
1326         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1327          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1328         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1329          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1330          nameValues[i].value.dwValueType, GetLastError());
1331         if (ret)
1332         {
1333             ok(size == nameValues[i].encodedSize,
1334              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1335             ok(!memcmp(buf, nameValues[i].encoded, size),
1336              "Got unexpected encoding\n");
1337             LocalFree(buf);
1338         }
1339     }
1340 }
1341
1342 static void test_decodeNameValue(DWORD dwEncoding)
1343 {
1344     int i;
1345     BYTE *buf = NULL;
1346     DWORD bufSize = 0;
1347     BOOL ret;
1348
1349     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1350     {
1351         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1352          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1353          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1354          &buf, &bufSize);
1355         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1356          nameValues[i].value.dwValueType, GetLastError());
1357         if (ret)
1358         {
1359             compareNameValues(&nameValues[i].value,
1360              (const CERT_NAME_VALUE *)buf);
1361             LocalFree(buf);
1362         }
1363     }
1364 }
1365
1366 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1367 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1368 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1369  'h','q','.','o','r','g',0 };
1370 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1371  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1372  0x6f, 0x72, 0x67 };
1373 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1374  0x575b, 0 };
1375 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1376 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1377  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1378 static const BYTE localhost[] = { 127, 0, 0, 1 };
1379 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1380  0x01 };
1381 static const unsigned char encodedCommonName[] = {
1382     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1383 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1384 static const BYTE encodedDirectoryName[] = {
1385 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1386 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1387
1388 static void test_encodeAltName(DWORD dwEncoding)
1389 {
1390     CERT_ALT_NAME_INFO info = { 0 };
1391     CERT_ALT_NAME_ENTRY entry = { 0 };
1392     BYTE *buf = NULL;
1393     DWORD size = 0;
1394     BOOL ret;
1395     char oid[] = "1.2.3";
1396
1397     /* Test with empty info */
1398     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1399      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1400     if (buf)
1401     {
1402         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1403         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1404         LocalFree(buf);
1405     }
1406     /* Test with an empty entry */
1407     info.cAltEntry = 1;
1408     info.rgAltEntry = &entry;
1409     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1410      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1411     ok(!ret && GetLastError() == E_INVALIDARG,
1412      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1413     /* Test with an empty pointer */
1414     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1415     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1416      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1417     if (buf)
1418     {
1419         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1420         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1421         LocalFree(buf);
1422     }
1423     /* Test with a real URL */
1424     U(entry).pwszURL = (LPWSTR)url;
1425     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1426      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1427     if (buf)
1428     {
1429         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1430         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1431         LocalFree(buf);
1432     }
1433     /* Now with the URL containing an invalid IA5 char */
1434     U(entry).pwszURL = (LPWSTR)nihongoURL;
1435     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1436      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1437     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1438      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1439     /* The first invalid character is at index 7 */
1440     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1441      "Expected invalid char at index 7, got %d\n",
1442      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1443     /* Now with the URL missing a scheme */
1444     U(entry).pwszURL = (LPWSTR)dnsName;
1445     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1446      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1447     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1448     if (buf)
1449     {
1450         /* This succeeds, but it shouldn't, so don't worry about conforming */
1451         LocalFree(buf);
1452     }
1453     /* Now with a DNS name */
1454     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1455     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1456      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1457     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1458     if (buf)
1459     {
1460         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1461         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1462         LocalFree(buf);
1463     }
1464     /* Test with an IP address */
1465     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1466     U(entry).IPAddress.cbData = sizeof(localhost);
1467     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1468     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1469      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1470     if (buf)
1471     {
1472         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1473         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1474         LocalFree(buf);
1475     }
1476     /* Test with OID */
1477     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1478     U(entry).pszRegisteredID = oid;
1479     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1480      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1481     if (buf)
1482     {
1483         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1484         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1485         LocalFree(buf);
1486     }
1487     /* Test with directory name */
1488     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1489     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1490     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1491     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1492      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1493     if (buf)
1494     {
1495         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1496         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1497         LocalFree(buf);
1498     }
1499 }
1500
1501 static void test_decodeAltName(DWORD dwEncoding)
1502 {
1503     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1504      0x00, 0x00, 0x01 };
1505     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1506      0x01 };
1507     BOOL ret;
1508     BYTE *buf = NULL;
1509     DWORD bufSize = 0;
1510     CERT_ALT_NAME_INFO *info;
1511
1512     /* Test some bogus ones first */
1513     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1514      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1515      NULL, &buf, &bufSize);
1516     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1517      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1518      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1519      GetLastError());
1520     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1521      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1522      &bufSize);
1523     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1524      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1525      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1526      GetLastError());
1527     /* Now expected cases */
1528     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1529      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1530     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1531     if (buf)
1532     {
1533         info = (CERT_ALT_NAME_INFO *)buf;
1534
1535         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1536          info->cAltEntry);
1537         LocalFree(buf);
1538     }
1539     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1540      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1541     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1542     if (buf)
1543     {
1544         info = (CERT_ALT_NAME_INFO *)buf;
1545
1546         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1547          info->cAltEntry);
1548         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1549          "Expected CERT_ALT_NAME_URL, got %d\n",
1550          info->rgAltEntry[0].dwAltNameChoice);
1551         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1552          "Expected empty URL\n");
1553         LocalFree(buf);
1554     }
1555     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1556      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1557     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1558     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1559      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1560     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1561     if (buf)
1562     {
1563         info = (CERT_ALT_NAME_INFO *)buf;
1564
1565         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1566          info->cAltEntry);
1567         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1568          "Expected CERT_ALT_NAME_URL, got %d\n",
1569          info->rgAltEntry[0].dwAltNameChoice);
1570         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1571         LocalFree(buf);
1572     }
1573     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1574      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1575     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1576     if (buf)
1577     {
1578         info = (CERT_ALT_NAME_INFO *)buf;
1579
1580         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1581          info->cAltEntry);
1582         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1583          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1584          info->rgAltEntry[0].dwAltNameChoice);
1585         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1586          "Unexpected DNS name\n");
1587         LocalFree(buf);
1588     }
1589     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1590      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1591     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1592     if (buf)
1593     {
1594         info = (CERT_ALT_NAME_INFO *)buf;
1595
1596         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1597          info->cAltEntry);
1598         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1599          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1600          info->rgAltEntry[0].dwAltNameChoice);
1601         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1602          "Unexpected IP address length %d\n",
1603           U(info->rgAltEntry[0]).IPAddress.cbData);
1604         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1605          sizeof(localhost)), "Unexpected IP address value\n");
1606         LocalFree(buf);
1607     }
1608     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1609      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1610     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1611     if (buf)
1612     {
1613         info = (CERT_ALT_NAME_INFO *)buf;
1614
1615         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1616          info->cAltEntry);
1617         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1618          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1619          info->rgAltEntry[0].dwAltNameChoice);
1620         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1621            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1622         LocalFree(buf);
1623     }
1624     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1625      encodedDirectoryName, sizeof(encodedDirectoryName),
1626      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1627     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1628     if (buf)
1629     {
1630         info = (CERT_ALT_NAME_INFO *)buf;
1631
1632         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1633          info->cAltEntry);
1634         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1635          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1636          info->rgAltEntry[0].dwAltNameChoice);
1637         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1638          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1639           U(info->rgAltEntry[0]).DirectoryName.cbData);
1640         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1641          encodedCommonName, sizeof(encodedCommonName)),
1642          "Unexpected directory name value\n");
1643         LocalFree(buf);
1644     }
1645 }
1646
1647 struct UnicodeExpectedError
1648 {
1649     DWORD   valueType;
1650     LPCWSTR str;
1651     DWORD   errorIndex;
1652     DWORD   error;
1653 };
1654
1655 static const WCHAR oneW[] = { '1',0 };
1656 static const WCHAR aW[] = { 'a',0 };
1657 static const WCHAR quoteW[] = { '"', 0 };
1658
1659 static struct UnicodeExpectedError unicodeErrors[] = {
1660  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1661  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1662  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1663  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1664  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1665  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1666 };
1667
1668 struct UnicodeExpectedResult
1669 {
1670     DWORD           valueType;
1671     LPCWSTR         str;
1672     CRYPT_DATA_BLOB encoded;
1673 };
1674
1675 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1676 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1677 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1678 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1679 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1680 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1681 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1682 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1683 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1684 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1685 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1686 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1687  0x5b };
1688 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1689  0x6f,0x5b };
1690 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1691  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1692 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1693  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1694
1695 static struct UnicodeExpectedResult unicodeResults[] = {
1696  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1697  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1698  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1699  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1700  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1701  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1702  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1703  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1704  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1705  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1706  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1707  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1708  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1709 };
1710
1711 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1712  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1713  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1714 };
1715
1716 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1717 {
1718     BYTE *buf = NULL;
1719     DWORD size = 0, i;
1720     BOOL ret;
1721     CERT_NAME_VALUE value;
1722
1723     if (0)
1724     {
1725         /* Crashes on win9x */
1726         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1727          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1728         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1729          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1730     }
1731     /* Have to have a string of some sort */
1732     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1733     value.Value.pbData = NULL;
1734     value.Value.cbData = 0;
1735     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1736      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1737     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1738      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1739     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1740     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1741      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1742     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1743      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1744     value.dwValueType = CERT_RDN_ANY_TYPE;
1745     value.Value.pbData = (LPBYTE)oneW;
1746     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1747      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1748     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1749      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1750     value.Value.cbData = sizeof(oneW);
1751     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1752      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1753     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1754      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1755     /* An encoded string with specified length isn't good enough either */
1756     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1757     value.Value.pbData = oneUniversal;
1758     value.Value.cbData = sizeof(oneUniversal);
1759     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1760      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1761     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1762      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1763     /* More failure checking */
1764     value.Value.cbData = 0;
1765     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1766     {
1767         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1768         value.dwValueType = unicodeErrors[i].valueType;
1769         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1770          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1771         ok(!ret && GetLastError() == unicodeErrors[i].error,
1772          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1773          unicodeErrors[i].error, GetLastError());
1774         ok(size == unicodeErrors[i].errorIndex,
1775          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1776          size);
1777     }
1778     /* cbData can be zero if the string is NULL-terminated */
1779     value.Value.cbData = 0;
1780     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1781     {
1782         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1783         value.dwValueType = unicodeResults[i].valueType;
1784         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1785          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1786         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1787          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1788         if (buf)
1789         {
1790             ok(size == unicodeResults[i].encoded.cbData,
1791              "Value type %d: expected size %d, got %d\n",
1792              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1793             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1794              "Value type %d: unexpected value\n", value.dwValueType);
1795             LocalFree(buf);
1796         }
1797     }
1798     /* These "encode," but they do so by truncating each unicode character
1799      * rather than properly encoding it.  Kept separate from the proper results,
1800      * because the encoded forms won't decode to their original strings.
1801      */
1802     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1803     {
1804         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1805         value.dwValueType = unicodeWeirdness[i].valueType;
1806         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1807          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1808         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1809         if (buf)
1810         {
1811             ok(size == unicodeWeirdness[i].encoded.cbData,
1812              "Value type %d: expected size %d, got %d\n",
1813              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1814             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1815              "Value type %d: unexpected value\n", value.dwValueType);
1816             LocalFree(buf);
1817         }
1818     }
1819 }
1820
1821 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1822 {
1823     if (n <= 0) return 0;
1824     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1825     return *str1 - *str2;
1826 }
1827
1828 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1829 {
1830     DWORD i;
1831
1832     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1833     {
1834         BYTE *buf = NULL;
1835         BOOL ret;
1836         DWORD size = 0;
1837
1838         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1839          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1840          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1841         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1842          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1843         if (ret && buf)
1844         {
1845             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1846
1847             ok(value->dwValueType == unicodeResults[i].valueType,
1848              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1849              value->dwValueType);
1850             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1851              value->Value.cbData / sizeof(WCHAR)),
1852              "Unexpected decoded value for index %d (value type %d)\n", i,
1853              unicodeResults[i].valueType);
1854             LocalFree(buf);
1855         }
1856     }
1857 }
1858
1859 struct encodedOctets
1860 {
1861     const BYTE *val;
1862     const BYTE *encoded;
1863 };
1864
1865 static const unsigned char bin46[] = { 'h','i',0 };
1866 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1867 static const unsigned char bin48[] = {
1868      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1869 static const unsigned char bin49[] = {
1870      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1871 static const unsigned char bin50[] = { 0 };
1872 static const unsigned char bin51[] = { 0x04,0x00,0 };
1873
1874 static const struct encodedOctets octets[] = {
1875     { bin46, bin47 },
1876     { bin48, bin49 },
1877     { bin50, bin51 },
1878 };
1879
1880 static void test_encodeOctets(DWORD dwEncoding)
1881 {
1882     CRYPT_DATA_BLOB blob;
1883     DWORD i;
1884
1885     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1886     {
1887         BYTE *buf = NULL;
1888         BOOL ret;
1889         DWORD bufSize = 0;
1890
1891         blob.cbData = strlen((const char*)octets[i].val);
1892         blob.pbData = (BYTE*)octets[i].val;
1893         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1894          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1895         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1896         if (buf)
1897         {
1898             ok(buf[0] == 4,
1899              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1900             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1901              buf[1], octets[i].encoded[1]);
1902             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1903              octets[i].encoded[1] + 1), "Got unexpected value\n");
1904             LocalFree(buf);
1905         }
1906     }
1907 }
1908
1909 static void test_decodeOctets(DWORD dwEncoding)
1910 {
1911     DWORD i;
1912
1913     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1914     {
1915         BYTE *buf = NULL;
1916         BOOL ret;
1917         DWORD bufSize = 0;
1918
1919         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1920          octets[i].encoded, octets[i].encoded[1] + 2,
1921          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1922         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1923         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1924          "Expected size >= %d, got %d\n",
1925            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1926         ok(buf != NULL, "Expected allocated buffer\n");
1927         if (buf)
1928         {
1929             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1930
1931             if (blob->cbData)
1932                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1933                  "Unexpected value\n");
1934             LocalFree(buf);
1935         }
1936     }
1937 }
1938
1939 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1940
1941 struct encodedBits
1942 {
1943     DWORD cUnusedBits;
1944     const BYTE *encoded;
1945     DWORD cbDecoded;
1946     const BYTE *decoded;
1947 };
1948
1949 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1950 static const unsigned char bin53[] = { 0xff,0xff };
1951 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1952 static const unsigned char bin55[] = { 0xff,0xfe };
1953 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1954 static const unsigned char bin57[] = { 0xfe };
1955 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1956
1957 static const struct encodedBits bits[] = {
1958     /* normal test cases */
1959     { 0, bin52, 2, bin53 },
1960     { 1, bin54, 2, bin55 },
1961     /* strange test case, showing cUnusedBits >= 8 is allowed */
1962     { 9, bin56, 1, bin57 },
1963 };
1964
1965 static void test_encodeBits(DWORD dwEncoding)
1966 {
1967     DWORD i;
1968
1969     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1970     {
1971         CRYPT_BIT_BLOB blob;
1972         BOOL ret;
1973         BYTE *buf = NULL;
1974         DWORD bufSize = 0;
1975
1976         blob.cbData = sizeof(bytesToEncode);
1977         blob.pbData = (BYTE *)bytesToEncode;
1978         blob.cUnusedBits = bits[i].cUnusedBits;
1979         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1980          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1981         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1982         if (buf)
1983         {
1984             ok(bufSize == bits[i].encoded[1] + 2,
1985              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
1986              bits[i].encoded[1] + 2);
1987             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1988              "%d: Unexpected value\n", i);
1989             LocalFree(buf);
1990         }
1991     }
1992 }
1993
1994 static void test_decodeBits(DWORD dwEncoding)
1995 {
1996     static const BYTE ber[] = "\x03\x02\x01\xff";
1997     static const BYTE berDecoded = 0xfe;
1998     DWORD i;
1999     BOOL ret;
2000     BYTE *buf = NULL;
2001     DWORD bufSize = 0;
2002
2003     /* normal cases */
2004     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2005     {
2006         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2007          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2008          &bufSize);
2009         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2010         if (buf)
2011         {
2012             CRYPT_BIT_BLOB *blob;
2013
2014             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2015                "Got unexpected size %d\n", bufSize);
2016             blob = (CRYPT_BIT_BLOB *)buf;
2017             ok(blob->cbData == bits[i].cbDecoded,
2018              "Got unexpected length %d, expected %d\n", blob->cbData,
2019              bits[i].cbDecoded);
2020             if (blob->cbData && bits[i].cbDecoded)
2021                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2022                  "Unexpected value\n");
2023             LocalFree(buf);
2024         }
2025     }
2026     /* special case: check that something that's valid in BER but not in DER
2027      * decodes successfully
2028      */
2029     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2030      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2031     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2032     if (buf)
2033     {
2034         CRYPT_BIT_BLOB *blob;
2035
2036         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2037            "Got unexpected size %d\n", bufSize);
2038         blob = (CRYPT_BIT_BLOB *)buf;
2039         ok(blob->cbData == sizeof(berDecoded),
2040            "Got unexpected length %d\n", blob->cbData);
2041         if (blob->cbData)
2042             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2043         LocalFree(buf);
2044     }
2045 }
2046
2047 struct Constraints2
2048 {
2049     CERT_BASIC_CONSTRAINTS2_INFO info;
2050     const BYTE *encoded;
2051 };
2052
2053 static const unsigned char bin59[] = { 0x30,0x00 };
2054 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2055 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2056 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2057 static const struct Constraints2 constraints2[] = {
2058  /* empty constraints */
2059  { { FALSE, FALSE, 0}, bin59 },
2060  /* can be a CA */
2061  { { TRUE,  FALSE, 0}, bin60 },
2062  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2063   * but that's not the case
2064   */
2065  { { FALSE, TRUE,  0}, bin61 },
2066  /* can be a CA and has path length constraints set */
2067  { { TRUE,  TRUE,  1}, bin62 },
2068 };
2069
2070 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2071 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2072  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2073  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2074  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2075 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2076  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2077  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2078  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2079  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2080
2081 static void test_encodeBasicConstraints(DWORD dwEncoding)
2082 {
2083     DWORD i, bufSize = 0;
2084     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2085     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2086      (LPBYTE)encodedDomainName };
2087     BOOL ret;
2088     BYTE *buf = NULL;
2089
2090     /* First test with the simpler info2 */
2091     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2092     {
2093         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2094          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2095          &bufSize);
2096         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2097         if (buf)
2098         {
2099             ok(bufSize == constraints2[i].encoded[1] + 2,
2100              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2101              bufSize);
2102             ok(!memcmp(buf, constraints2[i].encoded,
2103              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2104             LocalFree(buf);
2105         }
2106     }
2107     /* Now test with more complex basic constraints */
2108     info.SubjectType.cbData = 0;
2109     info.fPathLenConstraint = FALSE;
2110     info.cSubtreesConstraint = 0;
2111     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2112      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2113     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2114      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2115     if (buf)
2116     {
2117         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2118         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2119          "Unexpected value\n");
2120         LocalFree(buf);
2121     }
2122     /* None of the certs I examined had any subtree constraint, but I test one
2123      * anyway just in case.
2124      */
2125     info.cSubtreesConstraint = 1;
2126     info.rgSubtreesConstraint = &nameBlob;
2127     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2128      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2129     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2130      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2131     if (buf)
2132     {
2133         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2134         ok(!memcmp(buf, constraintWithDomainName,
2135          sizeof(constraintWithDomainName)), "Unexpected value\n");
2136         LocalFree(buf);
2137     }
2138     /* FIXME: test encoding with subject type. */
2139 }
2140
2141 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2142
2143 static void test_decodeBasicConstraints(DWORD dwEncoding)
2144 {
2145     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2146      0xff };
2147     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2148     DWORD i;
2149     BOOL ret;
2150     BYTE *buf = NULL;
2151     DWORD bufSize = 0;
2152
2153     /* First test with simpler info2 */
2154     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2155     {
2156         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2157          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2158          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2159         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2160          GetLastError());
2161         if (buf)
2162         {
2163             CERT_BASIC_CONSTRAINTS2_INFO *info =
2164              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2165
2166             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2167              "Unexpected value for item %d\n", i);
2168             LocalFree(buf);
2169         }
2170     }
2171     /* Check with the order of encoded elements inverted */
2172     buf = (PBYTE)1;
2173     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2174      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2175      &bufSize);
2176     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2177      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2178      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2179      GetLastError());
2180     ok(!buf, "Expected buf to be set to NULL\n");
2181     /* Check with a non-DER bool */
2182     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2183      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2184      &buf, &bufSize);
2185     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2186     if (buf)
2187     {
2188         CERT_BASIC_CONSTRAINTS2_INFO *info =
2189          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2190
2191         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2192         LocalFree(buf);
2193     }
2194     /* Check with a non-basic constraints value */
2195     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196      encodedCommonName, encodedCommonName[1] + 2,
2197      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2198     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2199      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2200      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2201      GetLastError());
2202     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2203     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2204      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2205      &buf, &bufSize);
2206     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2207     if (buf)
2208     {
2209         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2210
2211         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2212         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2213         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2214         LocalFree(buf);
2215     }
2216     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2217      constraintWithDomainName, sizeof(constraintWithDomainName),
2218      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2219     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2220     if (buf)
2221     {
2222         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2223
2224         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2225         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2226         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2227         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2228         {
2229             ok(info->rgSubtreesConstraint[0].cbData ==
2230              sizeof(encodedDomainName), "Wrong size %d\n",
2231              info->rgSubtreesConstraint[0].cbData);
2232             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2233              sizeof(encodedDomainName)), "Unexpected value\n");
2234         }
2235         LocalFree(buf);
2236     }
2237 }
2238
2239 /* These are terrible public keys of course, I'm just testing encoding */
2240 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2241 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2242 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2243 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2244 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2245 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2246 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2247 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2248
2249 struct EncodedRSAPubKey
2250 {
2251     const BYTE *modulus;
2252     size_t modulusLen;
2253     const BYTE *encoded;
2254     size_t decodedModulusLen;
2255 };
2256
2257 struct EncodedRSAPubKey rsaPubKeys[] = {
2258     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2259     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2260     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2261     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2262 };
2263
2264 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2265 {
2266     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2267     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2268     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2269     BOOL ret;
2270     BYTE *buf = NULL;
2271     DWORD bufSize = 0, i;
2272
2273     /* Try with a bogus blob type */
2274     hdr->bType = 2;
2275     hdr->bVersion = CUR_BLOB_VERSION;
2276     hdr->reserved = 0;
2277     hdr->aiKeyAlg = CALG_RSA_KEYX;
2278     rsaPubKey->magic = 0x31415352;
2279     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2280     rsaPubKey->pubexp = 65537;
2281     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2282      sizeof(modulus1));
2283
2284     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2285      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2286     ok(!ret && GetLastError() == E_INVALIDARG,
2287      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2288     /* Now with a bogus reserved field */
2289     hdr->bType = PUBLICKEYBLOB;
2290     hdr->reserved = 1;
2291     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2292      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2293     if (buf)
2294     {
2295         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2296          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2297         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2298         LocalFree(buf);
2299     }
2300     /* Now with a bogus blob version */
2301     hdr->reserved = 0;
2302     hdr->bVersion = 0;
2303     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2304      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2305     if (buf)
2306     {
2307         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2308          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2309         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2310         LocalFree(buf);
2311     }
2312     /* And with a bogus alg ID */
2313     hdr->bVersion = CUR_BLOB_VERSION;
2314     hdr->aiKeyAlg = CALG_DES;
2315     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2316      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2317     if (buf)
2318     {
2319         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2320          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2321         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2322         LocalFree(buf);
2323     }
2324     /* Check a couple of RSA-related OIDs */
2325     hdr->aiKeyAlg = CALG_RSA_KEYX;
2326     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2327      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2328     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2329      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2330     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2331      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2332     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2333      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2334     /* Finally, all valid */
2335     hdr->aiKeyAlg = CALG_RSA_KEYX;
2336     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2337     {
2338         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2339          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2340         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2341          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2342         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2343         if (buf)
2344         {
2345             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2346              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2347              bufSize);
2348             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2349              "Unexpected value\n");
2350             LocalFree(buf);
2351         }
2352     }
2353 }
2354
2355 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2356 {
2357     DWORD i;
2358     LPBYTE buf = NULL;
2359     DWORD bufSize = 0;
2360     BOOL ret;
2361
2362     /* Try with a bad length */
2363     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2364      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2365      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2366     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2367      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2368      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2369      GetLastError());
2370     /* Try with a couple of RSA-related OIDs */
2371     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2372      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2373      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2374     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2375      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2376     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2377      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2378      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2379     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2380      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2381     /* Now try success cases */
2382     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2383     {
2384         bufSize = 0;
2385         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2386          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2387          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2389         if (buf)
2390         {
2391             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2392             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2393
2394             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2395              rsaPubKeys[i].decodedModulusLen,
2396              "Wrong size %d\n", bufSize);
2397             ok(hdr->bType == PUBLICKEYBLOB,
2398              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2399              hdr->bType);
2400             ok(hdr->bVersion == CUR_BLOB_VERSION,
2401              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2402              CUR_BLOB_VERSION, hdr->bVersion);
2403             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2404              hdr->reserved);
2405             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2406              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2407             ok(rsaPubKey->magic == 0x31415352,
2408              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2409             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2410              "Wrong bit len %d\n", rsaPubKey->bitlen);
2411             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2412              rsaPubKey->pubexp);
2413             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2414              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2415              "Unexpected modulus\n");
2416             LocalFree(buf);
2417         }
2418     }
2419 }
2420
2421 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2422  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2423  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2424
2425 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2426  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2427  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2428  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2429
2430 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2431 {
2432     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2433     CRYPT_SEQUENCE_OF_ANY seq;
2434     DWORD i;
2435     BOOL ret;
2436     BYTE *buf = NULL;
2437     DWORD bufSize = 0;
2438
2439     /* Encode a homogeneous sequence */
2440     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2441     {
2442         blobs[i].cbData = ints[i].encoded[1] + 2;
2443         blobs[i].pbData = (BYTE *)ints[i].encoded;
2444     }
2445     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2446     seq.rgValue = blobs;
2447
2448     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2449      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2450     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2451     if (buf)
2452     {
2453         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2454         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2455         LocalFree(buf);
2456     }
2457     /* Change the type of the first element in the sequence, and give it
2458      * another go
2459      */
2460     blobs[0].cbData = times[0].encodedTime[1] + 2;
2461     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2462     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2463      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2464     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2465     if (buf)
2466     {
2467         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2468         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2469          "Unexpected value\n");
2470         LocalFree(buf);
2471     }
2472 }
2473
2474 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2475 {
2476     BOOL ret;
2477     BYTE *buf = NULL;
2478     DWORD bufSize = 0;
2479
2480     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2481      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2482     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2483     if (buf)
2484     {
2485         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2486         DWORD i;
2487
2488         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2489          "Wrong elements %d\n", seq->cValue);
2490         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2491         {
2492             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2493              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2494              seq->rgValue[i].cbData);
2495             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2496              ints[i].encoded[1] + 2), "Unexpected value\n");
2497         }
2498         LocalFree(buf);
2499     }
2500     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2501      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2502      &bufSize);
2503     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2504     if (buf)
2505     {
2506         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2507
2508         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2509          "Wrong elements %d\n", seq->cValue);
2510         /* Just check the first element since it's all that changed */
2511         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2512          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2513          seq->rgValue[0].cbData);
2514         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2515          times[0].encodedTime[1] + 2), "Unexpected value\n");
2516         LocalFree(buf);
2517     }
2518 }
2519
2520 struct encodedExtensions
2521 {
2522     CERT_EXTENSIONS exts;
2523     const BYTE *encoded;
2524 };
2525
2526 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2527 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2528 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2529 static CERT_EXTENSION criticalExt =
2530  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2531 static CERT_EXTENSION nonCriticalExt =
2532  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2533 static CHAR oid_short[] = "1.1";
2534 static CERT_EXTENSION extWithShortOid =
2535  { oid_short, FALSE, { 0, NULL } };
2536
2537 static const BYTE ext0[] = { 0x30,0x00 };
2538 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2539                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2540 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2541                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2542 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2543
2544 static const struct encodedExtensions exts[] = {
2545  { { 0, NULL }, ext0 },
2546  { { 1, &criticalExt }, ext1 },
2547  { { 1, &nonCriticalExt }, ext2 },
2548  { { 1, &extWithShortOid }, ext3 }
2549 };
2550
2551 static void test_encodeExtensions(DWORD dwEncoding)
2552 {
2553     DWORD i;
2554
2555     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2556     {
2557         BOOL ret;
2558         BYTE *buf = NULL;
2559         DWORD bufSize = 0;
2560
2561         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2562          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2563         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2564         if (buf)
2565         {
2566             ok(bufSize == exts[i].encoded[1] + 2,
2567              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2568             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2569              "Unexpected value\n");
2570             LocalFree(buf);
2571         }
2572     }
2573 }
2574
2575 static void test_decodeExtensions(DWORD dwEncoding)
2576 {
2577     DWORD i;
2578
2579     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2580     {
2581         BOOL ret;
2582         BYTE *buf = NULL;
2583         DWORD bufSize = 0;
2584
2585         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2586          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2587          NULL, &buf, &bufSize);
2588         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2589         if (buf)
2590         {
2591             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2592             DWORD j;
2593
2594             ok(ext->cExtension == exts[i].exts.cExtension,
2595              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2596              ext->cExtension);
2597             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2598             {
2599                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2600                  exts[i].exts.rgExtension[j].pszObjId),
2601                  "Expected OID %s, got %s\n",
2602                  exts[i].exts.rgExtension[j].pszObjId,
2603                  ext->rgExtension[j].pszObjId);
2604                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2605                  exts[i].exts.rgExtension[j].Value.pbData,
2606                  exts[i].exts.rgExtension[j].Value.cbData),
2607                  "Unexpected value\n");
2608             }
2609             LocalFree(buf);
2610         }
2611     }
2612 }
2613
2614 /* MS encodes public key info with a NULL if the algorithm identifier's
2615  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2616  * it encodes them by omitting the algorithm parameters.  It accepts either
2617  * form for decoding.
2618  */
2619 struct encodedPublicKey
2620 {
2621     CERT_PUBLIC_KEY_INFO info;
2622     const BYTE *encoded;
2623     const BYTE *encodedNoNull;
2624     CERT_PUBLIC_KEY_INFO decoded;
2625 };
2626
2627 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2628  0xe, 0xf };
2629 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2630
2631 static const unsigned char bin64[] = {
2632     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2633 static const unsigned char bin65[] = {
2634     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2635 static const unsigned char bin66[] = {
2636     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2637 static const unsigned char bin67[] = {
2638     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2639 static const unsigned char bin68[] = {
2640     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2641     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2642 static const unsigned char bin69[] = {
2643     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2644     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2645 static const unsigned char bin70[] = {
2646     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2647     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2648     0x0f};
2649 static const unsigned char bin71[] = {
2650     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2651     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2652     0x0f};
2653 static unsigned char bin72[] = { 0x05,0x00};
2654
2655 static CHAR oid_bogus[] = "1.2.3",
2656             oid_rsa[]   = szOID_RSA;
2657
2658 static const struct encodedPublicKey pubKeys[] = {
2659  /* with a bogus OID */
2660  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2661   bin64, bin65,
2662   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2663  /* some normal keys */
2664  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2665   bin66, bin67,
2666   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2667  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2668   bin68, bin69,
2669   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2670  /* with add'l parameters--note they must be DER-encoded */
2671  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2672   (BYTE *)aKey, 0 } },
2673   bin70, bin71,
2674   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2675   (BYTE *)aKey, 0 } } },
2676 };
2677
2678 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2679 {
2680     DWORD i;
2681
2682     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2683     {
2684         BOOL ret;
2685         BYTE *buf = NULL;
2686         DWORD bufSize = 0;
2687
2688         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2689          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2690          &bufSize);
2691         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2692          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2693         if (buf)
2694         {
2695             ok(bufSize == pubKeys[i].encoded[1] + 2,
2696              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2697             if (bufSize == pubKeys[i].encoded[1] + 2)
2698                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2699                  "Unexpected value\n");
2700             LocalFree(buf);
2701         }
2702     }
2703 }
2704
2705 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2706  const CERT_PUBLIC_KEY_INFO *got)
2707 {
2708     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2709      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2710      got->Algorithm.pszObjId);
2711     ok(expected->Algorithm.Parameters.cbData ==
2712      got->Algorithm.Parameters.cbData,
2713      "Expected parameters of %d bytes, got %d\n",
2714      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2715     if (expected->Algorithm.Parameters.cbData)
2716         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2717          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2718          "Unexpected algorithm parameters\n");
2719     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2720      "Expected public key of %d bytes, got %d\n",
2721      expected->PublicKey.cbData, got->PublicKey.cbData);
2722     if (expected->PublicKey.cbData)
2723         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2724          got->PublicKey.cbData), "Unexpected public key value\n");
2725 }
2726
2727 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2728 {
2729     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2730      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2731      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2732      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2733     DWORD i;
2734     BOOL ret;
2735     BYTE *buf = NULL;
2736     DWORD bufSize = 0;
2737
2738     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2739     {
2740         /* The NULL form decodes to the decoded member */
2741         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2742          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2743          NULL, &buf, &bufSize);
2744         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2745         if (buf)
2746         {
2747             comparePublicKeyInfo(&pubKeys[i].decoded,
2748              (CERT_PUBLIC_KEY_INFO *)buf);
2749             LocalFree(buf);
2750         }
2751         /* The non-NULL form decodes to the original */
2752         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2753          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2754          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2755         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2756         if (buf)
2757         {
2758             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2759             LocalFree(buf);
2760         }
2761     }
2762     /* Test with bogus (not valid DER) parameters */
2763     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2764      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2765      NULL, &buf, &bufSize);
2766     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2767      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2768      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2769      GetLastError());
2770 }
2771
2772 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2773  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2774  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2775  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2776  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2777 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2778  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2779  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2780  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2781  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2782 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2783  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2784  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2785  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2786  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2787 static const BYTE v4Cert[] = {
2788 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2789 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2790 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2791 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2792 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2793  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2794  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2795  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2796  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2797  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2798  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2799 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2800  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2801  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2802  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2803  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2804  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2805  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2806 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2807  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2808  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2809  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2810  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2811  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2812  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2813  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2814  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2815  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2816 static const BYTE v1CertWithPubKey[] = {
2817 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2818 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2819 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2820 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2821 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2822 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2823 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2824 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2825 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2826 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2827 0x01,0x01 };
2828 static const BYTE v1CertWithPubKeyNoNull[] = {
2829 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2830 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2831 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2832 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2833 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2834 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2835 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2836 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2837 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2838 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2839 static const BYTE v1CertWithSubjectKeyId[] = {
2840 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2841 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2842 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2843 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2844 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2845 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2846 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2847 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2848 0x4c,0x61,0x6e,0x67,0x00 };
2849 static const BYTE v1CertWithIssuerUniqueId[] = {
2850 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2851 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2852 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2853 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2854 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2855 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2856 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2857 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2858 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2859 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2860 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2861 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2862 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2863 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2864 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2865 0x01,0x01,0xff,0x02,0x01,0x01 };
2866 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2867 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2868 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2869 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2870 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2871 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2872 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2873 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2874 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2875 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2876 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2877 0xff,0x02,0x01,0x01 };
2878
2879 static const BYTE serialNum[] = { 0x01 };
2880
2881 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2882 {
2883     BOOL ret;
2884     BYTE *buf = NULL;
2885     DWORD size = 0;
2886     CERT_INFO info = { 0 };
2887     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2888     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2889     CERT_EXTENSION ext;
2890
2891     if (0)
2892     {
2893         /* Test with NULL pvStructInfo (crashes on win9x) */
2894         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2895          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2896         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2897          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2898     }
2899     /* Test with a V1 cert */
2900     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2901      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2902     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2903      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2904     if (buf)
2905     {
2906         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2907          v1Cert[1] + 2, size);
2908         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2909         LocalFree(buf);
2910     }
2911     /* Test v2 cert */
2912     info.dwVersion = CERT_V2;
2913     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2914      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2915     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2916      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2917     if (buf)
2918     {
2919         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2920         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2921         LocalFree(buf);
2922     }
2923     /* Test v3 cert */
2924     info.dwVersion = CERT_V3;
2925     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2926      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2927     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2928      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2929     if (buf)
2930     {
2931         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2932         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2933         LocalFree(buf);
2934     }
2935     /* A v4 cert? */
2936     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
2937     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2938      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2939     if (buf)
2940     {
2941         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
2942         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
2943         LocalFree(buf);
2944     }
2945     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2946      * API doesn't prevent it)
2947      */
2948     info.dwVersion = CERT_V1;
2949     info.cExtension = 1;
2950     info.rgExtension = &criticalExt;
2951     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2952      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2953     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2954      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2955     if (buf)
2956     {
2957         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2958         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2959         LocalFree(buf);
2960     }
2961     /* test v1 cert with a serial number */
2962     info.SerialNumber.cbData = sizeof(serialNum);
2963     info.SerialNumber.pbData = (BYTE *)serialNum;
2964     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2965      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2966     if (buf)
2967     {
2968         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2969         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2970         LocalFree(buf);
2971     }
2972     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
2973     info.dwVersion = CERT_V1;
2974     info.cExtension = 0;
2975     info.IssuerUniqueId.cbData = sizeof(serialNum);
2976     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
2977     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2978      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2979     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2980     if (buf)
2981     {
2982         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
2983         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
2984          "Got unexpected value\n");
2985         LocalFree(buf);
2986     }
2987     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2988     info.IssuerUniqueId.cbData = 0;
2989     info.IssuerUniqueId.pbData = NULL;
2990     info.cExtension = 1;
2991     info.rgExtension = &criticalExt;
2992     info.Issuer.cbData = sizeof(encodedCommonName);
2993     info.Issuer.pbData = (BYTE *)encodedCommonName;
2994     info.Subject.cbData = sizeof(encodedCommonName);
2995     info.Subject.pbData = (BYTE *)encodedCommonName;
2996     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2997      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2998     if (buf)
2999     {
3000         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3001         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3002         LocalFree(buf);
3003     }
3004     /* Add a public key */
3005     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3006     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3007     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3008     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3009      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3010     if (buf)
3011     {
3012         ok(size == sizeof(v1CertWithPubKey) ||
3013          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3014         if (size == sizeof(v1CertWithPubKey))
3015             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3016         else if (size == sizeof(v1CertWithPubKeyNoNull))
3017             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3018              "Got unexpected value\n");
3019         LocalFree(buf);
3020     }
3021     /* Again add an issuer unique id */
3022     info.IssuerUniqueId.cbData = sizeof(serialNum);
3023     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3024     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3025      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3026     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3027     if (buf)
3028     {
3029         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3030          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3031          "Wrong size %d\n", size);
3032         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3033             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3034              size), "unexpected value\n");
3035         else if (size ==
3036          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3037             ok(!memcmp(buf,
3038              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3039              "unexpected value\n");
3040         LocalFree(buf);
3041     }
3042     /* Remove the public key, and add a subject key identifier extension */
3043     info.IssuerUniqueId.cbData = 0;
3044     info.IssuerUniqueId.pbData = NULL;
3045     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3046     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3047     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3048     ext.pszObjId = oid_subject_key_identifier;
3049     ext.fCritical = FALSE;
3050     ext.Value.cbData = sizeof(octetCommonNameValue);
3051     ext.Value.pbData = octetCommonNameValue;
3052     info.cExtension = 1;
3053     info.rgExtension = &ext;
3054     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3055      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3056     if (buf)
3057     {
3058         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3059         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3060         LocalFree(buf);
3061     }
3062 }
3063
3064 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3065 {
3066     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3067      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3068     BOOL ret;
3069     BYTE *buf = NULL;
3070     DWORD size = 0, i;
3071
3072     /* Test with NULL pbEncoded */
3073     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3074      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3075     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3076      GetLastError() == OSS_BAD_ARG /* Win9x */),
3077      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3078     if (0)
3079     {
3080         /* Crashes on win9x */
3081         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3082          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3083         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3084          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3085     }
3086     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3087      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3088      * serial number, an issuer, a subject, and a public key.
3089      */
3090     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3091     {
3092         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3093          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3094          &buf, &size);
3095         ok(!ret, "Expected failure\n");
3096     }
3097     /* The following succeeds, even though v1 certs are not allowed to have
3098      * extensions.
3099      */
3100     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3101      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3102      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3103     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3104     if (ret)
3105     {
3106         CERT_INFO *info = (CERT_INFO *)buf;
3107
3108         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3109         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3110          info->dwVersion);
3111         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3112          info->cExtension);
3113         LocalFree(buf);
3114     }
3115     /* The following also succeeds, even though V1 certs are not allowed to
3116      * have issuer unique ids.
3117      */
3118     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3119      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3120      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3121      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3122     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3123     if (ret)
3124     {
3125         CERT_INFO *info = (CERT_INFO *)buf;
3126
3127         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3128         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3129          info->dwVersion);
3130         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3131          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3132         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3133          "unexpected issuer unique id value\n");
3134         LocalFree(buf);
3135     }
3136     /* Now check with serial number, subject and issuer specified */
3137     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3138      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3139     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3140     if (buf)
3141     {
3142         CERT_INFO *info = (CERT_INFO *)buf;
3143
3144         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3145         ok(info->SerialNumber.cbData == 1,
3146          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3147         ok(*info->SerialNumber.pbData == *serialNum,
3148          "Expected serial number %d, got %d\n", *serialNum,
3149          *info->SerialNumber.pbData);
3150         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3151          "Wrong size %d\n", info->Issuer.cbData);
3152         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3153          "Unexpected issuer\n");
3154         ok(info->Subject.cbData == sizeof(encodedCommonName),
3155          "Wrong size %d\n", info->Subject.cbData);
3156         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3157          info->Subject.cbData), "Unexpected subject\n");
3158         LocalFree(buf);
3159     }
3160     /* Check again with pub key specified */
3161     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3162      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3163      &buf, &size);
3164     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3165     if (buf)
3166     {
3167         CERT_INFO *info = (CERT_INFO *)buf;
3168
3169         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3170         ok(info->SerialNumber.cbData == 1,
3171          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3172         ok(*info->SerialNumber.pbData == *serialNum,
3173          "Expected serial number %d, got %d\n", *serialNum,
3174          *info->SerialNumber.pbData);
3175         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3176          "Wrong size %d\n", info->Issuer.cbData);
3177         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3178          "Unexpected issuer\n");
3179         ok(info->Subject.cbData == sizeof(encodedCommonName),
3180          "Wrong size %d\n", info->Subject.cbData);
3181         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3182          info->Subject.cbData), "Unexpected subject\n");
3183         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3184          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3185          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3186         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3187          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3188         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3189          sizeof(aKey)), "Unexpected public key\n");
3190         LocalFree(buf);
3191     }
3192 }
3193
3194 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3195  0xe, 0xf };
3196
3197 static const BYTE signedBigCert[] = {
3198  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3199  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3200  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3201  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3202  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3203  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3204  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3205  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3206  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3207  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3208  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3209  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3210
3211 static void test_encodeCert(DWORD dwEncoding)
3212 {
3213     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3214      * also that bigCert is a NULL-terminated string, so don't count its
3215      * last byte (otherwise the signed cert won't decode.)
3216      */
3217     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3218      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3219     BOOL ret;
3220     BYTE *buf = NULL;
3221     DWORD bufSize = 0;
3222
3223     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3224      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3225     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3226     if (buf)
3227     {
3228         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3229         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3230         LocalFree(buf);
3231     }
3232 }
3233
3234 static void test_decodeCert(DWORD dwEncoding)
3235 {
3236     BOOL ret;
3237     BYTE *buf = NULL;
3238     DWORD size = 0;
3239
3240     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3241      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3242     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3243     if (buf)
3244     {
3245         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3246
3247         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3248          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3249         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3250          "Unexpected cert\n");
3251         ok(info->Signature.cbData == sizeof(hash),
3252          "Wrong signature size %d\n", info->Signature.cbData);
3253         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3254          "Unexpected signature\n");
3255         LocalFree(buf);
3256     }
3257     /* A signed cert decodes as a CERT_INFO too */
3258     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3259      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3260     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3261     if (buf)
3262     {
3263         CERT_INFO *info = (CERT_INFO *)buf;
3264
3265         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3266         ok(info->SerialNumber.cbData == 1,
3267          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3268         ok(*info->SerialNumber.pbData == *serialNum,
3269          "Expected serial number %d, got %d\n", *serialNum,
3270          *info->SerialNumber.pbData);
3271         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3272          "Wrong size %d\n", info->Issuer.cbData);
3273         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3274          "Unexpected issuer\n");
3275         ok(info->Subject.cbData == sizeof(encodedCommonName),
3276          "Wrong size %d\n", info->Subject.cbData);
3277         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3278          info->Subject.cbData), "Unexpected subject\n");
3279         LocalFree(buf);
3280     }
3281 }
3282
3283 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3284 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3285  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3286  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3287 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3288  0x00, 0x03 };
3289 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3290  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3291  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3292 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3293  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3294  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3295  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3296  0x2e, 0x6f, 0x72, 0x67 };
3297 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3298  CRL_REASON_AFFILIATION_CHANGED;
3299
3300 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3301 {
3302     CRL_DIST_POINTS_INFO info = { 0 };
3303     CRL_DIST_POINT point = { { 0 } };
3304     CERT_ALT_NAME_ENTRY entry = { 0 };
3305     BOOL ret;
3306     BYTE *buf = NULL;
3307     DWORD size = 0;
3308
3309     /* Test with an empty info */
3310     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3311      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3312     ok(!ret && GetLastError() == E_INVALIDARG,
3313      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3314     /* Test with one empty dist point */
3315     info.cDistPoint = 1;
3316     info.rgDistPoint = &point;
3317     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3318      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3319     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3320     if (buf)
3321     {
3322         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3323         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3324         LocalFree(buf);
3325     }
3326     /* A dist point with an invalid name */
3327     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3328     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3329     U(entry).pwszURL = (LPWSTR)nihongoURL;
3330     U(point.DistPointName).FullName.cAltEntry = 1;
3331     U(point.DistPointName).FullName.rgAltEntry = &entry;
3332     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3333      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3334     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3335      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3336     /* The first invalid character is at index 7 */
3337     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3338      "Expected invalid char at index 7, got %d\n",
3339      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3340     /* A dist point with (just) a valid name */
3341     U(entry).pwszURL = (LPWSTR)url;
3342     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3343      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3344     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3345     if (buf)
3346     {
3347         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3348         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3349         LocalFree(buf);
3350     }
3351     /* A dist point with (just) reason flags */
3352     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3353     point.ReasonFlags.cbData = sizeof(crlReason);
3354     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3355     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3356      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3357     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3358     if (buf)
3359     {
3360         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3361         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3362         LocalFree(buf);
3363     }
3364     /* A dist point with just an issuer */
3365     point.ReasonFlags.cbData = 0;
3366     point.CRLIssuer.cAltEntry = 1;
3367     point.CRLIssuer.rgAltEntry = &entry;
3368     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3369      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3370     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3371     if (buf)
3372     {
3373         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3374         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3375         LocalFree(buf);
3376     }
3377     /* A dist point with both a name and an issuer */
3378     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3379     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3380      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3381     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3382     if (buf)
3383     {
3384         ok(size == sizeof(distPointWithUrlAndIssuer),
3385          "Wrong size %d\n", size);
3386         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3387         LocalFree(buf);
3388     }
3389 }
3390
3391 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3392 {
3393     BOOL ret;
3394     BYTE *buf = NULL;
3395     DWORD size = 0;
3396     PCRL_DIST_POINTS_INFO info;
3397     PCRL_DIST_POINT point;
3398     PCERT_ALT_NAME_ENTRY entry;
3399
3400     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3401      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3402      &buf, &size);
3403     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3404     if (ret)
3405     {
3406         info = (PCRL_DIST_POINTS_INFO)buf;
3407         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3408          "Wrong size %d\n", size);
3409         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3410          info->cDistPoint);
3411         point = info->rgDistPoint;
3412         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3413          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3414          point->DistPointName.dwDistPointNameChoice);
3415         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3416         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3417         LocalFree(buf);
3418     }
3419     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3420      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3421      &buf, &size);
3422     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3423     if (ret)
3424     {
3425         info = (PCRL_DIST_POINTS_INFO)buf;
3426         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3427          "Wrong size %d\n", size);
3428         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3429          info->cDistPoint);
3430         point = info->rgDistPoint;
3431         ok(point->DistPointName.dwDistPointNameChoice ==
3432          CRL_DIST_POINT_FULL_NAME,
3433          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3434          point->DistPointName.dwDistPointNameChoice);
3435         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3436          "Expected 1 name entry, got %d\n",
3437          U(point->DistPointName).FullName.cAltEntry);
3438         entry = U(point->DistPointName).FullName.rgAltEntry;
3439         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3440          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3441         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3442         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3443         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3444         LocalFree(buf);
3445     }
3446     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3447      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3448      NULL, &buf, &size);
3449     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3450     if (ret)
3451     {
3452         info = (PCRL_DIST_POINTS_INFO)buf;
3453         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3454          "Wrong size %d\n", size);
3455         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3456          info->cDistPoint);
3457         point = info->rgDistPoint;
3458         ok(point->DistPointName.dwDistPointNameChoice ==
3459          CRL_DIST_POINT_NO_NAME,
3460          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3461          point->DistPointName.dwDistPointNameChoice);
3462         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3463          "Expected reason length\n");
3464         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3465          "Unexpected reason\n");
3466         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3467         LocalFree(buf);
3468     }
3469     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3470      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3471      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3472     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3473     if (ret)
3474     {
3475         info = (PCRL_DIST_POINTS_INFO)buf;
3476         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3477          "Wrong size %d\n", size);
3478         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3479          info->cDistPoint);
3480         point = info->rgDistPoint;
3481         ok(point->DistPointName.dwDistPointNameChoice ==
3482          CRL_DIST_POINT_FULL_NAME,
3483          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3484          point->DistPointName.dwDistPointNameChoice);
3485         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3486          "Expected 1 name entry, got %d\n",
3487          U(point->DistPointName).FullName.cAltEntry);
3488         entry = U(point->DistPointName).FullName.rgAltEntry;
3489         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3490          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3491         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3492         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3493         ok(point->CRLIssuer.cAltEntry == 1,
3494          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3495         entry = point->CRLIssuer.rgAltEntry;
3496         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3497          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3498         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3499         LocalFree(buf);
3500     }
3501 }
3502
3503 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3504 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3505 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3506  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3507  0x67 };
3508
3509 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3510 {
3511     BOOL ret;
3512     BYTE *buf = NULL;
3513     DWORD size = 0;
3514     CRL_ISSUING_DIST_POINT point = { { 0 } };
3515     CERT_ALT_NAME_ENTRY entry;
3516
3517     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3518      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3519     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3520     {
3521         skip("no X509_ISSUING_DIST_POINT encode support\n");
3522         return;
3523     }
3524     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3525      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3526     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3527      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3528     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3529     if (buf)
3530     {
3531         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3532         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3533         LocalFree(buf);
3534     }
3535     /* nonsensical flags */
3536     point.fOnlyContainsUserCerts = TRUE;
3537     point.fOnlyContainsCACerts = TRUE;
3538     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3539      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3540     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3541     if (buf)
3542     {
3543         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3544         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3545         LocalFree(buf);
3546     }
3547     /* unimplemented name type */
3548     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3549     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3550     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3551      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3552     ok(!ret && GetLastError() == E_INVALIDARG,
3553      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3554     /* empty name */
3555     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3556     U(point.DistPointName).FullName.cAltEntry = 0;
3557     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3558      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3559     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3560     if (buf)
3561     {
3562         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3563         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3564         LocalFree(buf);
3565     }
3566     /* name with URL entry */
3567     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3568     U(entry).pwszURL = (LPWSTR)url;
3569     U(point.DistPointName).FullName.cAltEntry = 1;
3570     U(point.DistPointName).FullName.rgAltEntry = &entry;
3571     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3572      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3573     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3574     if (buf)
3575     {
3576         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3577         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3578         LocalFree(buf);
3579     }
3580 }
3581
3582 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3583  const CERT_ALT_NAME_ENTRY *got)
3584 {
3585     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3586      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3587      got->dwAltNameChoice);
3588     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3589     {
3590         switch (got->dwAltNameChoice)
3591         {
3592         case CERT_ALT_NAME_RFC822_NAME:
3593         case CERT_ALT_NAME_DNS_NAME:
3594         case CERT_ALT_NAME_EDI_PARTY_NAME:
3595         case CERT_ALT_NAME_URL:
3596         case CERT_ALT_NAME_REGISTERED_ID:
3597             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3598              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3599              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3600              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3601              "Unexpected name\n");
3602             break;
3603         case CERT_ALT_NAME_X400_ADDRESS:
3604         case CERT_ALT_NAME_DIRECTORY_NAME:
3605         case CERT_ALT_NAME_IP_ADDRESS:
3606             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3607                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3608             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3609                        U(*got).IPAddress.cbData), "Unexpected value\n");
3610             break;
3611         }
3612     }
3613 }
3614
3615 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3616  const CERT_ALT_NAME_INFO *got)
3617 {
3618     DWORD i;
3619
3620     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3621      expected->cAltEntry, got->cAltEntry);
3622     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3623         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3624 }
3625
3626 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3627  const CRL_DIST_POINT_NAME *got)
3628 {
3629     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3630      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3631     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3632         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3633 }
3634
3635 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3636  const CRL_ISSUING_DIST_POINT *got)
3637 {
3638     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3639     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3640      "Unexpected fOnlyContainsUserCerts\n");
3641     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3642      "Unexpected fOnlyContainsCACerts\n");
3643     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3644      "Unexpected reason flags\n");
3645     ok(got->fIndirectCRL == expected->fIndirectCRL,
3646      "Unexpected fIndirectCRL\n");
3647 }
3648
3649 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3650 {
3651     BOOL ret;
3652     BYTE *buf = NULL;
3653     DWORD size = 0;
3654     CRL_ISSUING_DIST_POINT point = { { 0 } };
3655
3656     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3657      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3658      &buf, &size);
3659     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3660     {
3661         skip("no X509_ISSUING_DIST_POINT decode support\n");
3662         return;
3663     }
3664     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3665     if (ret)
3666     {
3667         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3668         LocalFree(buf);
3669     }
3670     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3671      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3672      &buf, &size);
3673     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3674     if (ret)
3675     {
3676         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3677         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3678         LocalFree(buf);
3679     }
3680     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3681      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3682      &buf, &size);
3683     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3684     if (ret)
3685     {
3686         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3687         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3688         U(point.DistPointName).FullName.cAltEntry = 0;
3689         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3690         LocalFree(buf);
3691     }
3692     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3693      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3694     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3695     if (ret)
3696     {
3697         CERT_ALT_NAME_ENTRY entry;
3698
3699         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3700         U(entry).pwszURL = (LPWSTR)url;
3701         U(point.DistPointName).FullName.cAltEntry = 1;
3702         U(point.DistPointName).FullName.rgAltEntry = &entry;
3703         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3704         LocalFree(buf);
3705     }
3706 }
3707
3708 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3709  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3710  0x30, 0x5a };
3711 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3712  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3713  0x30, 0x30, 0x30, 0x30, 0x5a };
3714 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3715  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3716  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3717  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3718  0x5a };
3719 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3720  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3721  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3722  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3723  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3724  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3725 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3726  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3727  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3728  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3729  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3730  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3731 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3732  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3733  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3734  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3735  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3736  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3737  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3738 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3739  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3740  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3741  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3742  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3743  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3744  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3745 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3746  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3747  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3748  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3749  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3750  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3751  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3752 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3753  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3754  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3755  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3756  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3757  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3758  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3759
3760 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3761 {
3762     BOOL ret;
3763     BYTE *buf = NULL;
3764     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3765     DWORD size = 0;
3766     CRL_INFO info = { 0 };
3767     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3768     CERT_EXTENSION ext;
3769
3770     /* Test with a V1 CRL */
3771     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3772      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3773     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3774      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3775     if (buf)
3776     {
3777         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3778         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3779         LocalFree(buf);
3780     }
3781     /* Test v2 CRL */
3782     info.dwVersion = CRL_V2;
3783     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3784      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3785     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3786      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3787     if (buf)
3788     {
3789         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3790          v2CRL[1] + 2, size);
3791         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3792         LocalFree(buf);
3793     }
3794     /* v1 CRL with a name */
3795     info.dwVersion = CRL_V1;
3796     info.Issuer.cbData = sizeof(encodedCommonName);
3797     info.Issuer.pbData = (BYTE *)encodedCommonName;
3798     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3799      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3800     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3801     if (buf)
3802     {
3803         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3804         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3805         LocalFree(buf);
3806     }
3807     if (0)
3808     {
3809         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3810         info.cCRLEntry = 1;
3811         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3812          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3813         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3814          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3815     }
3816     /* now set an empty entry */
3817     info.cCRLEntry = 1;
3818     info.rgCRLEntry = &entry;
3819     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3820      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3821     if (buf)
3822     {
3823         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3824          "Wrong size %d\n", size);
3825         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3826          "Got unexpected value\n");
3827         LocalFree(buf);
3828     }
3829     /* an entry with a serial number */
3830     entry.SerialNumber.cbData = sizeof(serialNum);
3831     entry.SerialNumber.pbData = (BYTE *)serialNum;
3832     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3833      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3834     if (buf)
3835     {
3836         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3837          "Wrong size %d\n", size);
3838         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3839          "Got unexpected value\n");
3840         LocalFree(buf);
3841     }
3842     /* an entry with an extension */
3843     entry.cExtension = 1;
3844     entry.rgExtension = &criticalExt;
3845     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3846      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3847     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3848     if (buf)
3849     {
3850         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3851         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3852         LocalFree(buf);
3853     }
3854     /* a CRL with an extension */
3855     entry.cExtension = 0;
3856     info.cExtension = 1;
3857     info.rgExtension = &criticalExt;
3858     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3859      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3860     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3861     if (buf)
3862     {
3863         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3864         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3865         LocalFree(buf);
3866     }
3867     /* a v2 CRL with an extension, this time non-critical */
3868     info.dwVersion = CRL_V2;
3869     info.rgExtension = &nonCriticalExt;
3870     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3871      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3872     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3873     if (buf)
3874     {
3875         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3876         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3877         LocalFree(buf);
3878     }
3879     /* a v2 CRL with an issuing dist point extension */
3880     ext.pszObjId = oid_issuing_dist_point;
3881     ext.fCritical = TRUE;
3882     ext.Value.cbData = sizeof(urlIDP);
3883     ext.Value.pbData = (LPBYTE)urlIDP;
3884     entry.rgExtension = &ext;
3885     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3886      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3887     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3888     if (buf)
3889     {
3890         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3891         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3892         LocalFree(buf);
3893     }
3894 }
3895
3896 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3897  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3898  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3899  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3900  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3901  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3902  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3903  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3904  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3905  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3906  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3907  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3908  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3909  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3910  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3911  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3912  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3913  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3914  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3915  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3916  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3917  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3918  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3919  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3920  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3921  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3922  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3923  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3924  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3925  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3926  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3927  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3928  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3929  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3930  0xcd };
3931 static const BYTE verisignCRLWithLotsOfEntries[] = {
3932 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3933 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3934 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3935 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3936 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3937 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3938 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3939 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3940 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3941 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3942 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3943 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3944 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3945 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3946 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3947 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3948 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3949 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3950 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3951 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3952 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3953 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3954 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3955 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3956 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3957 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3958 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3959 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3960 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3961 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3962 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3963 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3964 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3965 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3966 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3967 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3968 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3969 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3970 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3971 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3972 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3973 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3974 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3975 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3976 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3977 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3978 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3979 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3980 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3981 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3982 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3983 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3984 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3985 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3986 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3987 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3988 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3989 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3990 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3991 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3992 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3993 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3994 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3995 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3996 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3997 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3998 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3999 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4000 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4001 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4002 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4003 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4004 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4005 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4006 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4007 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4008 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4009 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4010 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4011 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4012 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4013 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4014 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4015 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4016 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4017 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4018 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4019 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4020 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4021 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4022 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4023 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4024 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4025 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4026 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4027 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4028 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4029 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4030 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4031 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4032 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4033 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4034 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4035 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4036 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4037 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4038 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4039 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4040 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4041 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4042 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4043 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4044 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4045 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4046 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4047 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4048 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4049 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4050 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4051 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4052 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4053 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4054 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4055 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4056 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4057 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4058 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4059 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4060 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4061 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4062 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4063 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4064 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4065 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4066 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4067 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4068 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4069 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4070 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4071 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4072 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4073 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4074 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4075 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4076 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4077 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4078 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4079 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4080 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4081 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4082 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4083 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4084 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4085 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4086 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4087 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4088 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4089 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4090 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4091 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4092 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4093 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4094 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4095 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4096 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4097 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4098 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4099 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4100 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4101 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4102 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4103 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4104 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4105 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4106 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4107 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4108 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4109 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4110 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4111 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4112 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4113 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4114 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4115 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4116 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4117 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4118 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4119 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4120 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4121 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4122 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4123 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4124 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4125 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4126 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4127 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4128 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4129 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4130 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4131 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4132 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4133 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4134 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4135 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4136 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4137 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4138 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4139 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4140 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4141 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4142 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4143 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4144 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4145 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4146 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4147 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4148 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4149 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4150 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4151 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4152 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4153 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4154 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4155 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4156 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4157 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4158 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4159 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4160 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4161 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4162 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4163 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4164 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4165 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4166 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4167 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4168 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4169 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4170 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4171 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4172 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4173 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4174 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4175 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4176 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4177 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4178 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4179 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4180 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4181 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4182 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4183 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4184 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4185 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4186 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4187 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4188 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4189 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4190 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4191 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4192 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4193 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4194 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4195 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4196 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4197 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4198 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4199 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4200 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4201 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4202 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4203 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4204 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4205 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4206 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4207 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4208 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4209 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4210 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4211 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4212 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4213 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4214 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4215 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4216 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4217 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4218 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4219 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4220 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4221 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4222 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4223 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4224 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4225 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4226 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4227 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4228 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4229 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4230 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4231 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4232 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4233 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4234 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4235 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4236 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4237 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4238 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4239 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4240 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4241 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4242 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4243 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4244 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4245 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4246 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4247 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4248 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4249 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4250 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4251 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4252 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4253 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4254 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4255 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4256 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4257 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4258 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4259 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4260 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4261 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4262 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4263 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4264 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4265 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4266 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4267 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4268 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4269 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4270 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4271 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4272 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4273 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4274 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4275 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4276 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4277 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4278 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4279 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4280 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4281 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4282 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4283 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4284 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4285 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4286 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4287 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4288 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4289 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4290 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4291 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4292 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4293 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4294 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4295 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4296 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4297 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4298 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4299 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4300 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4301 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4302 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4303 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4304 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4305 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4306 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4307 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4308 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4309 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4310 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4311 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4312 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4313 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4314 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4315 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4316 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4317 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4318 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4319 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4320 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4321 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4322 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4323 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4324 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4325 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4326 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4327 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4328 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4329 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4330 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4331 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4332 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4333 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4334 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4335 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4336 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4337 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4338 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4339 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4340 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4341 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4342 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4343 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4344 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4345 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4346 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4347 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4348 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4349 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4350 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4351 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4352 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4353 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4354 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4355 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4356 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4357 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4358 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4359 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4360 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4361 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4362 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4363 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4364 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4365 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4366 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4367 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4368 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4369 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4370 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4371 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4372 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4373 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4374 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4375 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4376 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4377 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4378 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4379 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4380 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4381 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4382 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4383 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4384 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4385 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4386 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4387 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4388 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4389 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4390 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4391 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4392 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4393 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4394 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4395 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4396 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4397 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4398 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4399 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4400 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4401 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4402 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4403 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4404 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4405 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4406 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4407 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4408 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4409 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4410 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4411 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4412 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4413 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4414 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4415 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4416 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4417 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4418 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4419 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4420 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4421 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4422 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4423 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4424 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4425 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4426 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4427 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4428 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4429 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4430 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4431 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4432 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4433 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4434 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4435 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4436 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4437 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4438 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4439 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4440
4441 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4442 {
4443     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4444     BOOL ret;
4445     BYTE *buf = NULL;
4446     DWORD size = 0, i;
4447
4448     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4449     {
4450         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4451          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4452          &buf, &size);
4453         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4454          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4455          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4456          GetLastError());
4457     }
4458     /* at a minimum, a CRL must contain an issuer: */
4459     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4460      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4461      &buf, &size);
4462     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4463     if (buf)
4464     {
4465         CRL_INFO *info = (CRL_INFO *)buf;
4466
4467         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4468         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4469          info->cCRLEntry);
4470         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4471          "Wrong issuer size %d\n", info->Issuer.cbData);
4472         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4473          "Unexpected issuer\n");
4474         LocalFree(buf);
4475     }
4476     /* check decoding with an empty CRL entry */
4477     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4478      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4479      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4480     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4481      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4482      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4483      GetLastError());
4484     /* with a real CRL entry */
4485     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4486      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4487      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4488     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4489     if (buf)
4490     {
4491         CRL_INFO *info = (CRL_INFO *)buf;
4492         CRL_ENTRY *entry;
4493
4494         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4495         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4496          info->cCRLEntry);
4497         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4498         entry = info->rgCRLEntry;
4499         ok(entry->SerialNumber.cbData == 1,
4500          "Expected serial number size 1, got %d\n",
4501          entry->SerialNumber.cbData);
4502         ok(*entry->SerialNumber.pbData == *serialNum,
4503          "Expected serial number %d, got %d\n", *serialNum,
4504          *entry->SerialNumber.pbData);
4505         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4506          "Wrong issuer size %d\n", info->Issuer.cbData);
4507         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4508          "Unexpected issuer\n");
4509         LocalFree(buf);
4510     }
4511     /* a real CRL from verisign that has extensions */
4512     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4513      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4514      NULL, &buf, &size);
4515     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4516     if (buf)
4517     {
4518         CRL_INFO *info = (CRL_INFO *)buf;
4519         CRL_ENTRY *entry;
4520
4521         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4522         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4523          info->cCRLEntry);
4524         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4525         entry = info->rgCRLEntry;
4526         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4527          info->cExtension);
4528         LocalFree(buf);
4529     }
4530     /* another real CRL from verisign that has lots of entries */
4531     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4532      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4533      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4534     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4535     if (buf)
4536     {
4537         CRL_INFO *info = (CRL_INFO *)buf;
4538
4539         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4540         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4541          info->cCRLEntry);
4542         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4543          info->cExtension);
4544         LocalFree(buf);
4545     }
4546     /* and finally, with an extension */
4547     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4548      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4549      NULL, &buf, &size);
4550     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4551     if (buf)
4552     {
4553         CRL_INFO *info = (CRL_INFO *)buf;
4554         CRL_ENTRY *entry;
4555
4556         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4557         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4558          info->cCRLEntry);
4559         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4560         entry = info->rgCRLEntry;
4561         ok(entry->SerialNumber.cbData == 1,
4562          "Expected serial number size 1, got %d\n",
4563          entry->SerialNumber.cbData);
4564         ok(*entry->SerialNumber.pbData == *serialNum,
4565          "Expected serial number %d, got %d\n", *serialNum,
4566          *entry->SerialNumber.pbData);
4567         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4568          "Wrong issuer size %d\n", info->Issuer.cbData);
4569         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4570          "Unexpected issuer\n");
4571         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4572          info->cExtension);
4573         LocalFree(buf);
4574     }
4575     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4576      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4577      NULL, &buf, &size);
4578     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4579     if (buf)
4580     {
4581         CRL_INFO *info = (CRL_INFO *)buf;
4582
4583         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4584          info->cExtension);
4585         LocalFree(buf);
4586     }
4587     /* And again, with an issuing dist point */
4588     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4589      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4590      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4591     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4592     if (buf)
4593     {
4594         CRL_INFO *info = (CRL_INFO *)buf;
4595
4596         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4597          info->cExtension);
4598         LocalFree(buf);
4599     }
4600 }
4601
4602 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4603  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4604 static const BYTE encodedUsage[] = {
4605  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4606  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4607  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4608
4609 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4610 {
4611     BOOL ret;
4612     BYTE *buf = NULL;
4613     DWORD size = 0;
4614     CERT_ENHKEY_USAGE usage;
4615
4616     /* Test with empty usage */
4617     usage.cUsageIdentifier = 0;
4618     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4619      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4620     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4621     if (buf)
4622     {
4623         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4624         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4625         LocalFree(buf);
4626     }
4627     /* Test with a few usages */
4628     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4629     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4630     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4631      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4632     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4633     if (buf)
4634     {
4635         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4636         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4637         LocalFree(buf);
4638     }
4639 }
4640
4641 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4642 {
4643     BOOL ret;
4644     LPBYTE buf = NULL;
4645     DWORD size = 0;
4646
4647     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4648      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4649      &buf, &size);
4650     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4651     if (buf)
4652     {
4653         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4654
4655         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4656          "Wrong size %d\n", size);
4657         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4658          usage->cUsageIdentifier);
4659         LocalFree(buf);
4660     }
4661     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4662      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4663      &buf, &size);
4664     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4665     if (buf)
4666     {
4667         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4668         DWORD i;
4669
4670         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4671          "Wrong size %d\n", size);
4672         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4673          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4674         for (i = 0; i < usage->cUsageIdentifier; i++)
4675             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4676              "Expected OID %s, got %s\n", keyUsages[i],
4677              usage->rgpszUsageIdentifier[i]);
4678         LocalFree(buf);
4679     }
4680 }
4681
4682 static BYTE keyId[] = { 1,2,3,4 };
4683 static const BYTE authorityKeyIdWithId[] = {
4684  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4685 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4686  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4687  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4688 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4689
4690 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4691 {
4692     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4693     BOOL ret;
4694     BYTE *buf = NULL;
4695     DWORD size = 0;
4696
4697     /* Test with empty id */
4698     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4699      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4700     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4701     if (buf)
4702     {
4703         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4704         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4705         LocalFree(buf);
4706     }
4707     /* With just a key id */
4708     info.KeyId.cbData = sizeof(keyId);
4709     info.KeyId.pbData = keyId;
4710     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4711      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4712     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4713     if (buf)
4714     {
4715         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4716         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4717         LocalFree(buf);
4718     }
4719     /* With just an issuer */
4720     info.KeyId.cbData = 0;
4721     info.CertIssuer.cbData = sizeof(encodedCommonName);
4722     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4723     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4724      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4725     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4726     if (buf)
4727     {
4728         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4729          size);
4730         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4731         LocalFree(buf);
4732     }
4733     /* With just a serial number */
4734     info.CertIssuer.cbData = 0;
4735     info.CertSerialNumber.cbData = sizeof(serialNum);
4736     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4737     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4738      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4739     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4740     if (buf)
4741     {
4742         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4743          size);
4744         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4745         LocalFree(buf);
4746     }
4747 }
4748
4749 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4750 {
4751     BOOL ret;
4752     LPBYTE buf = NULL;
4753     DWORD size = 0;
4754
4755     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4756      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4757      &buf, &size);
4758     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4759     if (buf)
4760     {
4761         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4762
4763         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4764          size);
4765         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4766         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4767         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4768         LocalFree(buf);
4769     }
4770     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4771      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4772      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4773     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4774     if (buf)
4775     {
4776         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4777
4778         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4779          size);
4780         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4781         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4782          "Unexpected key id\n");
4783         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4784         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4785         LocalFree(buf);
4786     }
4787     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4788      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4789      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4790     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4791     if (buf)
4792     {
4793         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4794
4795         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4796          size);
4797         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4798         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4799          "Unexpected issuer len\n");
4800         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4801          sizeof(encodedCommonName)), "Unexpected issuer\n");
4802         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4803         LocalFree(buf);
4804     }
4805     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4806      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4807      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4808     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4809     if (buf)
4810     {
4811         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4812
4813         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4814          size);
4815         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4816         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4817         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4818          "Unexpected serial number len\n");
4819         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4820          "Unexpected serial number\n");
4821         LocalFree(buf);
4822     }
4823 }
4824
4825 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4826  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4827  0x6f,0x72,0x67 };
4828
4829 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4830 {
4831     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4832     CERT_ALT_NAME_ENTRY entry = { 0 };
4833     BOOL ret;
4834     BYTE *buf = NULL;
4835     DWORD size = 0;
4836
4837     /* Test with empty id */
4838     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4839      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4840     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4841     if (buf)
4842     {
4843         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4844         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4845         LocalFree(buf);
4846     }
4847     /* With just a key id */
4848     info.KeyId.cbData = sizeof(keyId);
4849     info.KeyId.pbData = keyId;
4850     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4851      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4852     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4853     if (buf)
4854     {
4855         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4856          size);
4857         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4858         LocalFree(buf);
4859     }
4860     /* With a bogus issuer name */
4861     info.KeyId.cbData = 0;
4862     info.AuthorityCertIssuer.cAltEntry = 1;
4863     info.AuthorityCertIssuer.rgAltEntry = &entry;
4864     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4865      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4866     ok(!ret && GetLastError() == E_INVALIDARG,
4867      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4868     /* With an issuer name */
4869     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4870     U(entry).pwszURL = (LPWSTR)url;
4871     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4872      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4873     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4874     if (buf)
4875     {
4876         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4877          size);
4878         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4879          "Unexpected value\n");
4880         LocalFree(buf);
4881     }
4882     /* With just a serial number */
4883     info.AuthorityCertIssuer.cAltEntry = 0;
4884     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4885     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4886     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4887      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4888     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4889     if (buf)
4890     {
4891         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4892          size);
4893         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4894         LocalFree(buf);
4895     }
4896 }
4897
4898 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4899 {
4900     BOOL ret;
4901     LPBYTE buf = NULL;
4902     DWORD size = 0;
4903
4904     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4905      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4906      &buf, &size);
4907     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4908     if (buf)
4909     {
4910         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4911
4912         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4913          size);
4914         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4915         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4916          "Expected no issuer name entries\n");
4917         ok(info->AuthorityCertSerialNumber.cbData == 0,
4918          "Expected no serial number\n");
4919         LocalFree(buf);
4920     }
4921     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4922      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4923      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4924     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4925     if (buf)
4926     {
4927         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4928
4929         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4930          size);
4931         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4932         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4933          "Unexpected key id\n");
4934         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4935          "Expected no issuer name entries\n");
4936         ok(info->AuthorityCertSerialNumber.cbData == 0,
4937          "Expected no serial number\n");
4938         LocalFree(buf);
4939     }
4940     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4941      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4942      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4943     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4944     if (buf)
4945     {
4946         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4947
4948         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4949          size);
4950         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4951         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4952          "Expected 1 issuer entry, got %d\n",
4953          info->AuthorityCertIssuer.cAltEntry);
4954         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4955          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4956          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4957         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4958          url), "Unexpected URL\n");
4959         ok(info->AuthorityCertSerialNumber.cbData == 0,
4960          "Expected no serial number\n");
4961         LocalFree(buf);
4962     }
4963     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4964      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4965      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4966     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4967     if (buf)
4968     {
4969         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4970
4971         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4972          size);
4973         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4974         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4975          "Expected no issuer name entries\n");
4976         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4977          "Unexpected serial number len\n");
4978         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4979          sizeof(serialNum)), "Unexpected serial number\n");
4980         LocalFree(buf);
4981     }
4982 }
4983
4984 static const BYTE authorityInfoAccessWithUrl[] = {
4985 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4986 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4987 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4988 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4989 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4990 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4991
4992 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4993 {
4994     static char oid1[] = "1.2.3";
4995     static char oid2[] = "1.5.6";
4996     BOOL ret;
4997     BYTE *buf = NULL;
4998     DWORD size = 0;
4999     CERT_ACCESS_DESCRIPTION accessDescription[2];
5000     CERT_AUTHORITY_INFO_ACCESS aia;
5001
5002     memset(accessDescription, 0, sizeof(accessDescription));
5003     aia.cAccDescr = 0;
5004     aia.rgAccDescr = NULL;
5005     /* Having no access descriptions is allowed */
5006     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5007      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5008     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5009     if (buf)
5010     {
5011         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5012         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5013         LocalFree(buf);
5014         buf = NULL;
5015     }
5016     /* It can't have an empty access method */
5017     aia.cAccDescr = 1;
5018     aia.rgAccDescr = accessDescription;
5019     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5020      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5021     ok(!ret && (GetLastError() == E_INVALIDARG ||
5022      GetLastError() == OSS_LIMITED /* Win9x */),
5023      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5024     /* It can't have an empty location */
5025     accessDescription[0].pszAccessMethod = oid1;
5026     SetLastError(0xdeadbeef);
5027     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5028      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5029     ok(!ret && GetLastError() == E_INVALIDARG,
5030      "expected E_INVALIDARG, got %08x\n", GetLastError());
5031     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5032     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5033     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5034      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5035     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5036     if (buf)
5037     {
5038         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5039          size);
5040         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5041          "unexpected value\n");
5042         LocalFree(buf);
5043         buf = NULL;
5044     }
5045     accessDescription[1].pszAccessMethod = oid2;
5046     accessDescription[1].AccessLocation.dwAltNameChoice =
5047      CERT_ALT_NAME_IP_ADDRESS;
5048     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5049      sizeof(encodedIPAddr);
5050     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5051      (LPBYTE)encodedIPAddr;
5052     aia.cAccDescr = 2;
5053     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5054      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5055     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5056     if (buf)
5057     {
5058         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5059          "unexpected size %d\n", size);
5060         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5061          "unexpected value\n");
5062         LocalFree(buf);
5063         buf = NULL;
5064     }
5065 }
5066
5067 static void compareAuthorityInfoAccess(LPCSTR header,
5068  const CERT_AUTHORITY_INFO_ACCESS *expected,
5069  const CERT_AUTHORITY_INFO_ACCESS *got)
5070 {
5071     DWORD i;
5072
5073     ok(expected->cAccDescr == got->cAccDescr,
5074      "%s: expected %d access descriptions, got %d\n", header,
5075      expected->cAccDescr, got->cAccDescr);
5076     for (i = 0; i < expected->cAccDescr; i++)
5077     {
5078         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5079          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5080          header, i, expected->rgAccDescr[i].pszAccessMethod,
5081          got->rgAccDescr[i].pszAccessMethod);
5082         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5083          &got->rgAccDescr[i].AccessLocation);
5084     }
5085 }
5086
5087 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5088 {
5089     static char oid1[] = "1.2.3";
5090     static char oid2[] = "1.5.6";
5091     BOOL ret;
5092     LPBYTE buf = NULL;
5093     DWORD size = 0;
5094
5095     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5096      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5097      &buf, &size);
5098     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5099     if (buf)
5100     {
5101         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5102
5103         compareAuthorityInfoAccess("empty AIA", &aia,
5104          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5105         LocalFree(buf);
5106         buf = NULL;
5107     }
5108     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5109      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5110      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5111     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5112     if (buf)
5113     {
5114         CERT_ACCESS_DESCRIPTION accessDescription;
5115         CERT_AUTHORITY_INFO_ACCESS aia;
5116
5117         accessDescription.pszAccessMethod = oid1;
5118         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5119         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5120         aia.cAccDescr = 1;
5121         aia.rgAccDescr = &accessDescription;
5122         compareAuthorityInfoAccess("AIA with URL", &aia,
5123          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5124         LocalFree(buf);
5125         buf = NULL;
5126     }
5127     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5128      authorityInfoAccessWithUrlAndIPAddr,
5129      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5130      NULL, &buf, &size);
5131     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5132     if (buf)
5133     {
5134         CERT_ACCESS_DESCRIPTION accessDescription[2];
5135         CERT_AUTHORITY_INFO_ACCESS aia;
5136
5137         accessDescription[0].pszAccessMethod = oid1;
5138         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5139         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5140         accessDescription[1].pszAccessMethod = oid2;
5141         accessDescription[1].AccessLocation.dwAltNameChoice =
5142          CERT_ALT_NAME_IP_ADDRESS;
5143         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5144          sizeof(encodedIPAddr);
5145         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5146          (LPBYTE)encodedIPAddr;
5147         aia.cAccDescr = 2;
5148         aia.rgAccDescr = accessDescription;
5149         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5150          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5151         LocalFree(buf);
5152         buf = NULL;
5153     }
5154 }
5155
5156 static const BYTE emptyCTL[] = {
5157 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5158 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5159 static const BYTE emptyCTLWithVersion1[] = {
5160 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5161 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5162 static const BYTE ctlWithUsageIdentifier[] = {
5163 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5164 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5165 static const BYTE ctlWithListIdentifier[] = {
5166 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5167 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5168 static const BYTE ctlWithSequenceNumber[] = {
5169 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5170 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5171 static const BYTE ctlWithThisUpdate[] = {
5172 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5173 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5174 static const BYTE ctlWithThisAndNextUpdate[] = {
5175 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5176 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5177 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5178 static const BYTE ctlWithAlgId[] = {
5179 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5180 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5181 static const BYTE ctlWithBogusEntry[] = {
5182 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5183 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5184 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5185 static const BYTE ctlWithOneEntry[] = {
5186 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5187 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5188 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5189 static const BYTE ctlWithTwoEntries[] = {
5190 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5191 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5192 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5193 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5194 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5195
5196 static void test_encodeCTL(DWORD dwEncoding)
5197 {
5198     static char oid1[] = "1.2.3";
5199     static char oid2[] = "1.5.6";
5200     char *pOid1 = oid1;
5201     BOOL ret;
5202     BYTE *buf = NULL;
5203     DWORD size = 0;
5204     CTL_INFO info;
5205     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5206     CTL_ENTRY ctlEntry[2];
5207     CRYPT_ATTRIBUTE attr1, attr2;
5208     CRYPT_ATTR_BLOB value1, value2;
5209
5210     memset(&info, 0, sizeof(info));
5211     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5212      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5213     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5214     if (buf)
5215     {
5216         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5217         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5218         LocalFree(buf);
5219         buf = NULL;
5220     }
5221     info.dwVersion = 1;
5222     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5223      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5224     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5225     if (buf)
5226     {
5227         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5228         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5229         LocalFree(buf);
5230         buf = NULL;
5231     }
5232     info.dwVersion = 0;
5233     info.SubjectUsage.cUsageIdentifier = 1;
5234     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5235     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5236      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5237     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5238     if (buf)
5239     {
5240         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5241          size);
5242         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5243         LocalFree(buf);
5244         buf = NULL;
5245     }
5246     info.SubjectUsage.cUsageIdentifier = 0;
5247     info.ListIdentifier.cbData = sizeof(serialNum);
5248     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5249     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5250      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5251     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5252     if (buf)
5253     {
5254         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5255         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5256         LocalFree(buf);
5257         buf = NULL;
5258     }
5259     info.ListIdentifier.cbData = 0;
5260     info.SequenceNumber.cbData = sizeof(serialNum);
5261     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5262     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5263      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5264     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5265     if (buf)
5266     {
5267         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5268          size);
5269         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5270         LocalFree(buf);
5271         buf = NULL;
5272     }
5273     info.SequenceNumber.cbData = 0;
5274     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5275     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5276      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5277     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5278     if (buf)
5279     {
5280         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5281         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5282         LocalFree(buf);
5283         buf = NULL;
5284     }
5285     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
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(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5292          size);
5293         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5294         LocalFree(buf);
5295         buf = NULL;
5296     }
5297     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5298     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5299     info.SubjectAlgorithm.pszObjId = oid2;
5300     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5301      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5302     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5303     if (buf)
5304     {
5305         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5306         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5307         LocalFree(buf);
5308         buf = NULL;
5309     }
5310     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5311      * (see tests below) but it'll encode fine.
5312      */
5313     info.SubjectAlgorithm.pszObjId = NULL;
5314     value1.cbData = sizeof(serialNum);
5315     value1.pbData = (LPBYTE)serialNum;
5316     attr1.pszObjId = oid1;
5317     attr1.cValue = 1;
5318     attr1.rgValue = &value1;
5319     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5320     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5321     ctlEntry[0].cAttribute = 1;
5322     ctlEntry[0].rgAttribute = &attr1;
5323     info.cCTLEntry = 1;
5324     info.rgCTLEntry = ctlEntry;
5325     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5326      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5327     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5328     if (buf)
5329     {
5330         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5331         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5332         LocalFree(buf);
5333         buf = NULL;
5334     }
5335     value1.cbData = sizeof(emptySequence);
5336     value1.pbData = (LPBYTE)emptySequence;
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(ctlWithOneEntry), "unexpected size %d\n", size);
5343         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5344         LocalFree(buf);
5345         buf = NULL;
5346     }
5347     value2.cbData = sizeof(encodedIPAddr);
5348     value2.pbData = (LPBYTE)encodedIPAddr;
5349     attr2.pszObjId = oid2;
5350     attr2.cValue = 1;
5351     attr2.rgValue = &value2;
5352     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5353     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5354     ctlEntry[1].cAttribute = 1;
5355     ctlEntry[1].rgAttribute = &attr2;
5356     info.cCTLEntry = 2;
5357     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5358      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5359     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5360     if (buf)
5361     {
5362         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5363         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5364         LocalFree(buf);
5365         buf = NULL;
5366     }
5367 }
5368
5369 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5370  const CTL_INFO *got)
5371 {
5372     DWORD i, j, k;
5373
5374     ok(expected->dwVersion == got->dwVersion,
5375      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5376      got->dwVersion);
5377     ok(expected->SubjectUsage.cUsageIdentifier ==
5378      got->SubjectUsage.cUsageIdentifier,
5379      "%s: expected %d usage identifiers, got %d\n", header,
5380      expected->SubjectUsage.cUsageIdentifier,
5381      got->SubjectUsage.cUsageIdentifier);
5382     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5383         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5384          got->SubjectUsage.rgpszUsageIdentifier[i]),
5385          "%s[%d]: expected %s, got %s\n", header, i,
5386          expected->SubjectUsage.rgpszUsageIdentifier[i],
5387          got->SubjectUsage.rgpszUsageIdentifier[i]);
5388     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5389      "%s: expected list identifier of %d bytes, got %d\n", header,
5390      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5391     if (expected->ListIdentifier.cbData)
5392         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5393          expected->ListIdentifier.cbData),
5394          "%s: unexpected list identifier value\n", header);
5395     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5396      "%s: expected sequence number of %d bytes, got %d\n", header,
5397      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5398     if (expected->SequenceNumber.cbData)
5399         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5400          expected->SequenceNumber.cbData),
5401          "%s: unexpected sequence number value\n", header);
5402     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5403      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5404      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5405      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5406     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5407      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5408      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5409      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5410     if (expected->SubjectAlgorithm.pszObjId &&
5411      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5412         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5413          expected->SubjectAlgorithm.pszObjId);
5414     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5415         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5416          got->SubjectAlgorithm.pszObjId),
5417          "%s: expected subject algorithm %s, got %s\n", header,
5418          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5419     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5420      got->SubjectAlgorithm.Parameters.cbData,
5421      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5422      expected->SubjectAlgorithm.Parameters.cbData,
5423      got->SubjectAlgorithm.Parameters.cbData);
5424     if (expected->SubjectAlgorithm.Parameters.cbData)
5425         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5426          got->SubjectAlgorithm.Parameters.pbData,
5427          expected->SubjectAlgorithm.Parameters.cbData),
5428          "%s: unexpected subject algorithm parameter value\n", header);
5429     ok(expected->cCTLEntry == got->cCTLEntry,
5430      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5431      got->cCTLEntry);
5432     for (i = 0; i < expected->cCTLEntry; i++)
5433     {
5434         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5435          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5436          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5437          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5438          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5439         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5440             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5441              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5442              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5443              "%s[%d]: unexpected subject identifier value\n",
5444              header, i);
5445         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5446         {
5447             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5448              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5449              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5450              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5451              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5452             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5453             {
5454                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5455                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5456                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5457                  header, i, j, k,
5458                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5459                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5460                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5461                     ok(!memcmp(
5462                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5463                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5464                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5465                      "%s[%d][%d][%d]: unexpected value\n",
5466                      header, i, j, k);
5467             }
5468         }
5469     }
5470     ok(expected->cExtension == got->cExtension,
5471      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5472      got->cExtension);
5473     for (i = 0; i < expected->cExtension; i++)
5474     {
5475         ok(!strcmp(expected->rgExtension[i].pszObjId,
5476          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5477          header, i, expected->rgExtension[i].pszObjId,
5478          got->rgExtension[i].pszObjId);
5479         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5480          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5481          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5482         ok(expected->rgExtension[i].Value.cbData ==
5483          got->rgExtension[i].Value.cbData,
5484          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5485          header, i, expected->rgExtension[i].Value.cbData,
5486          got->rgExtension[i].Value.cbData);
5487         if (expected->rgExtension[i].Value.cbData)
5488             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5489              got->rgExtension[i].Value.pbData,
5490              expected->rgExtension[i].Value.cbData),
5491              "%s[%d]: unexpected extension value\n", header, i);
5492     }
5493 }
5494
5495 static const BYTE signedCTL[] = {
5496 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5497 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5498 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5499 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5500 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5501 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5502 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5503 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5504 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5505 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5506 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5507 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5508 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5509 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5510 static const BYTE signedCTLWithCTLInnerContent[] = {
5511 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5512 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5513 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5514 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5515 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5516 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5517 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5518 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5519 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5520 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5521 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5522 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5523 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5524 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5525 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5526 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5527 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5528 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5529 0x57,0x6c,0x0b,0x47,0xb8 };
5530
5531 static void test_decodeCTL(DWORD dwEncoding)
5532 {
5533     static char oid1[] = "1.2.3";
5534     static char oid2[] = "1.5.6";
5535     static BYTE nullData[] = { 5,0 };
5536     char *pOid1 = oid1;
5537     BOOL ret;
5538     BYTE *buf = NULL;
5539     DWORD size = 0;
5540     CTL_INFO info;
5541     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5542     CTL_ENTRY ctlEntry[2];
5543     CRYPT_ATTRIBUTE attr1, attr2;
5544     CRYPT_ATTR_BLOB value1, value2;
5545
5546     memset(&info, 0, sizeof(info));
5547     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5548      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5549     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5550     if (buf)
5551     {
5552         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5553         LocalFree(buf);
5554         buf = NULL;
5555     }
5556     info.dwVersion = 1;
5557     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5558      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5559      &size);
5560     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5561     if (buf)
5562     {
5563         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5564         LocalFree(buf);
5565         buf = NULL;
5566     }
5567     info.dwVersion = 0;
5568     info.SubjectUsage.cUsageIdentifier = 1;
5569     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5570     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5571      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5572      &buf, &size);
5573     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5574     if (buf)
5575     {
5576         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5577         LocalFree(buf);
5578         buf = NULL;
5579     }
5580     info.SubjectUsage.cUsageIdentifier = 0;
5581     info.ListIdentifier.cbData = sizeof(serialNum);
5582     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5583     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5584      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5585     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5586     if (buf)
5587     {
5588         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5589         LocalFree(buf);
5590         buf = NULL;
5591     }
5592     info.ListIdentifier.cbData = 0;
5593     info.SequenceNumber.cbData = sizeof(serialNum);
5594     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5595     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5596      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5597     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5598     if (buf)
5599     {
5600         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5601         LocalFree(buf);
5602         buf = NULL;
5603     }
5604     info.SequenceNumber.cbData = 0;
5605     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5606     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5607      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5608     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5609     if (buf)
5610     {
5611         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5612         LocalFree(buf);
5613         buf = NULL;
5614     }
5615     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5616     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5617      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5618      &buf, &size);
5619     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5620     if (buf)
5621     {
5622         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5623         LocalFree(buf);
5624         buf = NULL;
5625     }
5626     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5627     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5628     info.SubjectAlgorithm.pszObjId = oid2;
5629     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5630     info.SubjectAlgorithm.Parameters.pbData = nullData;
5631     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5632      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5633     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5634     if (buf)
5635     {
5636         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5637         LocalFree(buf);
5638         buf = NULL;
5639     }
5640     SetLastError(0xdeadbeef);
5641     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5642      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5643     ok(!ret &&
5644      (GetLastError() == CRYPT_E_ASN1_EOD ||
5645       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5646       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5647      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5648      GetLastError());
5649     info.SubjectAlgorithm.Parameters.cbData = 0;
5650     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5651     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5652     info.SubjectAlgorithm.pszObjId = oid2;
5653     info.SubjectAlgorithm.pszObjId = NULL;
5654     value1.cbData = sizeof(emptySequence);
5655     value1.pbData = (LPBYTE)emptySequence;
5656     attr1.pszObjId = oid1;
5657     attr1.cValue = 1;
5658     attr1.rgValue = &value1;
5659     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5660     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5661     ctlEntry[0].cAttribute = 1;
5662     ctlEntry[0].rgAttribute = &attr1;
5663     info.cCTLEntry = 1;
5664     info.rgCTLEntry = ctlEntry;
5665     SetLastError(0xdeadbeef);
5666     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5667      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5668     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5669     if (buf)
5670     {
5671         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5672         LocalFree(buf);
5673         buf = NULL;
5674     }
5675     value2.cbData = sizeof(encodedIPAddr);
5676     value2.pbData = (LPBYTE)encodedIPAddr;
5677     attr2.pszObjId = oid2;
5678     attr2.cValue = 1;
5679     attr2.rgValue = &value2;
5680     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5681     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5682     ctlEntry[1].cAttribute = 1;
5683     ctlEntry[1].rgAttribute = &attr2;
5684     info.cCTLEntry = 2;
5685     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5686      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5687     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5688     if (buf)
5689     {
5690         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5691         LocalFree(buf);
5692         buf = NULL;
5693     }
5694     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5695     SetLastError(0xdeadbeef);
5696     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5697      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5698     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5699      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5700      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5701      GetLastError());
5702     SetLastError(0xdeadbeef);
5703     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5704      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5705      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5706     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5707      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5708      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5709      GetLastError());
5710 }
5711
5712 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5713 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5714  0x03,0,0,0,0,0,0 };
5715 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5716  0xa0,0x01,0x01 };
5717 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5718  0x03,0x02,0x01,0x01 };
5719 static BYTE bogusDER[] = { 1 };
5720
5721 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5722 {
5723     BOOL ret;
5724     BYTE *buf = NULL;
5725     DWORD size = 0;
5726     CRYPT_CONTENT_INFO info = { 0 };
5727     char oid1[] = "1.2.3";
5728
5729     if (0)
5730     {
5731         /* Crashes on win9x */
5732         SetLastError(0xdeadbeef);
5733         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5734          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5735         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5736          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5737     }
5738     SetLastError(0xdeadbeef);
5739     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5740      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5741     ok(!ret && (GetLastError() == E_INVALIDARG ||
5742      GetLastError() == OSS_LIMITED /* Win9x */),
5743      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5744     info.pszObjId = oid1;
5745     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5746      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5747     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5748     if (buf)
5749     {
5750         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5751         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5752         LocalFree(buf);
5753     }
5754     info.Content.pbData = bogusDER;
5755     info.Content.cbData = sizeof(bogusDER);
5756     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5757      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5758     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5759     if (buf)
5760     {
5761         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5762         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5763         LocalFree(buf);
5764     }
5765     info.Content.pbData = (BYTE *)ints[0].encoded;
5766     info.Content.cbData = ints[0].encoded[1] + 2;
5767     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5768      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5769     if (buf)
5770     {
5771         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5772         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5773         LocalFree(buf);
5774     }
5775 }
5776
5777 static const BYTE indefiniteSignedPKCSContent[] = {
5778 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5779 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5780 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5781 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5782 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5783 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5784 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5785 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5786 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5787 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5788 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5789 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5790 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5791 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5792 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5793 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5794 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5795 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5796 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5797 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5798 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5799 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5800 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5801 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5802 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5803 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5804 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5805 0x00,0x00,0x00,0x00,0x00,0x00 };
5806
5807 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5808 {
5809     BOOL ret;
5810     LPBYTE buf = NULL;
5811     DWORD size = 0;
5812     CRYPT_CONTENT_INFO *info;
5813
5814     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5815      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5816      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5817     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5818     if (buf)
5819     {
5820         info = (CRYPT_CONTENT_INFO *)buf;
5821
5822         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5823          info->pszObjId);
5824         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5825          info->Content.cbData);
5826         LocalFree(buf);
5827     }
5828     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5829      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5830      0, NULL, NULL, &size);
5831     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5832     SetLastError(0xdeadbeef);
5833     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5834      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5835      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5836     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5837      * I doubt an app depends on that.
5838      */
5839     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5840      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5841      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5842      GetLastError());
5843     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5844      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5845      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5846     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5847     if (buf)
5848     {
5849         info = (CRYPT_CONTENT_INFO *)buf;
5850
5851         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5852          info->pszObjId);
5853         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5854          "Unexpected size %d\n", info->Content.cbData);
5855         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5856          info->Content.cbData), "Unexpected value\n");
5857         LocalFree(buf);
5858     }
5859     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5860      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5861      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5862     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5863     if (buf)
5864     {
5865         info = (CRYPT_CONTENT_INFO *)buf;
5866
5867         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5868          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5869         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5870          info->Content.cbData);
5871         LocalFree(buf);
5872     }
5873 }
5874
5875 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5876  0x00 };
5877 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5878  0x01 };
5879 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5880  0x02,0x01,0x01 };
5881
5882 static void test_encodePKCSAttribute(DWORD dwEncoding)
5883 {
5884     CRYPT_ATTRIBUTE attr = { 0 };
5885     BOOL ret;
5886     LPBYTE buf = NULL;
5887     DWORD size = 0;
5888     CRYPT_ATTR_BLOB blob;
5889     char oid[] = "1.2.3";
5890
5891     if (0)
5892     {
5893         /* Crashes on win9x */
5894         SetLastError(0xdeadbeef);
5895         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5896          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5897         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5898          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5899     }
5900     SetLastError(0xdeadbeef);
5901     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5902      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5903     ok(!ret && (GetLastError() == E_INVALIDARG ||
5904      GetLastError() == OSS_LIMITED /* Win9x */),
5905      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5906     attr.pszObjId = oid;
5907     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5908      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5909     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5910     if (buf)
5911     {
5912         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5913         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5914         LocalFree(buf);
5915     }
5916     blob.cbData = sizeof(bogusDER);
5917     blob.pbData = bogusDER;
5918     attr.cValue = 1;
5919     attr.rgValue = &blob;
5920     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5921      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5922     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5923     if (buf)
5924     {
5925         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5926         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5927         LocalFree(buf);
5928     }
5929     blob.pbData = (BYTE *)ints[0].encoded;
5930     blob.cbData = ints[0].encoded[1] + 2;
5931     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5932      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5933     if (buf)
5934     {
5935         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5936         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5937         LocalFree(buf);
5938     }
5939 }
5940
5941 static void test_decodePKCSAttribute(DWORD dwEncoding)
5942 {
5943     BOOL ret;
5944     LPBYTE buf = NULL;
5945     DWORD size = 0;
5946     CRYPT_ATTRIBUTE *attr;
5947
5948     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5949      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5950      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5951     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5952     if (buf)
5953     {
5954         attr = (CRYPT_ATTRIBUTE *)buf;
5955
5956         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5957          attr->pszObjId);
5958         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5959         LocalFree(buf);
5960     }
5961     SetLastError(0xdeadbeef);
5962     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5963      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5964      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5965     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5966      * I doubt an app depends on that.
5967      */
5968     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5969      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5970      GetLastError() == OSS_MORE_INPUT /* Win9x */),
5971      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5972      GetLastError());
5973     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5974      intPKCSAttr, sizeof(intPKCSAttr),
5975      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5976     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5977     if (buf)
5978     {
5979         attr = (CRYPT_ATTRIBUTE *)buf;
5980
5981         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5982          attr->pszObjId);
5983         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5984         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5985          "Unexpected size %d\n", attr->rgValue[0].cbData);
5986         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5987          attr->rgValue[0].cbData), "Unexpected value\n");
5988         LocalFree(buf);
5989     }
5990 }
5991
5992 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5993 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5994  0x2a,0x03,0x31,0x00 };
5995 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5996  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5997
5998 static void test_encodePKCSAttributes(DWORD dwEncoding)
5999 {
6000     CRYPT_ATTRIBUTES attributes = { 0 };
6001     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6002     CRYPT_ATTR_BLOB blob;
6003     BOOL ret;
6004     LPBYTE buf = NULL;
6005     DWORD size = 0;
6006     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6007
6008     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6009      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6010     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6011     if (buf)
6012     {
6013         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6014         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6015         LocalFree(buf);
6016     }
6017     attributes.cAttr = 1;
6018     attributes.rgAttr = attr;
6019     SetLastError(0xdeadbeef);
6020     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6021      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6022     ok(!ret && (GetLastError() == E_INVALIDARG ||
6023      GetLastError() == OSS_LIMITED /* Win9x */),
6024      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6025     attr[0].pszObjId = oid1;
6026     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6027      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6028     if (buf)
6029     {
6030         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6031         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6032         LocalFree(buf);
6033     }
6034     attr[1].pszObjId = oid2;
6035     attr[1].cValue = 1;
6036     attr[1].rgValue = &blob;
6037     blob.pbData = (BYTE *)ints[0].encoded;
6038     blob.cbData = ints[0].encoded[1] + 2;
6039     attributes.cAttr = 2;
6040     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6041      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6042     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6043     if (buf)
6044     {
6045         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6046         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6047         LocalFree(buf);
6048     }
6049 }
6050
6051 static void test_decodePKCSAttributes(DWORD dwEncoding)
6052 {
6053     BOOL ret;
6054     LPBYTE buf = NULL;
6055     DWORD size = 0;
6056     CRYPT_ATTRIBUTES *attributes;
6057
6058     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6059      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6060      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6061     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6062     if (buf)
6063     {
6064         attributes = (CRYPT_ATTRIBUTES *)buf;
6065         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6066          attributes->cAttr);
6067         LocalFree(buf);
6068     }
6069     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6070      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6071      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6072     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6073     if (buf)
6074     {
6075         attributes = (CRYPT_ATTRIBUTES *)buf;
6076         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6077          attributes->cAttr);
6078         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6079          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6080         ok(attributes->rgAttr[0].cValue == 0,
6081          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6082         LocalFree(buf);
6083     }
6084     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6085      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6086      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6087     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6088     if (buf)
6089     {
6090         attributes = (CRYPT_ATTRIBUTES *)buf;
6091         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6092          attributes->cAttr);
6093         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6094          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6095         ok(attributes->rgAttr[0].cValue == 0,
6096          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6097         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6098          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6099         ok(attributes->rgAttr[1].cValue == 1,
6100          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6101         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6102          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6103         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6104          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6105         LocalFree(buf);
6106     }
6107 }
6108
6109 static const BYTE singleCapability[] = {
6110 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6111 static const BYTE twoCapabilities[] = {
6112 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6113 static const BYTE singleCapabilitywithNULL[] = {
6114 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6115
6116 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6117 {
6118     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6119     BOOL ret;
6120     LPBYTE buf = NULL;
6121     DWORD size = 0;
6122     CRYPT_SMIME_CAPABILITY capability[2];
6123     CRYPT_SMIME_CAPABILITIES capabilities;
6124
6125     /* An empty capabilities is allowed */
6126     capabilities.cCapability = 0;
6127     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6128      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6129     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6130     if (buf)
6131     {
6132         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6133         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6134         LocalFree(buf);
6135     }
6136     /* A non-empty capabilities with an empty capability (lacking an OID) is
6137      * not allowed
6138      */
6139     capability[0].pszObjId = NULL;
6140     capability[0].Parameters.cbData = 0;
6141     capabilities.cCapability = 1;
6142     capabilities.rgCapability = capability;
6143     SetLastError(0xdeadbeef);
6144     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6145      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6146     ok(!ret && (GetLastError() == E_INVALIDARG ||
6147      GetLastError() == OSS_LIMITED /* Win9x */),
6148      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6149     capability[0].pszObjId = oid1;
6150     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6151      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6152     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6153     if (buf)
6154     {
6155         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6156         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6157         LocalFree(buf);
6158     }
6159     capability[1].pszObjId = oid2;
6160     capability[1].Parameters.cbData = 0;
6161     capabilities.cCapability = 2;
6162     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6163      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6164     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6165     if (buf)
6166     {
6167         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6168         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6169         LocalFree(buf);
6170     }
6171 }
6172
6173 static void compareSMimeCapabilities(LPCSTR header,
6174  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6175 {
6176     DWORD i;
6177
6178     ok(got->cCapability == expected->cCapability,
6179      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6180      got->cCapability);
6181     for (i = 0; i < expected->cCapability; i++)
6182     {
6183         ok(!strcmp(expected->rgCapability[i].pszObjId,
6184          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6185          header, i, expected->rgCapability[i].pszObjId,
6186          got->rgCapability[i].pszObjId);
6187         ok(expected->rgCapability[i].Parameters.cbData ==
6188          got->rgCapability[i].Parameters.cbData,
6189          "%s[%d]: expected %d bytes, got %d\n", header, i,
6190          expected->rgCapability[i].Parameters.cbData,
6191          got->rgCapability[i].Parameters.cbData);
6192         if (expected->rgCapability[i].Parameters.cbData)
6193             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6194              got->rgCapability[i].Parameters.pbData,
6195              expected->rgCapability[i].Parameters.cbData),
6196              "%s[%d]: unexpected value\n", header, i);
6197     }
6198 }
6199
6200 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6201 {
6202     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6203     BOOL ret;
6204     DWORD size = 0;
6205     CRYPT_SMIME_CAPABILITY capability[2];
6206     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6207
6208     SetLastError(0xdeadbeef);
6209     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6210      emptySequence, sizeof(emptySequence),
6211      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6212     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6213     if (ret)
6214     {
6215         capabilities.cCapability = 0;
6216         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6217         LocalFree(ptr);
6218     }
6219     SetLastError(0xdeadbeef);
6220     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6221      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6222      &ptr, &size);
6223     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6224     if (ret)
6225     {
6226         capability[0].pszObjId = oid1;
6227         capability[0].Parameters.cbData = 0;
6228         capabilities.cCapability = 1;
6229         capabilities.rgCapability = capability;
6230         compareSMimeCapabilities("single capability", &capabilities, ptr);
6231         LocalFree(ptr);
6232     }
6233     SetLastError(0xdeadbeef);
6234     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6235      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6236      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6237     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6238     if (ret)
6239     {
6240         BYTE NULLparam[] = {0x05, 0x00};
6241         capability[0].pszObjId = oid1;
6242         capability[0].Parameters.cbData = 2;
6243         capability[0].Parameters.pbData = NULLparam;
6244         capabilities.cCapability = 1;
6245         capabilities.rgCapability = capability;
6246         compareSMimeCapabilities("single capability with NULL", &capabilities,
6247          ptr);
6248         LocalFree(ptr);
6249     }
6250     SetLastError(0xdeadbeef);
6251     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6252     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6253     &ptr, &size);
6254     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6255     if (ret)
6256     {
6257         capability[0].Parameters.cbData = 0;
6258         capability[1].pszObjId = oid2;
6259         capability[1].Parameters.cbData = 0;
6260         capabilities.cCapability = 2;
6261         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6262         LocalFree(ptr);
6263     }
6264 }
6265
6266 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6267  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6268  0x67 };
6269 static const BYTE minimalPKCSSigner[] = {
6270  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6271  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6272  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6273 static const BYTE PKCSSignerWithSerial[] = {
6274  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6275  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6276  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6277  0x00 };
6278 static const BYTE PKCSSignerWithHashAlgo[] = {
6279  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6280  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6281  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6282  0x00,0x04,0x00 };
6283 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6284  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6285  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6286  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6287  0x06,0x05,0x00,0x04,0x00 };
6288 static const BYTE PKCSSignerWithHash[] = {
6289  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6290  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6291  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6292  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6293  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6294 static const BYTE PKCSSignerWithAuthAttr[] = {
6295 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6296 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6297 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6298 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6299 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6300 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6301 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6302
6303 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6304 {
6305     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6306     BOOL ret;
6307     LPBYTE buf = NULL;
6308     DWORD size = 0;
6309     CMSG_SIGNER_INFO info = { 0 };
6310     char oid_common_name[] = szOID_COMMON_NAME;
6311     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6312      (LPBYTE)encodedCommonName };
6313     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6314
6315     SetLastError(0xdeadbeef);
6316     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6317      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6318     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6319     {
6320         skip("no PKCS7_SIGNER_INFO encode support\n");
6321         return;
6322     }
6323     ok(!ret && (GetLastError() == E_INVALIDARG ||
6324      GetLastError() == OSS_LIMITED /* Win9x */),
6325      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6326     /* To be encoded, a signer must have an issuer at least, and the encoding
6327      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6328      * see decoding tests.)
6329      */
6330     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6331     info.Issuer.pbData = encodedCommonNameNoNull;
6332     SetLastError(0xdeadbeef);
6333     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6334      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6335     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6336         ok(!ret && GetLastError() == E_INVALIDARG,
6337          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6338     else
6339     {
6340         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6341          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6342         if (buf)
6343         {
6344             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6345             if (size == sizeof(minimalPKCSSigner))
6346                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6347             else
6348                 ok(0, "Unexpected value\n");
6349             LocalFree(buf);
6350         }
6351     }
6352     info.SerialNumber.cbData = sizeof(serialNum);
6353     info.SerialNumber.pbData = (BYTE *)serialNum;
6354     SetLastError(0xdeadbeef);
6355     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6356      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6357     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6358         ok(!ret && GetLastError() == E_INVALIDARG,
6359          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6360     else
6361     {
6362         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6363          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6364         if (buf)
6365         {
6366             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6367              size);
6368             if (size == sizeof(PKCSSignerWithSerial))
6369                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6370                  "Unexpected value\n");
6371             else
6372                 ok(0, "Unexpected value\n");
6373             LocalFree(buf);
6374         }
6375     }
6376     info.HashAlgorithm.pszObjId = oid1;
6377     SetLastError(0xdeadbeef);
6378     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6379      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6380     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6381         ok(!ret && GetLastError() == E_INVALIDARG,
6382          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6383     else
6384     {
6385         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6386          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6387         if (buf)
6388         {
6389             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6390              size);
6391             if (size == sizeof(PKCSSignerWithHashAlgo))
6392                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6393                  "Unexpected value\n");
6394             else
6395                 ok(0, "Unexpected value\n");
6396             LocalFree(buf);
6397         }
6398     }
6399     info.HashEncryptionAlgorithm.pszObjId = oid2;
6400     SetLastError(0xdeadbeef);
6401     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6402      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6403     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6404         ok(!ret && GetLastError() == E_INVALIDARG,
6405          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6406     else
6407     {
6408         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6409         if (buf)
6410         {
6411             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6412              "Unexpected size %d\n", size);
6413             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6414                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6415                  "Unexpected value\n");
6416             else
6417                 ok(0, "Unexpected value\n");
6418             LocalFree(buf);
6419         }
6420     }
6421     info.EncryptedHash.cbData = sizeof(hash);
6422     info.EncryptedHash.pbData = (BYTE *)hash;
6423     SetLastError(0xdeadbeef);
6424     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6425      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6426     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6427         ok(!ret && GetLastError() == E_INVALIDARG,
6428          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6429     else
6430     {
6431         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6432         if (buf)
6433         {
6434             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6435              size);
6436             if (size == sizeof(PKCSSignerWithHash))
6437                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6438                  "Unexpected value\n");
6439             else
6440                 ok(0, "Unexpected value\n");
6441             LocalFree(buf);
6442         }
6443     }
6444     info.AuthAttrs.cAttr = 1;
6445     info.AuthAttrs.rgAttr = &attr;
6446     SetLastError(0xdeadbeef);
6447     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6448      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6449     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6450         ok(!ret && GetLastError() == E_INVALIDARG,
6451          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6452     else
6453     {
6454         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6455         if (buf)
6456         {
6457             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6458              size);
6459             if (size == sizeof(PKCSSignerWithAuthAttr))
6460                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6461                  "Unexpected value\n");
6462             else
6463                 ok(0, "Unexpected value\n");
6464             LocalFree(buf);
6465         }
6466     }
6467 }
6468
6469 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6470 {
6471     BOOL ret;
6472     LPBYTE buf = NULL;
6473     DWORD size = 0;
6474     CMSG_SIGNER_INFO *info;
6475
6476     /* A PKCS signer can't be decoded without a serial number. */
6477     SetLastError(0xdeadbeef);
6478     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6479      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6480      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6481     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6482      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6483      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6484      GetLastError());
6485     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6486      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6487      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6488     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6489      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6490     if (buf)
6491     {
6492         info = (CMSG_SIGNER_INFO *)buf;
6493         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6494          info->dwVersion);
6495         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6496          "Unexpected size %d\n", info->Issuer.cbData);
6497         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6498          info->Issuer.cbData), "Unexpected value\n");
6499         ok(info->SerialNumber.cbData == sizeof(serialNum),
6500          "Unexpected size %d\n", info->SerialNumber.cbData);
6501         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6502          "Unexpected value\n");
6503         LocalFree(buf);
6504     }
6505     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6506      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6507      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6508     if (buf)
6509     {
6510         info = (CMSG_SIGNER_INFO *)buf;
6511         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6512          info->dwVersion);
6513         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6514          "Unexpected size %d\n", info->Issuer.cbData);
6515         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6516          info->Issuer.cbData), "Unexpected value\n");
6517         ok(info->SerialNumber.cbData == sizeof(serialNum),
6518          "Unexpected size %d\n", info->SerialNumber.cbData);
6519         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6520          "Unexpected value\n");
6521         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6522          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6523         LocalFree(buf);
6524     }
6525     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6526      PKCSSignerWithHashAndEncryptionAlgo,
6527      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6528      NULL, &buf, &size);
6529     if (buf)
6530     {
6531         info = (CMSG_SIGNER_INFO *)buf;
6532         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6533          info->dwVersion);
6534         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6535          "Unexpected size %d\n", info->Issuer.cbData);
6536         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6537          info->Issuer.cbData), "Unexpected value\n");
6538         ok(info->SerialNumber.cbData == sizeof(serialNum),
6539          "Unexpected size %d\n", info->SerialNumber.cbData);
6540         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6541          "Unexpected value\n");
6542         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6543          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6544         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6545          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6546         LocalFree(buf);
6547     }
6548     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6549      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6550      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6551     if (buf)
6552     {
6553         info = (CMSG_SIGNER_INFO *)buf;
6554         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6555          info->dwVersion);
6556         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6557          "Unexpected size %d\n", info->Issuer.cbData);
6558         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6559          info->Issuer.cbData), "Unexpected value\n");
6560         ok(info->SerialNumber.cbData == sizeof(serialNum),
6561          "Unexpected size %d\n", info->SerialNumber.cbData);
6562         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6563          "Unexpected value\n");
6564         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6565          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6566         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6567          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6568         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6569          info->EncryptedHash.cbData);
6570         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6571          "Unexpected value\n");
6572         LocalFree(buf);
6573     }
6574     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6575      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6576      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6577     if (buf)
6578     {
6579         info = (CMSG_SIGNER_INFO *)buf;
6580         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6581          info->AuthAttrs.cAttr);
6582         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6583          "Expected %s, got %s\n", szOID_COMMON_NAME,
6584          info->AuthAttrs.rgAttr[0].pszObjId);
6585         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6586          info->AuthAttrs.rgAttr[0].cValue);
6587         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6588          sizeof(encodedCommonName), "Unexpected size %d\n",
6589          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6590         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6591          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6592         LocalFree(buf);
6593     }
6594 }
6595
6596 static const BYTE CMSSignerWithKeyId[] = {
6597 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6598 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6599
6600 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6601 {
6602     BOOL ret;
6603     LPBYTE buf = NULL;
6604     DWORD size = 0;
6605     CMSG_CMS_SIGNER_INFO info = { 0 };
6606     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6607
6608     SetLastError(0xdeadbeef);
6609     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6610      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6611     ok(!ret, "Expected failure, got %d\n", ret);
6612     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6613     {
6614         skip("no CMS_SIGNER_INFO encode support\n");
6615         return;
6616     }
6617     ok(GetLastError() == E_INVALIDARG,
6618        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6619     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6620     SetLastError(0xdeadbeef);
6621     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6622      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6623     ok(!ret, "Expected failure, got %d\n", ret);
6624     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6625     {
6626         skip("no CMS_SIGNER_INFO encode support\n");
6627         return;
6628     }
6629     ok(GetLastError() == E_INVALIDARG,
6630        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6631     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6632      * be a key id or a issuer serial number with at least the issuer set, and
6633      * the encoding must include PKCS_7_ASN_ENCODING.
6634      * (That isn't enough to be decoded, see decoding tests.)
6635      */
6636     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6637      sizeof(encodedCommonNameNoNull);
6638     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6639     SetLastError(0xdeadbeef);
6640     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6641      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6642     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6643         ok(!ret && GetLastError() == E_INVALIDARG,
6644          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6645     else
6646     {
6647         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6648         if (buf)
6649         {
6650             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6651             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6652             LocalFree(buf);
6653         }
6654     }
6655     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6656     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6657     SetLastError(0xdeadbeef);
6658     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6659      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6660     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6661         ok(!ret && GetLastError() == E_INVALIDARG,
6662          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6663     else
6664     {
6665         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6666         if (buf)
6667         {
6668             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6669              size);
6670             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6671             LocalFree(buf);
6672         }
6673     }
6674     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6675     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6676     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6677     SetLastError(0xdeadbeef);
6678     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6679      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6680     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6681         ok(!ret && GetLastError() == E_INVALIDARG,
6682          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6683     else
6684     {
6685         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6686         if (buf)
6687         {
6688             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6689              size);
6690             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6691             LocalFree(buf);
6692         }
6693     }
6694     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6695      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6696      * (see RFC 3852, section 5.3.)
6697      */
6698     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6699     U(info.SignerId).HashId.cbData = sizeof(hash);
6700     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6701     SetLastError(0xdeadbeef);
6702     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6703      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6704     ok(!ret && GetLastError() == E_INVALIDARG,
6705      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6706     /* Now with a hash algo */
6707     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6708     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6709      sizeof(encodedCommonNameNoNull);
6710     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6711     info.HashAlgorithm.pszObjId = oid1;
6712     SetLastError(0xdeadbeef);
6713     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6714      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6715     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6716         ok(!ret && GetLastError() == E_INVALIDARG,
6717          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6718     else
6719     {
6720         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6721         if (buf)
6722         {
6723             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6724              size);
6725             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6726              "Unexpected value\n");
6727             LocalFree(buf);
6728         }
6729     }
6730     info.HashEncryptionAlgorithm.pszObjId = oid2;
6731     SetLastError(0xdeadbeef);
6732     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6733      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6734     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6735         ok(!ret && GetLastError() == E_INVALIDARG,
6736          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6737     else
6738     {
6739         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6740         if (buf)
6741         {
6742             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6743              "Unexpected size %d\n", size);
6744             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6745              "Unexpected value\n");
6746             LocalFree(buf);
6747         }
6748     }
6749     info.EncryptedHash.cbData = sizeof(hash);
6750     info.EncryptedHash.pbData = (BYTE *)hash;
6751     SetLastError(0xdeadbeef);
6752     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6753      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6754     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6755         ok(!ret && GetLastError() == E_INVALIDARG,
6756          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6757     else
6758     {
6759         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6760         if (buf)
6761         {
6762             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6763              size);
6764             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6765             LocalFree(buf);
6766         }
6767     }
6768 }
6769
6770 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6771 {
6772     BOOL ret;
6773     LPBYTE buf = NULL;
6774     DWORD size = 0;
6775     CMSG_CMS_SIGNER_INFO *info;
6776     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6777
6778     /* A CMS signer can't be decoded without a serial number. */
6779     SetLastError(0xdeadbeef);
6780     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6781      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6782      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6783     ok(!ret, "expected failure\n");
6784     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6785     {
6786         skip("no CMS_SIGNER_INFO decode support\n");
6787         return;
6788     }
6789     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6790      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6791     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6792      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6793      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6794     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6795     if (buf)
6796     {
6797         info = (CMSG_CMS_SIGNER_INFO *)buf;
6798         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6799          info->dwVersion);
6800         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6801          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6802          info->SignerId.dwIdChoice);
6803         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6804          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6805          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6806         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6807          encodedCommonNameNoNull,
6808          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6809          "Unexpected value\n");
6810         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6811          sizeof(serialNum), "Unexpected size %d\n",
6812          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6813         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6814          serialNum, sizeof(serialNum)), "Unexpected value\n");
6815         LocalFree(buf);
6816     }
6817     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6818      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6819      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6820     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6821     if (buf)
6822     {
6823         info = (CMSG_CMS_SIGNER_INFO *)buf;
6824         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6825          info->dwVersion);
6826         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6827          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6828          info->SignerId.dwIdChoice);
6829         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6830          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6831          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6832         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6833          encodedCommonNameNoNull,
6834          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6835          "Unexpected value\n");
6836         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6837          sizeof(serialNum), "Unexpected size %d\n",
6838          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6839         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6840          serialNum, sizeof(serialNum)), "Unexpected value\n");
6841         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6842          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6843         LocalFree(buf);
6844     }
6845     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6846      PKCSSignerWithHashAndEncryptionAlgo,
6847      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6848      NULL, &buf, &size);
6849     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6850     if (buf)
6851     {
6852         info = (CMSG_CMS_SIGNER_INFO *)buf;
6853         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6854          info->dwVersion);
6855         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6856          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6857          info->SignerId.dwIdChoice);
6858         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6859          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6860          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6861         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6862          encodedCommonNameNoNull,
6863          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6864          "Unexpected value\n");
6865         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6866          sizeof(serialNum), "Unexpected size %d\n",
6867          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6868         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6869          serialNum, sizeof(serialNum)), "Unexpected value\n");
6870         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6871          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6872         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6873          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6874         LocalFree(buf);
6875     }
6876     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6877      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6878      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6879     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6880     if (buf)
6881     {
6882         info = (CMSG_CMS_SIGNER_INFO *)buf;
6883         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6884          info->dwVersion);
6885         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6886          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6887          info->SignerId.dwIdChoice);
6888         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6889          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6890          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6891         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6892          encodedCommonNameNoNull,
6893          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6894          "Unexpected value\n");
6895         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6896          sizeof(serialNum), "Unexpected size %d\n",
6897          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6898         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6899          serialNum, sizeof(serialNum)), "Unexpected value\n");
6900         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6901          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6902         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6903          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6904         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6905          info->EncryptedHash.cbData);
6906         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6907          "Unexpected value\n");
6908         LocalFree(buf);
6909     }
6910     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6911      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6912      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6913     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6914     if (buf)
6915     {
6916         info = (CMSG_CMS_SIGNER_INFO *)buf;
6917         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6918          info->dwVersion);
6919         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6920          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6921          info->SignerId.dwIdChoice);
6922         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6923          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6924         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6925          "Unexpected value\n");
6926         LocalFree(buf);
6927     }
6928 }
6929
6930 static BYTE emptyDNSPermittedConstraints[] = {
6931 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6932 static BYTE emptyDNSExcludedConstraints[] = {
6933 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6934 static BYTE DNSExcludedConstraints[] = {
6935 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6936 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6937 static BYTE permittedAndExcludedConstraints[] = {
6938 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6939 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6940 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6941 static BYTE permittedAndExcludedWithMinConstraints[] = {
6942 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6943 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6944 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6945 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6946 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6947 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6948 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6949
6950 static void test_encodeNameConstraints(DWORD dwEncoding)
6951 {
6952     BOOL ret;
6953     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6954     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6955     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6956     LPBYTE buf;
6957     DWORD size;
6958
6959     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6960      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6961     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6962     {
6963         skip("no X509_NAME_CONSTRAINTS encode support\n");
6964         return;
6965     }
6966     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6967     if (ret)
6968     {
6969         ok(size == sizeof(emptySequence), "Unexpected size\n");
6970         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6971         LocalFree(buf);
6972     }
6973     constraints.cPermittedSubtree = 1;
6974     constraints.rgPermittedSubtree = &permitted;
6975     SetLastError(0xdeadbeef);
6976     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6977      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6978     ok(!ret && GetLastError() == E_INVALIDARG,
6979      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6980     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6981     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6982      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6983     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6984     if (ret)
6985     {
6986         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6987         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6988          "Unexpected value\n");
6989         LocalFree(buf);
6990     }
6991     constraints.cPermittedSubtree = 0;
6992     constraints.cExcludedSubtree = 1;
6993     constraints.rgExcludedSubtree = &excluded;
6994     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6995     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6996      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6997     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6998     if (ret)
6999     {
7000         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7001         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7002          "Unexpected value\n");
7003         LocalFree(buf);
7004     }
7005     U(excluded.Base).pwszURL = (LPWSTR)url;
7006     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7007      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7008     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7009     if (ret)
7010     {
7011         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7012         ok(!memcmp(buf, DNSExcludedConstraints, size),
7013          "Unexpected value\n");
7014         LocalFree(buf);
7015     }
7016     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7017     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7018     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7019     constraints.cPermittedSubtree = 1;
7020     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7021      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7022     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7023     if (ret)
7024     {
7025         ok(size == sizeof(permittedAndExcludedConstraints),
7026          "Unexpected size\n");
7027         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7028          "Unexpected value\n");
7029         LocalFree(buf);
7030     }
7031     permitted.dwMinimum = 5;
7032     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7033      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7034     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7035     if (ret)
7036     {
7037         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7038          "Unexpected size\n");
7039         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7040          "Unexpected value\n");
7041         LocalFree(buf);
7042     }
7043     permitted.fMaximum = TRUE;
7044     permitted.dwMaximum = 3;
7045     SetLastError(0xdeadbeef);
7046     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7047      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7048     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7049     if (ret)
7050     {
7051         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7052          "Unexpected size\n");
7053         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7054          "Unexpected value\n");
7055         LocalFree(buf);
7056     }
7057 }
7058
7059 struct EncodedNameConstraints
7060 {
7061     CRYPT_DATA_BLOB            encoded;
7062     CERT_NAME_CONSTRAINTS_INFO constraints;
7063 };
7064
7065 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7066  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7067 static CERT_GENERAL_SUBTREE DNSSubtree = {
7068  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7069 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7070  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7071 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7072  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7073 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7074  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7075
7076 struct EncodedNameConstraints encodedNameConstraints[] = {
7077  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7078  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7079    { 1, &emptyDNSSubtree, 0, NULL } },
7080  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7081    { 0, NULL, 1, &emptyDNSSubtree } },
7082  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7083    { 0, NULL, 1, &DNSSubtree } },
7084  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7085    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7086  { { sizeof(permittedAndExcludedWithMinConstraints),
7087      permittedAndExcludedWithMinConstraints },
7088    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7089  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7090      permittedAndExcludedWithMinMaxConstraints },
7091    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7092 };
7093
7094 static void test_decodeNameConstraints(DWORD dwEncoding)
7095 {
7096     BOOL ret;
7097     DWORD i;
7098     CERT_NAME_CONSTRAINTS_INFO *constraints;
7099
7100     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7101     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7102     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7103     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7104     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7105     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7106     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7107     for (i = 0;
7108      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7109      i++)
7110     {
7111         DWORD size;
7112
7113         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7114          encodedNameConstraints[i].encoded.pbData,
7115          encodedNameConstraints[i].encoded.cbData,
7116          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7117         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7118         {
7119             skip("no X509_NAME_CONSTRAINTS decode support\n");
7120             return;
7121         }
7122         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7123         if (ret)
7124         {
7125             DWORD j;
7126
7127             if (constraints->cPermittedSubtree !=
7128              encodedNameConstraints[i].constraints.cPermittedSubtree)
7129                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7130                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7131                  constraints->cPermittedSubtree);
7132             if (constraints->cPermittedSubtree ==
7133              encodedNameConstraints[i].constraints.cPermittedSubtree)
7134             {
7135                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7136                 {
7137                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7138                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7139                 }
7140             }
7141             if (constraints->cExcludedSubtree !=
7142              encodedNameConstraints[i].constraints.cExcludedSubtree)
7143                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7144                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7145                  constraints->cExcludedSubtree);
7146             if (constraints->cExcludedSubtree ==
7147              encodedNameConstraints[i].constraints.cExcludedSubtree)
7148             {
7149                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7150                 {
7151                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7152                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7153                 }
7154             }
7155             LocalFree(constraints);
7156         }
7157     }
7158 }
7159
7160 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7161  'n','o','t','i','c','e',0 };
7162 static const BYTE noticeWithDisplayText[] = {
7163  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7164  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7165  0x00,0x69,0x00,0x63,0x00,0x65
7166 };
7167 static char org[] = "Wine";
7168 static int noticeNumbers[] = { 2,3 };
7169 static BYTE noticeWithReference[] = {
7170  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7171  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7172  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7173  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7174 };
7175
7176 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7177 {
7178     BOOL ret;
7179     LPBYTE buf;
7180     DWORD size;
7181     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7182     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7183
7184     memset(&notice, 0, sizeof(notice));
7185     ret = pCryptEncodeObjectEx(dwEncoding,
7186      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7187      NULL, &buf, &size);
7188     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7189     {
7190         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7191         return;
7192     }
7193     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7194     if (ret)
7195     {
7196         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7197         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7198         LocalFree(buf);
7199     }
7200     notice.pszDisplayText = noticeText;
7201     ret = pCryptEncodeObjectEx(dwEncoding,
7202      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7203      NULL, &buf, &size);
7204     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7205     if (ret)
7206     {
7207         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7208         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7209         LocalFree(buf);
7210     }
7211     reference.pszOrganization = org;
7212     reference.cNoticeNumbers = 2;
7213     reference.rgNoticeNumbers = noticeNumbers;
7214     notice.pNoticeReference = &reference;
7215     ret = pCryptEncodeObjectEx(dwEncoding,
7216      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7217      NULL, &buf, &size);
7218     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7219     if (ret)
7220     {
7221         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7222         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7223         LocalFree(buf);
7224     }
7225 }
7226
7227 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7228 {
7229     BOOL ret;
7230     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7231     DWORD size;
7232
7233     ret = pCryptDecodeObjectEx(dwEncoding,
7234      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7235      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7236      &notice, &size);
7237     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7238     {
7239         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7240         return;
7241     }
7242     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7243     if (ret)
7244     {
7245         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7246         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7247         LocalFree(notice);
7248     }
7249     ret = pCryptDecodeObjectEx(dwEncoding,
7250      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7251      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7252      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7253     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7254     if (ret)
7255     {
7256         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7257          "unexpected display text\n");
7258         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7259         LocalFree(notice);
7260     }
7261     ret = pCryptDecodeObjectEx(dwEncoding,
7262      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7263      noticeWithReference, sizeof(noticeWithReference),
7264      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7265     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7266     if (ret)
7267     {
7268         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7269          "unexpected display text\n");
7270         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7271         if (notice->pNoticeReference)
7272         {
7273             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7274              "unexpected organization %s\n",
7275              notice->pNoticeReference->pszOrganization);
7276             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7277              "expected 2 notice numbers, got %d\n",
7278              notice->pNoticeReference->cNoticeNumbers);
7279             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7280              "unexpected notice number %d\n",
7281              notice->pNoticeReference->rgNoticeNumbers[0]);
7282             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7283              "unexpected notice number %d\n",
7284              notice->pNoticeReference->rgNoticeNumbers[1]);
7285         }
7286         LocalFree(notice);
7287     }
7288 }
7289
7290 static char oid_any_policy[] = "2.5.29.32.0";
7291 static const BYTE policiesWithAnyPolicy[] = {
7292  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7293 };
7294 static char oid1[] = "1.2.3";
7295 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7296 static const BYTE twoPolicies[] = {
7297  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7298  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7299  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7300  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7301  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7302  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7303 };
7304
7305 static void test_encodeCertPolicies(DWORD dwEncoding)
7306 {
7307     BOOL ret;
7308     CERT_POLICIES_INFO info;
7309     CERT_POLICY_INFO policy[2];
7310     CERT_POLICY_QUALIFIER_INFO qualifier;
7311     LPBYTE buf;
7312     DWORD size;
7313
7314     memset(&info, 0, sizeof(info));
7315     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7316      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7317     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7318     if (ret)
7319     {
7320         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7321         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7322         LocalFree(buf);
7323     }
7324     memset(policy, 0, sizeof(policy));
7325     info.cPolicyInfo = 1;
7326     info.rgPolicyInfo = policy;
7327     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7328      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7329     ok(!ret && (GetLastError() == E_INVALIDARG ||
7330      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7331      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7332     policy[0].pszPolicyIdentifier = oid_any_policy;
7333     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7334      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7335     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7336     if (ret)
7337     {
7338         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7339         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7340         LocalFree(buf);
7341     }
7342     policy[1].pszPolicyIdentifier = oid1;
7343     memset(&qualifier, 0, sizeof(qualifier));
7344     qualifier.pszPolicyQualifierId = oid_user_notice;
7345     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7346     qualifier.Qualifier.pbData = noticeWithReference;
7347     policy[1].cPolicyQualifier = 1;
7348     policy[1].rgPolicyQualifier = &qualifier;
7349     info.cPolicyInfo = 2;
7350     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7351      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7352     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7353     if (ret)
7354     {
7355         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7356         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7357         LocalFree(buf);
7358     }
7359 }
7360
7361 static void test_decodeCertPolicies(DWORD dwEncoding)
7362 {
7363     BOOL ret;
7364     CERT_POLICIES_INFO *info;
7365     DWORD size;
7366
7367     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7368      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7369      &info, &size);
7370     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7371     if (ret)
7372     {
7373         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7374          info->cPolicyInfo);
7375         LocalFree(info);
7376     }
7377     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7378      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7379      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7380     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7381     if (ret)
7382     {
7383         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7384          info->cPolicyInfo);
7385         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7386          "unexpected policy id %s\n",
7387          info->rgPolicyInfo[0].pszPolicyIdentifier);
7388         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7389          "unexpected policy qualifier count %d\n",
7390          info->rgPolicyInfo[0].cPolicyQualifier);
7391         LocalFree(info);
7392     }
7393     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7394      twoPolicies, sizeof(twoPolicies),
7395      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7396     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7397     if (ret)
7398     {
7399         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7400          info->cPolicyInfo);
7401         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7402          "unexpected policy id %s\n",
7403          info->rgPolicyInfo[0].pszPolicyIdentifier);
7404         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7405          "unexpected policy qualifier count %d\n",
7406          info->rgPolicyInfo[0].cPolicyQualifier);
7407         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7408          "unexpected policy id %s\n",
7409          info->rgPolicyInfo[1].pszPolicyIdentifier);
7410         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7411          "unexpected policy qualifier count %d\n",
7412          info->rgPolicyInfo[1].cPolicyQualifier);
7413         ok(!strcmp(
7414          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7415          oid_user_notice), "unexpected policy qualifier id %s\n",
7416          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7417         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7418          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7419          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7420         ok(!memcmp(
7421          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7422          noticeWithReference, sizeof(noticeWithReference)),
7423          "unexpected qualifier value\n");
7424         LocalFree(info);
7425     }
7426 }
7427
7428 static const BYTE policyMappingWithOneMapping[] = {
7429 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7430 static const BYTE policyMappingWithTwoMappings[] = {
7431 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7432 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7433 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7434  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7435
7436 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7437 {
7438     static char oid2[] = "2.3.4";
7439     static char oid3[] = "1.3.4";
7440     static char oid4[] = "2.5.6";
7441     BOOL ret;
7442     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7443     CERT_POLICY_MAPPING mapping[2];
7444     LPBYTE buf;
7445     DWORD size, i;
7446
7447     /* Each of the mapping OIDs is equivalent, so check with all of them */
7448     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7449     {
7450         memset(&info, 0, sizeof(info));
7451         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7452          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7453         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7454         if (ret)
7455         {
7456             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7457             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7458              "unexpected value\n");
7459             LocalFree(buf);
7460         }
7461         mapping[0].pszIssuerDomainPolicy = NULL;
7462         mapping[0].pszSubjectDomainPolicy = NULL;
7463         info.cPolicyMapping = 1;
7464         info.rgPolicyMapping = mapping;
7465         SetLastError(0xdeadbeef);
7466         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7467          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7468         ok(!ret && GetLastError() == E_INVALIDARG,
7469          "expected E_INVALIDARG, got %08x\n", GetLastError());
7470         mapping[0].pszIssuerDomainPolicy = oid1;
7471         mapping[0].pszSubjectDomainPolicy = oid2;
7472         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7473          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7474         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7475         if (ret)
7476         {
7477             ok(size == sizeof(policyMappingWithOneMapping),
7478              "unexpected size %d\n", size);
7479             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7480              "unexpected value\n");
7481             LocalFree(buf);
7482         }
7483         mapping[1].pszIssuerDomainPolicy = oid3;
7484         mapping[1].pszSubjectDomainPolicy = oid4;
7485         info.cPolicyMapping = 2;
7486         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7487          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7488         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7489         if (ret)
7490         {
7491             ok(size == sizeof(policyMappingWithTwoMappings),
7492              "unexpected size %d\n", size);
7493             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7494              "unexpected value\n");
7495             LocalFree(buf);
7496         }
7497     }
7498 }
7499
7500 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7501 {
7502     DWORD size, i;
7503     CERT_POLICY_MAPPINGS_INFO *info;
7504     BOOL ret;
7505
7506     /* Each of the mapping OIDs is equivalent, so check with all of them */
7507     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7508     {
7509         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7510          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7511          &info, &size);
7512         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7513         if (ret)
7514         {
7515             ok(info->cPolicyMapping == 0,
7516              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7517             LocalFree(info);
7518         }
7519         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7520          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7521          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7522         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7523         if (ret)
7524         {
7525             ok(info->cPolicyMapping == 1,
7526              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7527             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7528              "unexpected issuer policy %s\n",
7529              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7530             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7531              "2.3.4"), "unexpected subject policy %s\n",
7532              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7533             LocalFree(info);
7534         }
7535         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7536          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7537          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7538         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7539         if (ret)
7540         {
7541             ok(info->cPolicyMapping == 2,
7542              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7543             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7544              "unexpected issuer policy %s\n",
7545              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7546             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7547              "2.3.4"), "unexpected subject policy %s\n",
7548              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7549             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7550              "unexpected issuer policy %s\n",
7551              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7552             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7553              "2.5.6"), "unexpected subject policy %s\n",
7554              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7555             LocalFree(info);
7556         }
7557     }
7558 }
7559
7560 static const BYTE policyConstraintsWithRequireExplicit[] = {
7561 0x30,0x03,0x80,0x01,0x00 };
7562 static const BYTE policyConstraintsWithInhibitMapping[] = {
7563 0x30,0x03,0x81,0x01,0x01 };
7564 static const BYTE policyConstraintsWithBoth[] = {
7565 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7566
7567 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7568 {
7569     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7570     LPBYTE buf;
7571     DWORD size;
7572     BOOL ret;
7573
7574     /* Even though RFC 5280 explicitly states CAs must not issue empty
7575      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7576      */
7577     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7578      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7579     todo_wine {
7580     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7581     if (ret)
7582     {
7583         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7584         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7585          "unexpected value\n");
7586         LocalFree(buf);
7587     }
7588     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7589      * is not, then a skip of 0 is encoded.
7590      */
7591     info.fRequireExplicitPolicy = TRUE;
7592     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7593      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7594     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7595     if (ret)
7596     {
7597         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7598          "unexpected size %d\n", size);
7599         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7600          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7601         LocalFree(buf);
7602     }
7603     /* With inhibit policy mapping */
7604     info.fRequireExplicitPolicy = FALSE;
7605     info.dwRequireExplicitPolicySkipCerts = 0;
7606     info.fInhibitPolicyMapping = TRUE;
7607     info.dwInhibitPolicyMappingSkipCerts = 1;
7608     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7609      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7610     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7611     if (ret)
7612     {
7613         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7614          "unexpected size %d\n", size);
7615         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7616          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7617         LocalFree(buf);
7618     }
7619     /* And with both */
7620     info.fRequireExplicitPolicy = TRUE;
7621     info.dwRequireExplicitPolicySkipCerts = 1;
7622     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7623      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7624     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7625     if (ret)
7626     {
7627         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7628          size);
7629         ok(!memcmp(buf, policyConstraintsWithBoth,
7630          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7631         LocalFree(buf);
7632     }
7633     }
7634 }
7635
7636 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7637 {
7638     CERT_POLICY_CONSTRAINTS_INFO *info;
7639     DWORD size;
7640     BOOL ret;
7641
7642     /* Again, even though CAs must not issue such constraints, they can be
7643      * decoded.
7644      */
7645     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7646      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7647      &info, &size);
7648     todo_wine {
7649     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7650     if (ret)
7651     {
7652         ok(!info->fRequireExplicitPolicy,
7653          "expected require explicit = FALSE\n");
7654         ok(!info->fInhibitPolicyMapping,
7655          "expected implicit mapping = FALSE\n");
7656         LocalFree(info);
7657     }
7658     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7659      policyConstraintsWithRequireExplicit,
7660      sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7661      NULL, &info, &size);
7662     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7663     if (ret)
7664     {
7665         ok(info->fRequireExplicitPolicy,
7666          "expected require explicit = TRUE\n");
7667         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7668          info->dwRequireExplicitPolicySkipCerts);
7669         ok(!info->fInhibitPolicyMapping,
7670          "expected implicit mapping = FALSE\n");
7671         LocalFree(info);
7672     }
7673     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7674      policyConstraintsWithInhibitMapping,
7675      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7676      NULL, &info, &size);
7677     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7678     if (ret)
7679     {
7680         ok(!info->fRequireExplicitPolicy,
7681          "expected require explicit = FALSE\n");
7682         ok(info->fInhibitPolicyMapping,
7683          "expected implicit mapping = TRUE\n");
7684         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7685          info->dwInhibitPolicyMappingSkipCerts);
7686         LocalFree(info);
7687     }
7688     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7689      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7690      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7691     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7692     if (ret)
7693     {
7694         ok(info->fRequireExplicitPolicy,
7695          "expected require explicit = TRUE\n");
7696         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7697          info->dwRequireExplicitPolicySkipCerts);
7698         ok(info->fInhibitPolicyMapping,
7699          "expected implicit mapping = TRUE\n");
7700         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7701          info->dwInhibitPolicyMappingSkipCerts);
7702         LocalFree(info);
7703     }
7704     }
7705 }
7706
7707 /* Free *pInfo with HeapFree */
7708 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7709 {
7710     BOOL ret;
7711     DWORD size = 0;
7712     HCRYPTKEY key;
7713
7714     /* This crashes
7715     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7716      */
7717     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7718     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7719      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7720     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7721      &size);
7722     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7723      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7724     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7725      NULL, &size);
7726     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7727      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7728     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7729      0, NULL, NULL, &size);
7730     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7731      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7732     /* Test with no key */
7733     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7734      0, NULL, NULL, &size);
7735     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7736      GetLastError());
7737     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7738     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7739     if (ret)
7740     {
7741         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7742          NULL, 0, NULL, NULL, &size);
7743         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7744         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7745         if (*pInfo)
7746         {
7747             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7748              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7749             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7750              GetLastError());
7751             if (ret)
7752             {
7753                 /* By default (we passed NULL as the OID) the OID is
7754                  * szOID_RSA_RSA.
7755                  */
7756                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7757                  "Expected %s, got %s\n", szOID_RSA_RSA,
7758                  (*pInfo)->Algorithm.pszObjId);
7759             }
7760         }
7761     }
7762     CryptDestroyKey(key);
7763 }
7764
7765 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7766  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7767  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7768  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7769  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7770  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7771  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7772  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7773  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7774  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7775  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7776  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7777  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7778  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7779  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7780  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7781  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7782  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7783  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7784  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7785  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7786  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7787  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7788  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7789  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7790
7791 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7792 {
7793     BOOL ret;
7794     HCRYPTKEY key;
7795     PCCERT_CONTEXT context;
7796     DWORD dwSize;
7797     ALG_ID ai;
7798
7799     /* These crash
7800     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7801     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7802     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7803     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7804      NULL);
7805      */
7806     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7807     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7808      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7809     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7810     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7811      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7812     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7813      &key);
7814     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7815      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7816
7817     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7818     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7819      &key);
7820     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7821
7822     dwSize = sizeof(ai);
7823     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7824     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7825     if(ret)
7826     {
7827       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7828       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7829     }
7830
7831     CryptDestroyKey(key);
7832
7833     /* Repeat with forced algorithm */
7834     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7835      &key);
7836     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7837
7838     dwSize = sizeof(ai);
7839     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7840     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7841     if(ret)
7842     {
7843       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7844       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7845     }
7846
7847     CryptDestroyKey(key);
7848
7849     /* Test importing a public key from a certificate context */
7850     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7851      sizeof(expiredCert));
7852     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7853      GetLastError());
7854     if (context)
7855     {
7856         ok(!strcmp(szOID_RSA_RSA,
7857          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7858          "Expected %s, got %s\n", szOID_RSA_RSA,
7859          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7860         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7861          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7862         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7863         CryptDestroyKey(key);
7864         CertFreeCertificateContext(context);
7865     }
7866 }
7867
7868 static const char cspName[] = "WineCryptTemp";
7869
7870 static void testPortPublicKeyInfo(void)
7871 {
7872     HCRYPTPROV csp;
7873     BOOL ret;
7874     PCERT_PUBLIC_KEY_INFO info = NULL;
7875
7876     /* Just in case a previous run failed, delete this thing */
7877     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7878      CRYPT_DELETEKEYSET);
7879     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7880      CRYPT_NEWKEYSET);
7881
7882     testExportPublicKey(csp, &info);
7883     testImportPublicKey(csp, info);
7884
7885     HeapFree(GetProcessHeap(), 0, info);
7886     CryptReleaseContext(csp, 0);
7887     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7888      CRYPT_DELETEKEYSET);
7889 }
7890
7891 START_TEST(encode)
7892 {
7893     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7894      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7895     HMODULE hCrypt32;
7896     DWORD i;
7897
7898     hCrypt32 = GetModuleHandleA("crypt32.dll");
7899     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7900     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7901     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7902     {
7903         win_skip("CryptDecodeObjectEx() is not available\n");
7904         return;
7905     }
7906
7907     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7908     {
7909         test_encodeInt(encodings[i]);
7910         test_decodeInt(encodings[i]);
7911         test_encodeEnumerated(encodings[i]);
7912         test_decodeEnumerated(encodings[i]);
7913         test_encodeFiletime(encodings[i]);
7914         test_decodeFiletime(encodings[i]);
7915         test_encodeName(encodings[i]);
7916         test_decodeName(encodings[i]);
7917         test_encodeUnicodeName(encodings[i]);
7918         test_decodeUnicodeName(encodings[i]);
7919         test_encodeNameValue(encodings[i]);
7920         test_decodeNameValue(encodings[i]);
7921         test_encodeUnicodeNameValue(encodings[i]);
7922         test_decodeUnicodeNameValue(encodings[i]);
7923         test_encodeAltName(encodings[i]);
7924         test_decodeAltName(encodings[i]);
7925         test_encodeOctets(encodings[i]);
7926         test_decodeOctets(encodings[i]);
7927         test_encodeBits(encodings[i]);
7928         test_decodeBits(encodings[i]);
7929         test_encodeBasicConstraints(encodings[i]);
7930         test_decodeBasicConstraints(encodings[i]);
7931         test_encodeRsaPublicKey(encodings[i]);
7932         test_decodeRsaPublicKey(encodings[i]);
7933         test_encodeSequenceOfAny(encodings[i]);
7934         test_decodeSequenceOfAny(encodings[i]);
7935         test_encodeExtensions(encodings[i]);
7936         test_decodeExtensions(encodings[i]);
7937         test_encodePublicKeyInfo(encodings[i]);
7938         test_decodePublicKeyInfo(encodings[i]);
7939         test_encodeCertToBeSigned(encodings[i]);
7940         test_decodeCertToBeSigned(encodings[i]);
7941         test_encodeCert(encodings[i]);
7942         test_decodeCert(encodings[i]);
7943         test_encodeCRLDistPoints(encodings[i]);
7944         test_decodeCRLDistPoints(encodings[i]);
7945         test_encodeCRLIssuingDistPoint(encodings[i]);
7946         test_decodeCRLIssuingDistPoint(encodings[i]);
7947         test_encodeCRLToBeSigned(encodings[i]);
7948         test_decodeCRLToBeSigned(encodings[i]);
7949         test_encodeEnhancedKeyUsage(encodings[i]);
7950         test_decodeEnhancedKeyUsage(encodings[i]);
7951         test_encodeAuthorityKeyId(encodings[i]);
7952         test_decodeAuthorityKeyId(encodings[i]);
7953         test_encodeAuthorityKeyId2(encodings[i]);
7954         test_decodeAuthorityKeyId2(encodings[i]);
7955         test_encodeAuthorityInfoAccess(encodings[i]);
7956         test_decodeAuthorityInfoAccess(encodings[i]);
7957         test_encodeCTL(encodings[i]);
7958         test_decodeCTL(encodings[i]);
7959         test_encodePKCSContentInfo(encodings[i]);
7960         test_decodePKCSContentInfo(encodings[i]);
7961         test_encodePKCSAttribute(encodings[i]);
7962         test_decodePKCSAttribute(encodings[i]);
7963         test_encodePKCSAttributes(encodings[i]);
7964         test_decodePKCSAttributes(encodings[i]);
7965         test_encodePKCSSMimeCapabilities(encodings[i]);
7966         test_decodePKCSSMimeCapabilities(encodings[i]);
7967         test_encodePKCSSignerInfo(encodings[i]);
7968         test_decodePKCSSignerInfo(encodings[i]);
7969         test_encodeCMSSignerInfo(encodings[i]);
7970         test_decodeCMSSignerInfo(encodings[i]);
7971         test_encodeNameConstraints(encodings[i]);
7972         test_decodeNameConstraints(encodings[i]);
7973         test_encodePolicyQualifierUserNotice(encodings[i]);
7974         test_decodePolicyQualifierUserNotice(encodings[i]);
7975         test_encodeCertPolicies(encodings[i]);
7976         test_decodeCertPolicies(encodings[i]);
7977         test_encodeCertPolicyMappings(encodings[i]);
7978         test_decodeCertPolicyMappings(encodings[i]);
7979         test_encodeCertPolicyConstraints(encodings[i]);
7980         test_decodeCertPolicyConstraints(encodings[i]);
7981     }
7982     testPortPublicKeyInfo();
7983 }